日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

图片播放技术总结

發(fā)布時(shí)間:2023/12/29 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图片播放技术总结 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1 概述

由于工作的項(xiàng)目上的需求,需要在瀏覽器上不間斷的播放圖片,即像播放視頻一樣播放圖片。

后端支持采用Java實(shí)現(xiàn),需要用Java編寫(xiě)一個(gè)Http服務(wù)器,并提供WebSocket服務(wù)。前后端通過(guò)Http鏈接或WebSocket提供圖片瀏覽服務(wù),前端采用JS輪詢(xún)或WebSocket推送的方式獲取圖片,瀏覽器顯示圖片有兩種方式:一種是采用連續(xù)切換圖片源,實(shí)現(xiàn)播放效果;另一種采用將圖片畫(huà)在canvas上面,實(shí)現(xiàn)播放。

要完成這個(gè)功能涉及到以下技術(shù):

  • Http服務(wù)器的實(shí)現(xiàn)
  • 高速的讀文件
  • WebSocket原理及實(shí)現(xiàn)
  • 基于瀏覽器pull方式的http資源獲取
  • 基于服務(wù)器端push方式的http資源獲取
  • JS播放圖片幀的性能

2 技術(shù)分析

2.1 Http服務(wù)器的實(shí)現(xiàn)

實(shí)現(xiàn)HTTP服務(wù)器比較容易,實(shí)現(xiàn)方式也有如下多種:

  • 基于jdk中com.sun包下面的HttpServer來(lái)實(shí)現(xiàn)。(不推薦,com.sun不在java規(guī)范內(nèi),jdk升級(jí)可能會(huì)不兼容)
  • 基于jetty或tomcat的嵌入式包來(lái)實(shí)現(xiàn)。此方式基于Servlet規(guī)范來(lái)實(shí)現(xiàn)的,較簡(jiǎn)單且易于理解。
  • 基于netty的方式實(shí)現(xiàn)。性能好,需要對(duì)NIO有了解,編程難度相對(duì)大一些。
  • 基于vert.x的實(shí)現(xiàn)。這種方式底層還是采用netty實(shí)現(xiàn),較簡(jiǎn)單,但是也需要熟悉vert.x的編程模型。

我們采用jetty的方式實(shí)現(xiàn),基于servlet3.0規(guī)范,可以支持異步請(qǐng)求方式。代碼如下:

