在java中缩放多页TIFF图像

我想更改多页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 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 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软件包完全支持您的需求,它只需要更多代码。

使用以下方法获取适合TIFF格式的ImageWriter

 ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next(); // Assumes TIFF plugin installled 

有关更多信息,请参阅ImageIO.getImageWritersByFormatName(String)的API文档。

然后使用writer.canWriteSequence()来判断您的编写器实例是否支持编写序列。 对于TIFF,它应该返回true 。 如果没有,您需要找到一个不同的插件。

接下来,使用writer.prepareWriteSequence(...)来准备图像序列。

对于要追加的每个图像(页面) writer.writeToSequence(new IIOImage(..., bufferedImage, null), ...)for循环中使用writer.writeToSequence(new IIOImage(..., bufferedImage, null), ...)

最后, for循环之外使用writer.endWriteSequence()来结束图像序列。

希望这些指针能让你朝着正确的方向前进。

更新:这是我认为应该工作的代码的清理和修改版本(我没有,也无法在我的工作笔记本电脑上安装JAI)。

重要的变化是从循环中删除writer.setOutput(ios) (你应该只设置一次),并且将writer.endWriteSequence()移动到循环中。 我还删除了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 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; }