2013-11-20 62 views
2

我有一个TIFF图像已读入我的应用程序并存储在BufferedImage对象中。如何使用Java Advanced Imaging(JAI)API确定图像的水平和垂直DPI?我一直在环顾四周,无法找到实现这一目标的简单方法。确定Java中的图像的DPI

+0

如果你已经是一个' BufferedImage',你运气不好。如果你有一个文件,流或类似的参考,我建议看看t他的ImageIO API,尤其是'ImageReader.getImageMetadata()',从那里获得DPI应该是相当直接的。 – haraldK

+0

数据以Web服务调用的字节数组的形式出现。我想我可以回到最初从字节数组中读取它来尝试一个'ImageReader'的地步。然后将DPI信息传递到我需要的地方。我的下一个绊脚石似乎是,当我尝试执行'ImageIO.getImageReadersByFormatName(“tiff”)'加载读者时,它说它无法找到该类型的读者。仍试图找出如何解决这个问题。 – Michael

+0

我总是发现Java图像API有多复杂,我对它们知道得有多么... – Michael

回答

5

这里的一个完整的例子中提取DPI(井,每毫米的像素,真的)使用标准的ImageIO API和标准元数据格式。复杂性,我们来了...... :-P

public class DPITest { 
    public static void main(String[] args) throws IOException { 
     File input = new File(args[0]); 

     ImageInputStream stream = ImageIO.createImageInputStream(input); 
     Iterator<ImageReader> readers = ImageIO.getImageReaders(stream); 

     if (readers.hasNext()) { 
      ImageReader reader = readers.next(); 
      reader.setInput(stream); 

      IIOMetadata metadata = reader.getImageMetadata(0); 
      IIOMetadataNode standardTree = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName); 
      IIOMetadataNode dimension = (IIOMetadataNode) standardTree.getElementsByTagName("Dimension").item(0); 
      float horizontalPixelSizeMM = getPixelSizeMM(dimension, "HorizontalPixelSize"); 
      float verticalPixelSizeMM = getPixelSizeMM(dimension, "VerticalPixelSize"); 

      // TODO: Convert pixelsPerMM to DPI left as an exercise to the reader.. ;-) 

      System.err.println("horizontalPixelSizeMM: " + horizontalPixelSizeMM); 
      System.err.println("verticalPixelSizeMM: " + verticalPixelSizeMM); 
     } 
     else { 
      System.err.printf("Could not read %s\n", input); 
     } 
    } 

    private static float getPixelSizeMM(final IIOMetadataNode dimension, final String elementName) { 
     // NOTE: The standard metadata format has defined dimension to pixels per millimeters, not DPI... 
     NodeList pixelSizes = dimension.getElementsByTagName(elementName); 
     IIOMetadataNode pixelSize = pixelSizes.getLength() > 0 ? (IIOMetadataNode) pixelSizes.item(0) : null; 
     return pixelSize != null ? Float.parseFloat(pixelSize.getAttribute("value")) : -1; 
    } 
} 

一些消息来源为:

+0

哇,他们绝对不会让JAI容易弄清楚......我真的觉得我有时候会在我的脑海中(而且我并不是Java的新手) 。所以,看起来我可以将'InputStream'传递给'ImageIO.createImageInputStream'而不是'File',它应该适用于我正在做的事情。当我星期一回到办公室时会试试这个。谢谢(你的)信息! – Michael

+0

我很好奇,是否有一些资源可以用来解决如何完成某些事情,或者它真的只是“试错”,通过API文档挖掘来弄清楚事情的真相吗? – Michael

+0

@Michael这只是ImageIO API,而不是JAI特有的(但jai-imageio提供了实现此API的TIFF ImageReader插件),因此请尝试使用Google搜索。但不知道是否有一个“权威指南”在那里...'InputStream'应该可以。我会用一些指针更新答案。 – haraldK

3

Apache Commons Sanselan图书馆获取图像信息:http://commons.apache.org/imaging/index.html

final ImageInfo imageInfo = Sanselan.getImageInfo(file); 

final int physicalWidthDpi = imageInfo.getPhysicalWidthDpi(); 
final int physicalHeightDpi = imageInfo.getPhysicalHeightDpi(); 
+0

没有使用Commons Imaging的方法吗?我不想为这个任务包含一个额外的库。另外,要使用这种方法,我必须将其编码回字节数组中。如果我这样做而不指定'TIFFEncodeParam'中的DPI设置,则上面的代码将为这两个值返回-1。如果我给编码器指定了DPI设置,我确实得到了一个值,但显然它将是我指定的DPI,而不是图像的原始值。 – Michael

+0

我会更新尝试一些东西 – constantlearner