2013-11-20 2 views
2

내 응용 프로그램에서 읽은 TIFF 이미지가 있고 BufferedImage 개체에 저장되어 있습니다. JAI (Java Advanced Imaging) API를 사용하여 이미지의 수평 및 수직 DPI를 어떻게 결정합니까? 나는 주변을 둘러 보았고 이것을 달성 할 수있는 직접적인 방법을 찾지 못했습니다.Java에서 이미지 DPI 확인

+0

당신이 모두 인 경우' BufferedImage', 운이 없다면 .. 파일, 스트림 또는 유사한 것에 대한 참조가 있다면, 나는 t 그는 ImageIO API, 특히'ImageReader.getImageMetadata()'를 사용하여 DPI를 얻는 것이 매우 간단합니다. – haraldK

+0

데이터가 웹 서비스 호출에서 바이트 배열로 제공됩니다. 나는 처음에 다시 ImageReader를 시도하기 위해 바이트 배열에서 읽었던 지점으로 돌아갈 수 있다고 생각한다. 그런 다음 DPI 정보를 필요한 지점으로 전달하십시오. 내 다음 걸림돌은'ImageIO.getImageReadersByFormatName ("tiff")'을 사용하여 독자를로드하려고 시도 할 때 해당 유형의 리더를 찾을 수 없다는 것입니다. 아직도 그것을 해결하는 방법을 찾아 내려고 노력했습니다. – Michael

+0

자바 이미징 API의 복잡성과 내가 알고있는 정보가 얼마나 부족한 지 알아 냈습니다. – Michael

답변

5

다음은 표준 ImageIO API 및 표준 메타 데이터 형식을 사용하여 DPI (실제로는 mm 당 픽셀 수)를 추출하는 전체 예입니다. 복잡성, 우리가 간다 ... - 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를 쉽게 이해할 수 없게 만듭니다 ... 가끔은 가끔씩 머리 속에 들어있는 것 같은 느낌이 듭니다. . 그래서, 내가하고있는 일을 할 수있는'File'보다는'ImageIO.createImageInputStream'에'InputStream'을 전달할 수있는 것처럼 보입니다. 월요일에 사무실에 갈 때 이걸 시험해 볼거야. 정보 주셔서 감사합니다! – Michael

+0

일을 성취하는 방법을 찾아 내려고하는 일부 리소스가 궁금하거나, API를 통해 문서를 찾아내는 데 '시행 착오'가 실제로 발생했는지 궁금합니다. – Michael

+0

@Michael 이것은 JAI 전용이 아닌 ImageIO API입니다 (그러나 jai-imageio는이 API를 구현하는 TIFF ImageReader 플러그인을 제공합니다). 따라서이를 시도해보십시오. 그러나 거기에 "결정적인 안내"가 있는지 확실하지 않습니다 ...'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