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