java:構建ImageInputStream利用ImageReader對記憶體位元組流進行影象解碼
java提供了一個非常方便的影象工具類javax.imageio.ImageIO
,用它的javax.imageio.ImageIO.read
方法可以很方便的將一個影象檔案進行解碼。
javax.imageio.ImageIO.read
方法有多個過載方法,支援File,InputStream,URL
等引數,但這些方法有可能會在解碼過程中使用檔案系統做cache,具體原因這裡不展開講了,好長,你要研究java原始碼。
有了磁碟IO勢必會影響解碼效率,這在效能敏感的應用環境是不能容忍的,
如果要實現完全基於記憶體的影象解碼,就不能簡單使用javax.imageio.ImageIO.read
方法。需要利用javax.imageio.stream.MemoryCacheImageInputStream
package test;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.MemoryCacheImageInputStream;
import org.junit.Test;
public class TestReadMemoryImage {
@Test
public final void testreadMemoryImage() throws IllegalArgumentException, IOException {
// 將影象檔案加讀取到記憶體成為位元組陣列
byte[] imgBytes = readBytes(TestReadMemoryImage.class.getResourceAsStream("/images/he049.jpg" ));
BufferedImage bufImg = readMemoryImage(imgBytes);
System.out.printf("decode success,width=%d,heigh=%d\n", bufImg.getWidth(),bufImg.getHeight());
}
@Test
public final void testreadMemoryImage1() throws IllegalArgumentException, IOException {
// 將影象檔案加讀取到記憶體成為位元組陣列
byte[] imgBytes = readBytes(TestReadMemoryImage.class.getResourceAsStream("/images/he049.jpg"));
BufferedImage bufImg = readMemoryImage1(imgBytes);
System.out.printf("decode success,width=%d,heigh=%d\n", bufImg.getWidth(),bufImg.getHeight());
}
/**
* 從記憶體位元組陣列中讀取影象
*
* @param imgBytes
* 未解碼的影象資料
* @return 返回 {@link BufferedImage}
* @throws IOException
* 當讀寫錯誤或不識別的格式時丟擲
*/
public static final BufferedImage readMemoryImage(byte[] imgBytes) throws IOException {
if (null == imgBytes || 0 == imgBytes.length)
throw new NullPointerException("the argument 'imgBytes' must not be null or empty");
// 將位元組陣列轉為InputStream,再轉為MemoryCacheImageInputStream
ImageInputStream imageInputstream = new MemoryCacheImageInputStream(new ByteArrayInputStream(imgBytes));
// 獲取所有能識別資料流格式的ImageReader物件
Iterator<ImageReader> it = ImageIO.getImageReaders(imageInputstream);
// 迭代器遍歷嘗試用ImageReader物件進行解碼
while (it.hasNext()) {
ImageReader imageReader = it.next();
// 設定解碼器的輸入流
imageReader.setInput(imageInputstream, true, true);
// 影象檔案格式字尾
String suffix = imageReader.getFormatName().trim().toLowerCase();
// 影象寬度
int width = imageReader.getWidth(0);
// 影象高度
int height = imageReader.getHeight(0);
System.out.printf("format %s,%dx%d\n", suffix, width, height);
try {
// 解碼成功返回BufferedImage物件
// 0即為對第0張影象解碼(gif格式會有多張影象),前面獲取寬度高度的方法中的引數0也是同樣的意思
return imageReader.read(0, imageReader.getDefaultReadParam());
} catch (Exception e) {
imageReader.dispose();
// 如果解碼失敗嘗試用下一個ImageReader解碼
}
}
imageInputstream.close();
// 沒有能識別此資料的影象ImageReader物件,丟擲異常
throw new IOException("unsupported image format");
}
public static final BufferedImage readMemoryImage1(byte[] imgBytes) throws IOException {
if (null == imgBytes || 0 == imgBytes.length)
throw new NullPointerException("the argument 'imgBytes' must not be null or empty");
// 將位元組陣列轉為InputStream,再轉為MemoryCacheImageInputStream
ImageInputStream imageInputstream = new MemoryCacheImageInputStream(new ByteArrayInputStream(imgBytes));
// 直接呼叫ImageIO.read方法解碼
BufferedImage bufImg = ImageIO.read(imageInputstream);
if(null==bufImg)
// 沒有能識別此資料的影象ImageReader物件,丟擲異常
throw new IOException("unsupported image format");
return bufImg;
}
/**
* 從{@link InputStream}讀取位元組陣列<br>
* 結束時會關閉{@link InputStream}<br>
* {@code in}為{@code null}時丟擲{@link NullPointerException}
*
* @param in
* @return 位元組陣列
* @throws IOException
*/
public static final byte[] readBytes(InputStream in) throws IOException {
if (null == in)
throw new NullPointerException("the argument 'in' must not be null");
try {
int buffSize = Math.max(in.available(), 1024 * 8);
byte[] temp = new byte[buffSize];
ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);
int size = 0;
while ((size = in.read(temp)) != -1) {
out.write(temp, 0, size);
}
return out.toByteArray();
} finally {
in.close();
}
}
}
程式碼中提供了兩個方法來實現記憶體解碼(readMemoryImage
和readMemoryImage1
),共同點就是都要基於byte陣列構建一個MemoryCacheImageInputStream
物件作為 ImageInputStream
。
不同點就是readMemoryImage1
方法直接使用javax.imageio.ImageIO.read(ImageInputStream stream)
方法來解碼。
而readMemoryImage
則是尋找合適的ImageReader
來實現解碼,
其實邏輯上與javax.imageio.ImageIO.read(ImageInputStream stream)
方法實現程式碼也差不多,你可以自己選擇。最終的結果都是一樣的。
相關推薦
java:構建ImageInputStream利用ImageReader對記憶體位元組流進行影象解碼
java提供了一個非常方便的影象工具類javax.imageio.ImageIO,用它的javax.imageio.ImageIO.read方法可以很方便的將一個影象檔案進行解碼。 javax.imageio.ImageIO.read方法有多個過載方法,支援F
Java利用JNI呼叫FFMpeg對h264碼流進行解碼
前期配置工作: 使用JNI呼叫: java端: package com.recon.action; public class Decode { public native String loadfile(String s); //
GA:利用GA對一元函數進行優化過程,求x∈(0,10)中y的最大值——Jason niu
title variable ati 過程 優化 mea ... http [] x = 0:0.01:10; y = x + 10*sin(5*x)+7*cos(4*x); figure plot(x, y) xlabel(‘independent variable
利用python對2012美國大選進行資料分析(四,時間處理)
1,str轉datetime 我們可以使用pd.to_datetime(series,format='%Y%m%d')將字元轉化為日期,格式為年月日。 data_vs['time'] = pd.to_datetime(data_vs['contb_receipt_dt']
Java基礎知識複習(五)-- 位元組流 && 字元流
一、位元組流 InputStream位元組輸入流 ,OutputStream位元組輸出流 ,用於以位元組的形式讀取和寫入資料 所有的資料存放在計算機中都是以數字的形式存放的。 所以字母就需要轉換為數字才能夠存放。 比如A就對應的數字65,a對應的數字97. 不同的字母和符號對應不
JAVA陣列學習之一:對一維陣列進行逆序排列
Java中的陣列必須先初始化,然後才能使用。所謂初始化,就是為陣列中的元素分配記憶體空間,併為元素賦值。 陣列的初始化方式: 動態初始化:初始化時只指定陣列長度,由系統為陣列分配初始值。 靜態初始化:
利用Python對QQ空間資料進行分析,瞭解你的QQ好友
對如下內容進行了分析: 好友發說說月份統計 好友所屬星座統計 好友手機裝置統計 好友發說說小時統計 對好友的好友進行統計 本人對於Python學習建立了一個小小的學習圈子,為各位提供了一個平臺,大家一起來討論學習Python。歡迎各位到來Python學習群:96041
EL之RF(RFC):利用RF對二分類問題進行建模並評估
EL之RF(RFC):利用RF對二分類問題進行建模並評估 輸出結果 設計思路 核心程式碼 auc = [] nTreeList = range(50, 2000, 50) for iTrees in nTreeList:
EL之RF(RFC):利用RF對多分類問題進行建模並評估(六分類+分層抽樣)
EL之RF(RFC):利用RF對多分類問題進行建模並評估(六分類+分層抽樣) 輸出結果 設計思路 核心程式碼 missCLassError = [] nTreeList = range(50, 2000, 50) for iTrees in n
EL之GB(GBC):利用GB對二分類問題進行建模並評估
EL之GB(GBC):利用GB對二分類問題進行建模並評估 輸出結果 T1、純GB演算法 T2、以RF為基學習器的GB演算法 設計思路 核心程式碼
[作業系統設定]利用IPSec對指定的ip進行訪問限制
以win2003系統為例: 操作(看圖): 1.任務:現在192.168.2.200可訪問;目的;本地禁止對其訪問 2.進入:管理工具->本地安全設定->IP安全策略 3.右鍵建立IP安全策略 4.彈出嚮導,如下圖:(一直選擇[是]或者[下一步]直至完成,
利用junit對springMVC的Controller進行測試
java.lang.NoClassDefFoundError: javax/servlet/SessionCookieConfigat org.springframework.test.context.web.AbstractGenericWebContextLoader.configureWebResou
使用java語言,利用多執行緒呼叫WebService進行資料處理
因工作原因,需要將一個表(tbA)中的所有資料,根據user_id,去請求webserive獲取相關的資料,然後插入到另外的一張表(tbB)中,供他人使用。不過這個表中的資料不少有78萬條左右,而這樣的大批量資料操作,還不能白天執行。只能在夜裡,等伺服器負荷低的時候進
利用tcpdump對安卓機頂盒進行抓包
最近遇到一個問題,詳情如下:同一檯安卓機頂盒(海思晶片 Android4.4)在同一樓層的不同位置播放同一個視訊流,結果一個能播放另一個不能播放。最終原因:不能播放的區域網路物理鏈路不一樣,符合防火牆的規則,導致機頂盒的請求被攔截了。解決思路:抓包分析步驟2、利用adb命令將
利用echarts對pm2.5資料進行視覺化處理
echarts是百度提供的資料視覺化js外掛,功能強大,提供各種基本的圖表(尤其世界以及中國各種地圖,方便時空資料的視覺化);具體看參考http://echarts.baidu.com/ 。 本文主要嘗試了四個功能 1. 滑鼠放在地圖某個區上時顯示該區在所給資料
java向檔案中寫入內容,位元組流,字元流,緩衝,複製檔案,設定字元編碼 例項
package com.liuxin.test; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.
利用metasploit對ms10-018漏洞進行攻擊例項
攻擊機:VMware 環境下Kali-liunx靶機:VMware環境下Windows xp1、首先進入metasploit2、用search命令來尋找ms10-018的可用攻擊模組3、我們使用第一個使用use命令,複製模組名稱4、使用show options 命令來檢視可用
教你如何利用threejs對3D模型面板進行DIY
一步一步教你如何利用threejs載入gltf模型來實現DIY換膚功能。 ### 模型準備 - ***模型製作*** 模型可以通過網上下載,也可以自己通過c4d、maya、blender等模型製作軟體得到。這裡就不敘述有關模型製作的問題,本文中會在blender進行模型的有關設定。 - ***模型
C#對字符串進行編碼解碼
odin div 字符串 編碼解碼 odi encode cnblogs 進行 viewbag 以UTF8編碼格式為例: 1 //編碼 2 ViewBag.FileURL = HttpUtility.UrlEncode(UriString, Encoding.UTF8);
JavaWeb基礎 URLDecoder.decode 對字符串進行URL解碼
clip logs system java.net chrom block ide cnblogs .com 禮悟: 好好學習多思考,尊師重道存感恩。葉見尋根三二一,江河湖海同一體。 虛懷若谷良心主,願行無悔給最苦。讀書鍛煉強身心,誠勸且行且珍惜。