一文帶你掌握J(rèn)ava ImageIO類(lèi)
一、ImageIO 的基礎(chǔ)知識(shí)
1.1 ImageIO 的作用
ImageIO 是 Java 標(biāo)準(zhǔn)庫(kù)提供的一個(gè)類(lèi),它提供了讀取和寫(xiě)入多種常見(jiàn)圖像格式的功能。開(kāi)發(fā)者可以使用 ImageIO 類(lèi)快速、便捷地讀取和寫(xiě)入圖像,而無(wú)需關(guān)心底層的細(xì)節(jié)。
1.2 ImageIO 的特點(diǎn)
ImageIO 支持的圖像格式非常廣泛,包括 JPEG、PNG、BMP、GIF 等常見(jiàn)格式,同時(shí)也支持 TIFF、ICO、WBMP、JPEG 2000 等更加少見(jiàn)的格式。這使得開(kāi)發(fā)者可以方便地讀取和寫(xiě)入多種不同格式的圖像。
ImageIO 還支持靈活的、可配置的圖片格式轉(zhuǎn)換。例如,可以將一張 JPEG 格式的圖像讀取到內(nèi)存中,然后將其保存為 PNG 格式的圖像。此外,ImageIO 還支持高級(jí)的圖像處理操作,如裁剪、旋轉(zhuǎn)、縮放、反轉(zhuǎn)、鏡像等。
1.3 ImageIO 的使用環(huán)境
ImageIO 是 Java 標(biāo)準(zhǔn)庫(kù)中的一個(gè)類(lèi),因此不需要額外的庫(kù)或安裝,可以直接在 Java 應(yīng)用程序中使用。它支持 Java SE 6 及以上版本,并且可以運(yùn)行在所有常見(jiàn)的操作系統(tǒng)上。
1.4 ImageIO 的基本使用方法
使用 ImageIO 類(lèi)讀取和寫(xiě)入圖像的基本流程如下:
- 通過(guò) ImageIO 類(lèi)的靜態(tài)方法 read() 或者 write() 方法獲取圖片輸入輸出流;
- 創(chuàng)建 ImageInputStream 或者 ImageOutputStream;
- 讀/寫(xiě)圖像。
例如,讀取一張 JPEG 格式的圖片,代碼如下:
String imageFilePath = "image.jpg"; try { InputStream inputStream = new FileInputStream(new File(imageFilePath)); BufferedImage bufferedImage = ImageIO.read(inputStream); // 圖像處理邏輯 } catch (IOException e) { e.printStackTrace(); }
上述代碼通過(guò) FileInputStream 打開(kāi)文件輸入流,然后通過(guò) ImageIO.read() 方法讀取圖像數(shù)據(jù),最后對(duì)圖像進(jìn)行了處理操作。
下面我們將詳細(xì)介紹 ImageIO 類(lèi)的各個(gè)方面,包括讀取、寫(xiě)入、壓縮、格式轉(zhuǎn)換以及高級(jí)操作等。
二、ImageIO 的讀取操作
2.1 ImageIO 的 read() 方法
ImageIO 的 read() 方法是最常見(jiàn)的讀取圖像的方式,它有多個(gè)重載形式,可以用來(lái)讀取 File、InputStream、URL 和 ImageInputStream 等多種類(lèi)型的輸入流。此外,ImageIO 還支持從 byte 數(shù)組讀取或者從任意 SeekableStream 中讀取文件。
例如,通過(guò) ImageIO 的 read() 方法從本地文件讀取一張圖片:
String imageFilePath = "image.jpg"; try { BufferedImage bufferedImage = ImageIO.read(new File(imageFilePath)); // 圖像處理邏輯 } catch (IOException e) { e.printStackTrace(); }
read() 方法返回了一個(gè) BufferedImage 對(duì)象,開(kāi)發(fā)者可以對(duì)這個(gè)對(duì)象進(jìn)行各種操作,如裁剪、旋轉(zhuǎn)、縮放等。注意:當(dāng)讀取的圖像不是 RGB 格式時(shí),返回的 BufferedImage 對(duì)象可能為 null。
2.2 以 Byte 數(shù)組形式讀取圖像
有些場(chǎng)景下,開(kāi)發(fā)者需要將圖片數(shù)據(jù)保存在內(nèi)存中,然后再進(jìn)行處理。ImageIO 的 read() 方法提供了一個(gè)重載形式,可以將圖像數(shù)據(jù)讀取到 byte 數(shù)組中,示例代碼如下:
String imageFilePath = "image.jpg"; try { File file = new File(imageFilePath); BufferedImage bufferedImage = ImageIO.read(file); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ImageIO.write(bufferedImage, "jpg", byteArrayOutputStream); byte[] bytes = byteArrayOutputStream.toByteArray(); // 處理字節(jié)數(shù)組中的圖像 } catch (IOException e) { e.printStackTrace(); }
在上述代碼中,首先使用 ImageIO.read() 方法將圖片讀取到內(nèi)存中,并得到了一個(gè) BufferedImage 對(duì)象。然后,使用 ImageIO.write() 方法將 BufferedImage 對(duì)象寫(xiě)入到 ByteArrayOutputStream 中,最終得到了字節(jié)數(shù)組形式的圖像數(shù)據(jù)。
2.3 指定圖像格式
ImageIO 的 read() 方法可以自動(dòng)識(shí)別常見(jiàn)的圖像格式,但有時(shí)候需要指定特定的格式。通過(guò) ImageIO 的 getReaderFormatNames() 方法可以查看支持的格式列表,示例代碼如下:
String[] formatNames = ImageIO.getReaderFormatNames(); for (String format : formatNames) { System.out.println(format); }
如果要指定讀取的格式,可以使用 ImageIO 的 getImageReadersByFormatName() 方法指定,例如:
File file = new File("image.xx"); Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("xxx"); try { ImageReader reader = readers.next(); ImageInputStream inputStream = ImageIO.createImageInputStream(file); reader.setInput(inputStream); BufferedImage image = reader.read(0); // 處理讀取的圖像 } catch (IOException e) { e.printStackTrace(); }
在上述代碼中,getImageReadersByFormatName() 方法傳入的參數(shù)是指定的圖像格式名,然后通過(guò) Iterator 獲取到 ImageReader 對(duì)象,再使用 ImageIO.createImageInputStream() 方法創(chuàng)建 ImageInputStream 對(duì)象,并通過(guò) setInput() 方法設(shè)置輸入源。最后通過(guò) reader.read() 方法讀取圖像。
三、ImageIO 的寫(xiě)入操作
3.1 ImageIO 的 write() 方法
ImageIO 的 write() 方法是寫(xiě)入圖像的主要方法,它可以將 BufferedImage 對(duì)象寫(xiě)入到文件或者輸出流中。除此之外,ImageIO 還提供了其他的方法來(lái)指定寫(xiě)出的格式和壓縮質(zhì)量等參數(shù)。
下面是一個(gè)將 BufferedImage 寫(xiě)入 PNG 格式的簡(jiǎn)單示例:
BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); try { ImageIO.write(image, "png", new File("output.png")); } catch (IOException e) { e.printStackTrace(); }
在上述代碼中,使用 ImageIO.write() 方法將 BufferedImage 對(duì)象寫(xiě)入到本地文件 output.png 中。
3.2 指定圖像格式
與讀取圖像類(lèi)似,ImageIO 的 write() 方法默認(rèn)會(huì)根據(jù)擴(kuò)展名或者其他信息自動(dòng)識(shí)別輸出的圖片格式。但是有些場(chǎng)景下需要手動(dòng)指定輸出的圖像格式,可通過(guò)如下方式進(jìn)行設(shè)置:
BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); try { File file = new File("output.xx"); ImageWriter writer = ImageIO.getImageWritersByFormatName("xxx").next(); ImageOutputStream outputStream = ImageIO.createImageOutputStream(file); writer.setOutput(outputStream); writer.write(image); outputStream.close(); } catch (Exception e) { e.printStackTrace(); }
在上述代碼中,getImageWritersByFormatName() 方法傳入指定的圖像格式名,然后通過(guò) ImageWriter 對(duì)象設(shè)置 ImageOutputStream,最后通過(guò) write() 方法寫(xiě)入圖像。
3.3 指定壓縮質(zhì)量
在寫(xiě)入圖像時(shí),ImageIO 還可以控制輸出的壓縮質(zhì)量,從而控制輸出圖像文件的大小。不過(guò)需要注意的是,并非所有的圖像格式都支持壓縮。目前只有 JPEG 和 PNG 格式支持壓縮功能。
下面是一個(gè)將 BufferedImage 寫(xiě)入 JPG 格式并指定壓縮質(zhì)量的示例:
BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); try { File file = new File("output.jpg"); // 獲取 JPEG 格式的 ImageWriter ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next(); // 設(shè)置輸出流 ImageOutputStream outputStream = ImageIO.createImageOutputStream(file); writer.setOutput(outputStream); // 設(shè)置壓縮參數(shù) JPEGImageWriteParam param = (JPEGImageWriteParam) writer.getDefaultWriteParam(); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality(0.8f); // 寫(xiě)入圖像 writer.write(null, new IIOImage(image, null, null), param); outputStream.close(); } catch (Exception e) { e.printStackTrace(); }
在上述代碼中,首先從 ImageIO 中獲取 JPEG 格式的 ImageWriter 對(duì)象,然后設(shè)置輸出流和壓縮參數(shù)。其中,setCompressionQuality() 方法用于設(shè)置壓縮質(zhì)量,值范圍為 0.0~1.0,其中 1.0 表示不壓縮,0.0 表示最大壓縮。
3.4 指定保存位置
如果需要將 BufferedImage 對(duì)象寫(xiě)入到指定的文件目錄下,可以使用 ImageIO 的 write() 方法進(jìn)行操作。下面是一個(gè)將 BufferedImage 寫(xiě)入本地文件的示例:
BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); try { File file = new File("output.png"); ImageIO.write(image, "png", file); } catch (Exception e) { e.printStackTrace(); }
需要注意的是,write() 方法不支持壓縮參數(shù)設(shè)置,如果需要控制輸出文件大小,需要使用上述的 ImageWriter 方式。
四、ImageIO 的格式轉(zhuǎn)換
在實(shí)際開(kāi)發(fā)中,經(jīng)常需要將圖像從一種格式轉(zhuǎn)換成另一種格式。ImageIO 提供的格式轉(zhuǎn)換功能非常靈活,可以通過(guò)如下代碼片段實(shí)現(xiàn):
BufferedImage srcImage = ImageIO.read(new File("input.jpg")); File outputFile = new File("output.png"); // 獲取 png 格式的 ImageWriter ImageWriter writer = ImageIO.getImageWritersByFormatName("png").next(); // 設(shè)置輸出流 ImageOutputStream outputStream = ImageIO.createImageOutputStream(outputFile); writer.setOutput(outputStream); // 寫(xiě)入圖像 writer.write(null, new IIOImage(srcImage, null, null), null); outputStream.close();
在上述代碼中,首先使用 ImageIO.read() 方法讀取 JPEG 格式的圖像,然后通過(guò) getImageWritersByFormatName() 方法獲取 PNG 格式的 ImageWriter 對(duì)象。接著創(chuàng)建 ImageOutputStream 對(duì)象,并寫(xiě)入轉(zhuǎn)換后的 PNG 格式圖像。
需要注意的是,有些格式轉(zhuǎn)換可能會(huì)導(dǎo)致圖像信息的丟失,例如將 24-bit 的 RGB 圖像轉(zhuǎn)換成 8-bit 的 GIF 圖像,會(huì)導(dǎo)致顏色數(shù)量減少,從而造成圖像質(zhì)量下降。
五、ImageIO 的高級(jí)操作
除了基本的格式讀取、寫(xiě)入和轉(zhuǎn)換外,ImageIO 還提供了一些高級(jí)的圖像處理操作,如裁剪、旋轉(zhuǎn)、縮放、反轉(zhuǎn)、鏡像等。下面簡(jiǎn)單介紹一下這些操作。
5.1 裁剪圖像
通過(guò) ImageIO.read() 方法讀取的 BufferedImage 對(duì)象支持裁剪功能??梢酝ㄟ^(guò)調(diào)用 getSubimage() 方法獲取指定區(qū)域的子圖像。例如:
BufferedImage srcImage = ImageIO.read(new File("input.jpg")); BufferedImage destImage = srcImage.getSubimage(10, 10, 100, 100);
5.2 旋轉(zhuǎn)圖像
ImageIO 也支持對(duì)圖像進(jìn)行旋轉(zhuǎn)操作??梢酝ㄟ^(guò) AffineTransform 類(lèi)來(lái)實(shí)現(xiàn)圖像的旋轉(zhuǎn)變換。
BufferedImage srcImage = ImageIO.read(new File("input.jpg")); double radian = Math.toRadians(30); // 旋轉(zhuǎn)角度為 30 度 AffineTransform transform = new AffineTransform(); transform.rotate(radian, srcImage.getWidth() / 2, srcImage.getHeight() / 2); AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR); BufferedImage destImage = op.filter(srcImage, null);
在上述代碼中,radian 變量表示旋轉(zhuǎn)的角度,AffineTransform 類(lèi)用于創(chuàng)建旋轉(zhuǎn)變換,AffineTransformOp 類(lèi)用于將變換應(yīng)用到圖像上。
5.3 縮放圖像
縮放圖像同樣是 ImageIO 的高級(jí)操作之一??梢酝ㄟ^(guò) AffineTransform 類(lèi)來(lái)實(shí)現(xiàn)圖像的縮放變換。
BufferedImage srcImage = ImageIO.read(new File("input.jpg")); AffineTransform transform = new AffineTransform(); double scale = 0.5; // 圖像縮小一倍 transform.scale(scale, scale); AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR); BufferedImage destImage = op.filter(srcImage, null);
在上述代碼中,通過(guò) AffineTransform 的 scale() 方法設(shè)置縮放比例,AffineTransformOp 類(lèi)用于將變換應(yīng)用到圖像上。
5.4 反轉(zhuǎn)圖像
對(duì)于需要水平或垂直翻轉(zhuǎn)的圖像,ImageIO 提供了如下方式實(shí)現(xiàn):
``` // 讀取輸入圖像(示例中為名為 input.png 的圖像) BufferedImage srcImage = ImageIO.read(new File("input.png")); // 水平鏡像 AffineTransform transform = new AffineTransform(-1, 0, 0, 1, srcImage.getWidth(), 0); AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR); BufferedImage horizontalFlipped = op.filter(srcImage, null); // 垂直鏡像 transform = new AffineTransform(1, 0, 0, -1, 0, srcImage.getHeight()); op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR); BufferedImage verticalFlipped = op.filter(srcImage, null); // 上下顛倒 transform = new AffineTransform(-1, 0, 0, -1, srcImage.getWidth(), srcImage.getHeight()); op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR); BufferedImage upsideDown = op.filter(srcImage, null); // 保存結(jié)果圖像(保存為 PNG 格式的文件) ImageIO.write(horizontalFlipped, "png", new File("horizontal.png")); ImageIO.write(verticalFlipped, "png", new File("vertical.png")); ImageIO.write(upsideDown, "png", new File("upside_down.png"));
5.5 鏡像圖像
對(duì)于需要鏡像的圖像,ImageIO 提供了如下方式實(shí)現(xiàn):
BufferedImage srcImage = ImageIO.read(new File("input.jpg")); // 水平鏡像 AffineTransform transform = new AffineTransform(-1, 0, 0, 1, srcImage.getWidth(), 0); // 垂直鏡像 AffineTransform transform = new AffineTransform(1, 0, 0, -1, 0, srcImage.getHeight());
在上述代碼中,水平鏡像通過(guò)將 x 軸翻轉(zhuǎn)并沿 y 軸平移一段距離實(shí)現(xiàn),垂直鏡像通過(guò)將 y 軸翻轉(zhuǎn)并沿 x 軸平移一段距離實(shí)現(xiàn)。
5.6 組合操作
同時(shí)進(jìn)行多個(gè)圖像變換時(shí),可以通過(guò) AffineTransform 中的 concatenate() 方法,將多個(gè)變換組合到一起進(jìn)行處理。例如:
BufferedImage srcImage = ImageIO.read(new File("input.jpg")); AffineTransform transform1 = new AffineTransform(); AffineTransform transform2 = new AffineTransform(); double scale = 0.5; transform1.scale(scale, scale); transform2.translate(50, 50); transform1.concatenate(transform2); // 將兩個(gè)變換組合在一起 AffineTransformOp op = new AffineTransformOp(transform1, AffineTransformOp.TYPE_BILINEAR); BufferedImage destImage = op.filter(srcImage, null);
在上述代碼中,首先創(chuàng)建兩個(gè)不同的 AffineTransform 對(duì)象,一個(gè)用于縮放,一個(gè)用于平移,然后將其組合在一起。注意,組合時(shí)要先進(jìn)行平移變換,再進(jìn)行縮放變換,否則會(huì)產(chǎn)生錯(cuò)誤的結(jié)果。
六、注意事項(xiàng)
在使用 ImageIO 時(shí),需要注意以下幾點(diǎn):
- 避免頻繁的讀寫(xiě)文件,選擇合適的內(nèi)存緩存方式進(jìn)行操作;
- 在處理不同格式的圖像時(shí),應(yīng)該注意色彩模式、透明度等方面的差異,以避免圖像信息的丟失;
- 在進(jìn)行高級(jí)操作時(shí),應(yīng)該考慮到圖像質(zhì)量的問(wèn)題,避免操作過(guò)度造成圖像質(zhì)量的下降。
以上就是一文帶你掌握J(rèn)ava ImageIO類(lèi)的詳細(xì)內(nèi)容,更多關(guān)于Java ImageIO類(lèi)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
mybatis參數(shù)類(lèi)型不匹配錯(cuò)誤argument type mismatch的處理方案
這篇文章主要介紹了mybatis參數(shù)類(lèi)型不匹配錯(cuò)誤argument type mismatch的處理方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01Java 異步線程監(jiān)聽(tīng)與結(jié)果回調(diào)及異常捕獲總結(jié)分析
異常是程序之中導(dǎo)致程序中斷的一種指令流,異常一旦出現(xiàn)并且沒(méi)有進(jìn)行合理處理的話,那么程序就將中斷執(zhí)行,這篇文章綜合介紹了異步線程監(jiān)聽(tīng)與結(jié)果回調(diào)及異常捕獲2021-11-11如何使用Spring MVC的消息轉(zhuǎn)換器設(shè)置日期格式
這篇文章主要介紹了如何使用Spring MVC的消息轉(zhuǎn)換器設(shè)置日期格式,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07泛型的類(lèi)型擦除后fastjson反序列化時(shí)如何還原詳解
這篇文章主要為大家介紹了泛型的類(lèi)型擦除后fastjson反序列化時(shí)如何還原詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Java實(shí)現(xiàn)一個(gè)簡(jiǎn)易聊天室流程
這篇文章主要介紹了我的java課程設(shè)計(jì)一個(gè)多人聊天室(socket+多線程)本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-11-11