在Java中缩放多页TIFF图像 [英] Scale multi page TIFF Image in java

查看:97
本文介绍了在Java中缩放多页TIFF图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想更改多页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 truefor 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.

然后最后,在for循环的外部中,使用

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