我想更改多页TIFF图像的高度,所以我在下面的代码段中进行缩放。但是它仅从tiff文件返回第一页,我想它会将其转换为JPEG图像。如何保留文件的所有页面?
public static byte[] scale(byte[] fileData, int width, int height) { System.out.println("width:::"+width+"::::height:::"+height); ByteArrayInputStream in = new ByteArrayInputStream(fileData); ByteArrayOutputStream buffer=null; BufferedImage img=null; BufferedImage imageBuff=null; try { ImageInputStream imageStream = ImageIO.createImageInputStream(new ByteArrayInputStream(fileData)); java.util.Iterator<ImageReader> readers = ImageIO.getImageReaders(imageStream); while(readers.hasNext()) { ImageReader nextImageReader = readers.next(); nextImageReader.reset(); } img = ImageIO.read(in); if(height == 0) { height = (width * img.getHeight())/ img.getWidth(); } if(width == 0) { width = (height * img.getWidth())/ img.getHeight(); } Image scaledImage = img.getScaledInstance(width, height, Image.SCALE_SMOOTH); imageBuff = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); imageBuff.getGraphics().drawImage(scaledImage, 0, 0, new Color(0,0,0), null); buffer = new ByteArrayOutputStream(); ImageIO.write(imageBuff, "TIF", buffer); } catch (IOException e) { e.printStackTrace(); } finally{ if(img!=null){ img.flush(); img=null; } if(imageBuff!=null){ imageBuff.flush(); imageBuff=null; } if(buffer!=null){ try { buffer.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(in!=null){ try { in.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return buffer.toByteArray(); }
更新的代码:
public static byte[] resize(byte[] img,int height,int width) throws IOException { byte[] outimage = null; ImageReader reader=null; ImageWriter writer=null; ByteArrayOutputStream baos=null; ImageOutputStream ios=null; ImageInputStream imageStream=null; try { baos = new ByteArrayOutputStream(30000); ios = ImageIO.createImageOutputStream(baos); reader = getTiffImageReader(); imageStream= ImageIO.createImageInputStream(new ByteArrayInputStream(img)); reader.setInput(imageStream); int pages = reader.getNumImages(true); Iterator<ImageWriter> imageWriters = ImageIO.getImageWritersByFormatName("TIFF"); writer = imageWriters.next(); writer.setOutput(ios); ImageWriteParam writeParam = writer.getDefaultWriteParam(); writeParam.setTilingMode(ImageWriteParam.MODE_DEFAULT); writer.prepareWriteSequence(reader.getStreamMetadata()); for (int i = 0; i < pages; i++) { //IIOImage iioImage = reader.readAll(i, null); BufferedImage bufimage=null; BufferedImage imageBuff=null; bufimage=reader.read(i); imageBuff=Thumbnails.of(bufimage).size(1200, 1200).asBufferedImage(); IIOImage scalediioImage = new IIOImage(imageBuff, null, null); writer.writeToSequence(scalediioImage, writeParam); bufimage.flush(); imageBuff.flush(); } writer.endWriteSequence(); outimage = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally{ if(imageStream!=null){ imageStream.close(); } if(ios!=null){ ios.flush(); ios.close(); } if(baos!=null){ baos.close(); } if(reader!=null){ reader.dispose(); } if(writer!=null){ writer.dispose(); } } return outimage; }
ImageIO.write(...)只会写入单个独立映像。将多个图像写入同一输出流并不能解决此问题。但是,ImageIO软件包完全支持您所需的内容,只需要更多代码即可。
ImageIO.write(...)
使用以下命令获取适用ImageWriter于TIFF格式的格式:
ImageWriter
ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next(); // Assumes TIFF plugin installled
有关更多信息,请参见ImageIO.getImageWritersByFormatName(String)的API文档。
然后使用writer.canWriteSequence()来告诉您的writer实例是否支持编写序列。它 应该 返回trueTIFF。如果不是,则需要找到其他插件。
writer.canWriteSequence()
writer
true
接下来,使用writer.prepareWriteSequence(...)准备图像序列。
writer.prepareWriteSequence(...)
对于要附加的每个图像(页),使用 writer.writeToSequence(new IIOImage(..., bufferedImage, null), ...)的for循环。
writer.writeToSequence(new IIOImage(..., bufferedImage, null), ...)
for
然后最后, 外部 的for环使用writer.endWriteSequence()以结束图像序列。
writer.endWriteSequence()
希望这些指针能使您朝正确的方向前进。
更新:这是我 认为 应该工作的代码的经过清理和修改的版本(我没有,也不能在我的笔记本电脑上安装JAI)。
重要的更改是writer.setOutput(ios)从循环中删除(只需设置一次),然后将writer.endWriteSequence()循环移开。我还删除了该BufferedImage数组,以避免将所有图像保留在内存中,为方便起见,可能需要保留它。
writer.setOutput(ios)
BufferedImage
如果您仍然遇到问题,请告诉我,我会解决的。
public static byte[] resize(byte[] img) throws IOException { byte[] outimage = null; try { ByteArrayOutputStream baos = new ByteArrayOutputStream(30000); ImageOutputStream ios = ImageIO.createImageOutputStream(baos); ImageReader reader = getTiffImageReader(); ImageInputStream imageStream = ImageIO.createImageInputStream(new ByteArrayInputStream(img)); reader.setInput(imageStream); int pages = reader.getNumImages(true); Iterator<ImageWriter> imageWriters = ImageIO.getImageWritersByFormatName("TIFF"); ImageWriter writer = imageWriters.next(); writer.setOutput(ios); ImageWriteParam writeParam = writer.getDefaultWriteParam(); writeParam.setTilingMode(ImageWriteParam.MODE_DEFAULT); writer.prepareWriteSequence(reader.getStreamMetadata()); // You want the stream metadata here for (int i = 0; i < pages; i++) { IIOImage iioImage = reader.readAll(i, null); // Save some lines by using readAll BufferedImage image = (BufferedImage) iioImage.getRenderedImage(); // Modify image here... iioImage.setRenderedImage(image); writer.writeToSequence(iioImage, writeParam); } writer.endWriteSequence(); // Crucial, must be done outside loop ios.flush(); ios.close(); outimage = baos.toByteArray(); baos.close(); writer.dispose(); reader.dispose(); } catch (Exception e) { e.printStackTrace(); } return outimage; }