【发布时间】:2014-04-04 07:36:40
【问题描述】:
我想改变多页 TIFF 图像的高度,所以我使用下面的代码 sn-p 来缩放它。但它只返回 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;
}
【问题讨论】:
-
您至少需要java.net/projects/jai-imageio。您似乎在要求 multi-page TIFF 文件,但我不确定 ImageIO 甚至 JAI 是否可以处理它们...
-
我认为在更新的代码中没有输出也没有异常,这很奇怪,但它可能是循环内的
writer.setOutput(ios)以某种方式重置了编写过程。只设置一次输出,在writer.prepareWriteSequence()之前做。 -
旁注:
BufferedImage.flush()在这里是多余的,除非您实际将图像绘制到屏幕上(即,如果仅刷新本机视频 RAM)。图像仍将保存在 Java 堆内存中。