在Java中缩放多页TIFF图像 [英] Scale multi page TIFF Image in java
问题描述
我想更改多页TIFF图像的高度,所以我在下面的代码段中进行缩放.但是它仅从tiff文件返回第一页,我想它会将其转换为JPEG图像.如何保留文件的所有页面?
I want to change the height of multi page TIFF image so I am using below code snippet to scale it. But It returns just first page from the tiff file , I guess it converts it to JPEG image. How to retain all pages of the file??
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(...)
will only ever write single stand-alone images. Writing multiple images to the same output stream does not remedy this. However the ImageIO package comes with full support for what you want, it just requires more code.
使用以下命令为TIFF格式获取正确的ImageWriter
:
Obtain the proper ImageWriter
for TIFF format, using :
ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next(); // Assumes TIFF plugin installled
有关 ImageIO.getImageWritersByFormatName(String)了解更多信息.
然后使用 writer
实例是否支持编写序列. 应该返回TIFF的true
.如果没有,则需要找到其他插件.
Then use writer.canWriteSequence()
to tell if your writer
instance supports writing sequences. It should return true
for TIFF. If not, you need to find a different plugin.
接下来,使用 writer.prepareWriteSequence(...)
准备图像序列.
Next, use writer.prepareWriteSequence(...)
to prepare your image sequence.
For each image (page) you want to append, use writer.writeToSequence(new IIOImage(..., bufferedImage, null), ...)
in a for
loop.
Then finally, outside the for
loop use writer.endWriteSequence()
to end the image sequence.
希望这些指针能使您朝正确的方向前进.
Hope these pointers should get you going in the right direction.
更新:这是我认为应该可以使用的代码的经过清理和修改的版本(我没有,也不能在我的笔记本电脑上安装JAI).
Update: Here's a cleaned up and modified version of your code that I think should work (I don't have and can't install JAI on my work laptop).
重要的更改是将writer.setOutput(ios)
从循环中删除(您只应设置一次),然后将writer.endWriteSequence()
移出循环.我还删除了BufferedImage
数组,以避免将所有图像保留在内存中,为方便起见,可能需要保留它.
The important changes are removing the writer.setOutput(ios)
from the loop (you should only set it once), and moving writer.endWriteSequence()
oustide the loop. I also removed the BufferedImage
array, to avoid keeping all the images in memory, you might want to keep it for convenience.
如果您仍然遇到麻烦,请告诉我,我会解决的.
Let me know if you still have trouble, and I'll see what I can do.
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;
}
这篇关于在Java中缩放多页TIFF图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!