public static void main(String[] args){Server server = new Server();ServerConnector connector = new ServerConnector(server);connector.setPort(8080);server.addConnector(connector);ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);context.setContextPath("/");context.addServlet(new ServletHolder(new HelloServlet()), "/hello"); server.setHandler(context);try {// Initialize javax.websocket layerServerContainer wscontainer = WebSocketServerContainerInitializer.configureContext(context);// Add WebSocket endpoint to javax.websocket layerwscontainer.addEndpoint(EventSocket.class);server.start();server.dump(System.err);server.join();} catch (Throwable t){t.printStackTrace(System.err);} }

2.2 高速的讀文件

關(guān)于Java高速讀取文件可參考這篇文章:How to read files quickly
這篇文章得出四個(gè)結(jié)論:

  • 為了減少I(mǎi)/O操作,每次應(yīng)該讀一個(gè)byte數(shù)組,而不是一個(gè)byte字節(jié),8K的byte數(shù)組就是一個(gè)好的選擇。
  • 為了減少方法調(diào)用的開(kāi)銷(xiāo),每次應(yīng)該獲取一個(gè)byte數(shù)組的數(shù)據(jù),而不是一個(gè)byte字節(jié)。
  • 為了減少線(xiàn)程同步鎖的開(kāi)銷(xiāo),要么減少線(xiàn)程同步方法的調(diào)用,要么采用非線(xiàn)程安全的類(lèi),如:FileChannel 和MappedByteBuffer。
  • 為了減少在JVM/OS、internal buffers和應(yīng)用程序數(shù)組之間的數(shù)據(jù)拷貝,要么使用帶有內(nèi)存映射的FileChannel類(lèi),要么使用a direct or wrapped array ByteBuffer.

下面提高兩種高速讀取文件方法:

for (String filePath : fileList){try(FileChannel ch = new RandomAccessFile(filePath, "r").getChannel()){int size = (int) ch.size();MappedByteBuffer buf = ch.map(MapMode.READ_ONLY, 0, size);// 處理buf....} catch (IOException e) {e.printStackTrace();} } for (String filePath : fileList){try (SeekableByteChannel sbc = Files.newByteChannel(Paths.get(filePath), StandardOpenOption.READ)) {ByteBuffer buf = ByteBuffer.allocate(10);// Read the bytes with the proper encoding for this platform. If// you skip this step, you might see something that looks like// Chinese characters when you expect Latin-style characters.//String encoding = System.getProperty("file.encoding");while (sbc.read(buf) > 0) {buf.rewind();// 處理buf...//System.out.print(Charset.forName(encoding).decode(buf));buf.flip();}} catch (IOException x) {System.out.println("caught exception: " + x);} }

2.3 WebSocket原理及實(shí)現(xiàn)

WebSocket的原理以及與Http區(qū)別可以參考:WebSocket與http的區(qū)別,以及它的原理,總體來(lái)說(shuō),原理及區(qū)別如下:

  • WebSocket和Http協(xié)議沒(méi)有太大的關(guān)系,WS只是借助Http實(shí)現(xiàn)了第一次握手,之后從http協(xié)議upgrade為ws://協(xié)議。
  • WS是持久性連接(類(lèi)似socket),而HTTP的短連接、長(zhǎng)連接都不是持久的。
  • WS協(xié)議是支持全雙工的,可以pull,亦可以push。

用Java實(shí)現(xiàn)WebSocket服務(wù)端:

@ClientEndpoint @ServerEndpoint(value="/events/") public class EventSocket{private static int DEFAULT_BUFFER_SIZE = 128 * 1024;// 8192private byte[] bytes;@OnOpenpublic void onWebSocketConnect(Session session, EndpointConfig config) {session.setMaxBinaryMessageBufferSize(DEFAULT_BUFFER_SIZE);}@OnMessagepublic void onWebSocketText(Session session, String message) throws Exception{System.out.println("Received TEXT message: " + message);bytes = ... // 讀取圖片文件字節(jié)// 發(fā)送圖片文件session.getAsyncRemote().sendBinary( ByteBuffer.wrap( this.bytes ) );}@OnClosepublic void onWebSocketClose(Session session, CloseReason reason){System.out.println("Socket Closed: " + reason);}@OnErrorpublic void onWebSocketError(Session session, Throwable cause){cause.printStackTrace(System.err);} }

2.4 瀏覽器并發(fā)請(qǐng)求與長(zhǎng)連接

瀏覽器請(qǐng)求一般都是拉取服務(wù)器的資源,而請(qǐng)求方式分為短連接和長(zhǎng)連接兩種,這篇文章介紹很清楚:HTTP的長(zhǎng)連接和短連接

瀏覽器對(duì)后端資源的請(qǐng)求都是并發(fā)的執(zhí)行的,不同的瀏覽器并發(fā)連接數(shù)不同。現(xiàn)在大多數(shù)瀏覽器都支持http1.1協(xié)議,默認(rèn)都會(huì)開(kāi)啟keep-alive,支持長(zhǎng)連接。在瀏覽器對(duì)后端的資源發(fā)出請(qǐng)求,在開(kāi)啟keep-alive情況下,都會(huì)復(fù)用連接通道。如果是不間斷的下載圖片,應(yīng)該使用的是長(zhǎng)連接通道復(fù)用功能。

2.5 Web服務(wù)器Push技術(shù)

實(shí)現(xiàn)服務(wù)器端Push有以下幾種方式:

  • Ajax輪詢(xún)。采用setInterval方法不停的調(diào)用
  • Ajax長(zhǎng)輪詢(xún)。俗稱(chēng)Comet方式,不需要重復(fù)建立連接,沒(méi)有響應(yīng)就一直等,等到才關(guān)閉連接。
  • WebSocket
  • server-sent-events

Ajax輪詢(xún)?cè)磉€是pull的方式,不算真正的push,但是對(duì)一些老版本的瀏覽器是適用的。WebSocket優(yōu)點(diǎn)是支持全雙工、可跨域。server-sent-server實(shí)現(xiàn)簡(jiǎn)單,但只支持server到client單向傳輸,且IE系列都不支持。詳細(xì)內(nèi)容參考: web服務(wù)器端推送技術(shù)簡(jiǎn)介

除了上面一些方法外,還有一些其他方式,如:Flash XML Socket, Java Applet等非主流。

而在本案例中,如果采用WebSocket傳送圖片,可實(shí)現(xiàn)真正的服務(wù)器端不間斷的推送圖片數(shù)據(jù),但是如果要實(shí)現(xiàn)并發(fā)傳送,必須自己在瀏覽器端來(lái)實(shí)現(xiàn),否則,僅僅單連接的情況下不一定比瀏覽器的并發(fā)連接快。

2.6 JS播放圖片幀的性能

JS播放圖片有多種方式,如:

  • 采用標(biāo)簽,不停改變img的src屬性,實(shí)現(xiàn)播放。
  • 采用Html5的Canvas,將Image對(duì)象畫(huà)在Canvas上,實(shí)現(xiàn)播放。
  • 將圖片設(shè)置為Div的背景,不停的更換背景,實(shí)現(xiàn)播放。

采用標(biāo)簽方式實(shí)現(xiàn)如下:

(function() {var i = 0;var pics = [ "andy_white.jpg", "andy_black.jpg" ];var el = document.getElementById('img_to_flip'); // el doesn't changefunction toggle() {el.src = pics[i]; // set the imagei = (i + 1) % pics.length; // update the counter}setInterval(toggle, 2000); })();

這種方式下瀏覽器CPU占用率非常高,在IE11和Chrome下,i3的CPU(T440P)占用都在60%左右,內(nèi)存占用較少,大約在100M左右。CPU的消耗主要在瀏覽器對(duì)圖片的渲染上。
用Canvas替代標(biāo)簽,CPU占用方面,IE11仍然占用那么高,Chrome能降一半。更換背景的方式?jīng)]有實(shí)驗(yàn)。基于以上,采用Canvas的方式是一種比較好的選擇。

aaaa


bbbb

轉(zhuǎn)載于:https://www.cnblogs.com/gjhuai/p/6807492.html

總結(jié)

以上是生活随笔為你收集整理的图片播放技术总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。