2017-12-05 20 views
0

하나 이상의 이미지를 포함 할 수있는 스트림이 있으며 별도의 플래그없이 연속적으로 저장됩니다. javas ImageIO를 사용하여 스트림을 열고 구문 분석하면 첫 번째 이미지를 올바르게 구문 분석하지만 스트림을 닫으면 다음 이미지를 스트리밍 할 수 없습니다.스트림에 연속적으로 저장된 여러 jpeg를 구문 분석합니다.

그래서 파일의 각 압축 된 이미지가 얼마나 큰지 파악하려고합니다. 따라서 이미지의 정확한 바이트 수를 버퍼로 읽고 해당 버퍼에서 ByteArrayInputStream을 만들고 새로운 작은 버퍼를 사용하는 BufferedImage. 내 문제는 이미지가 얼마나 큰지 알아내는 것입니다. 너비/높이가 압축 된 것이 너비 * 높이보다 작기 때문에 도움이되지 않습니다.

버퍼를 통해 읽고 각 이미지가 쉽게 끝나는 곳을 찾는 방법이 있습니까? 스트림 마지막에는 하나의 eof를 제외하고는 soi, eoi, sof, eof, tags가 없습니다.

또는 더 좋은 방법이 있습니까? 스트림을 닫지 않고 계속 작업하게 해주는 ImageIO.read()에 대한 방법?

+0

여러 개의 SOI/EOI가없는 여러 이미지가있는 JPEG (JFIF)가 있다고 생각하기가 어렵습니다. 어떤 소프트웨어가 그것을 썼는지 알고 있습니까? 공유 할 샘플 파일이 있습니까? 그렇다면 아마도 도움이 될 수 있습니다. – haraldK

+0

나는 nitf 파일을 작업하고 있었지만 공유 할 수는 없지만 jpeg 이미지가 포함될 수있는 DoD 이미지 형식입니다. 내가 찾고 있던 파일이 jpeg와 호환되지 않는다고 생각합니다. DoD 웹 사이트의 예제 파일에는 soi, eoi 태그가 있습니다. – broccolli

답변

0

먼저 ImageIO.read(...)은 임의의 형식으로 된 파일의 단일 (첫 번째) 이미지 만 읽을 수있는 편리한 방법입니다. 대신, 당신은 귀하의 의견에 대한 ImageReader을 얻을 경우

, 당신은 (일반적으로) 개별 이미지는 read(int imageIndex, ImageReadParam param)를 사용하여 getNumImages(boolean allowSearch)를 사용하여 입력에 이미지의 수를 얻을, 읽기 (또는 생략) 할 수 있습니다. 같은

뭔가 :

// Create input stream 
try (ImageInputStream input = ImageIO.createImageInputStream(file)) { 
    // Get the reader 
    Iterator<ImageReader> readers = ImageIO.getImageReaders(input); 

    if (!readers.hasNext()) { 
     throw new IllegalArgumentException("No reader for: " + file); 
    } 

    ImageReader reader = readers.next(); 

    try { 
     reader.setInput(input); 

     // Optionally, listen for read warnings, progress, etc. 
     reader.addIIOReadWarningListener(...); 
     reader.addIIOReadProgressListener(...); 

     ImageReadParam param = reader.getDefaultReadParam(); 

     // Note: For some formats (ie. GIF), finding the number of images 
     // requires searching the entire stream. In this case, it may 
     // be more convenient to just read until you get an IndexOutOfBoundsException 
     for (int i = 0; i < reader.getNumImages(true); i++) { 
      // Optionally, control read settings like sub sampling, source region or destination etc. 
      param.setSourceSubsampling(...); 
      param.setSourceRegion(...); 
      param.setDestination(...); 
      // ... 

      // Finally read the image, using settings from param 
      BufferedImage image = reader.read(i, param); 

      // Optionally, read thumbnails, meta data, etc... 
      int numThumbs = reader.getNumThumbnails(0); 
      // ... 
     } 
    } 
    finally { 
     // Dispose reader in finally block to avoid memory leaks 
     reader.dispose(); 
    } 
} 

JRE를 번들 JPEGImageReader 이론도 단일 스트림에서 여러 JFIF의 서브를 지원해야한다. 그러나, 나는 당신이 지원이 깨 졌음을 발견 할 것이라고 생각합니다 (적어도 ImageIO 플러그인 프로젝트에는 open issue to fix this이 있습니다).

유감스럽게도 JPEG 압축 이미지의 길이를 디코딩하지 않고 (또는 길이를 JFIF 스트림 외부에 저장하여) 찾는 것은 불가능합니다. 당신이 시도 할 수

것은, ("시작 - 중 - 이미지", 0xffd8) 다음 SOI를 들어, 다음 앞으로 스캔 첫 번째 이미지를 읽기 위해 (아마도 ImageInputStream가 포장)되어 마커, 는 2 바이트 다시 찾아 (SOI 마커의 경우) 다음 이미지를 읽으려고합니다. SOI 마커는 JPEG 인코딩 된 데이터 안에 존재할 수 없습니다.

위키피디아에서 JPEGJFIF segments에 대한 자세한 내용을 볼 수 있습니다.

+0

이것은 위대한 솔루션이었습니다. 독자의 손을 떼고 거기에서 모든 이미지를 반복해야만했습니다. 고마워. 고마워. – broccolli