2017-12-31 294 views
-2

jpeg의 메타, 헤더 및 코덱 정보없이 얼마나 큰 jpeg 파일인지 알고 싶습니다. 그래서 결국에는 DCT 계수와 양자화 및 허프만 테이블로 구성된 압축 된 픽셀 데이터 만 검색합니다.코덱 정보가없는 jpeg 파일의 크기는 얼마입니까?

그러나 이러한 배열의 크기를 파이썬 또는 C/C++로 추출하는 방법은 무엇입니까?

내가 libjpeg 사용하려고 않았지만, 압축 된 데이터의 크기를 계산하는 방법을 찾지 못했습니다.

+0

내가 확신 libjpeg이야 [난 그냥 지금에 대한 문서를 읽어] 이 정보를 제공하지 않습니다 (직접, 출처를 변경하지 않고). 파이썬의 JPEG 코드는 libjpeg을 기반으로하기 때문에 도움이 될지 의심 스럽다. 헤더 등을 읽는 코드를 작성한 다음 전체 크기에서 메타 데이터 크기를 뺍니다. –

+3

왜 알고 싶습니까? 메타 데이터가 없으면 나머지는 쓸모가 없습니다. –

+0

저는 JPEG 파일의 시작 부분에 약 9 바이트의 순수한 식별 데이터가 있다고 생각합니다. 다른 모든 것은 디코딩에 필요합니다. –

답변

0

대략 다음과 같은 코드가 있습니다. 나는 이것이 어떤 라이브러리에서나 사용할 수있는 "기성품"해결책이 있다고 믿지 않는다.

매우 정교하지 않으며, 내가 원하는만큼 간단하지도 않습니다. 나는 "~/Pictures"폴더 (그리고 다른 장소의 몇몇 다른 것들)에서 무작위 이미지 수백 개를 돌렸지 만 "모든"이미지를 처리 ​​할 것이라는 보장은 없다. 내 모든 이미지는 두 개의 서로 다른 응용 프로그램에 의해 생성된다고 생각한다. "다른 몇몇"은 다른 프로듀서가 다른 필드를 사용하거나이 코드가 처리 할 수없는 형태로 데이터를 생성 할 수도 있습니다. 그것이 깨지면, 당신은 모든 조각을 지키게되지만 환불은 없습니다.

실제 이미지 데이터가 무엇이고 그렇지 않은지 확인하려면 독자에게 맡기 겠습니다. 블럭 크기는 블럭 헤더 자체를 포함하지 않는다. 즉, 맨 위에 또 다른 2 바이트가있다.

오, 그렇습니다.이 코드는 C++과 C의 혼합 코드입니다. 다른 목적으로 작성한 코드의 일부분을이 코드와 함께 해킹 했으므로 정리를하지 않아도됩니다. 더 내 최고의 모든 코딩을 꼭 ...

은 나뿐만 아니라 여기까지 코드를 추가하지했습니다 https://github.com/Leporacanthicus/jpegrd

#include <fstream> 
#include <ios> 
#include <vector> 
#include <cstdint> 


#define die(str, ...) \ 
    do { printf(str, __VA_ARGS__); exit(1); } while(0) 

void read_bytes(std::ifstream &f, uint8_t *buffer, std::streamsize sz) 
{ 
    if(!f.read(reinterpret_cast<char*>(buffer), sz)) 
    { 
     die("Expected to read %zd bytes\n", sz); 
    } 
} 

uint32_t read_size(std::ifstream &f) 
{ 
    uint8_t buffer[2]; 
    read_bytes(f, buffer, 2); 
    uint32_t size = buffer[0] << 8 | buffer[1]; 
    return size; 
} 

void skip_size(std::ifstream &f, std::streamsize to_skip) 
{ 
    f.seekg(to_skip - 2, std::ios_base::cur); 
} 

void check_buffer(uint8_t *buffer, const std::vector<uint8_t> &val) 
{ 
    uint8_t *b = buffer; 
    for(auto v : val) 
    { 
     if (*b != v) 
     { 
      die("Mismatch! Expected %02x, got %02x\n", v, *b); 
     } 
     b++; 
    } 
} 

uint32_t find_next_header(std::ifstream &f) 
{ 
    uint8_t b; 
    bool found = false; 
    uint32_t count = 0; 
    do 
    { 
     read_bytes(f, &b, 1); 
     if (b == 0xFF) 
     { 
      if (f.peek() == 0x00) 
      { 
       read_bytes(f, &b, 1); 
       count+= 2; 
      } 
      else 
      { 
       f.unget(); 
       found = true; 
      } 
     } 
     else 
     { 
      count++; 
     } 
    } while(!found); 

    return count; 
} 

int main(int argc, char **argv) 
{ 
    if (argc != 2) 
    { 
     printf("Expected filename as argument\n"); 
     exit(1); 
    } 

    std::ifstream f(argv[1], std::ios_base::in|std::ios_base::binary); 
    if (!f) 
    { 
     die("Couldn't open the file %s\n", argv[1]); 
    } 

    uint8_t buffer[2]; 
    uint32_t total = 0; 

    read_bytes(f, buffer, 2); 
    check_buffer(buffer, {0xFF, 0xd8}); 
    total += 2; 

    bool eoi = false; 
    do 
    { 
     uint32_t size; 
     read_bytes(f, buffer, 2); 
     if (buffer[0] != 0xff) 
     { 
      die("Expected 0xFF byte, got %02x at offset %zu\n", 
       buffer[0], (size_t)f.tellg()); 
     } 
     total += 2; 
     switch(buffer[1]) 
     { 
     case 0xE0: 
     case 0xE1: 
     case 0xE2: 
     case 0xE3: 
     case 0xE4: 
     case 0xE5: 
     case 0xE6: 
     case 0xE7: 
     case 0xE8: 
     case 0xE9: 
     case 0xEA: 
     case 0xEB: 
     case 0xEC: 
     case 0xED: 
     case 0xEE: 
     case 0xEF: 
      size = read_size(f); 
      total += size; 
      printf("APP Data Type %02x: %u bytes of application data\n", 
        buffer[1], size); 
      skip_size(f, size); 
      break; 

     case 0xDB: 
      size = read_size(f); 
      total += size; 
      printf("DQT: %u bytes of quantization data\n", size); 
      skip_size(f, size); 
      break; 

     case 0xC0: 
     case 0xC2: 
      size = read_size(f); 
      total += size; 
      printf("SOF: %u bytes of frame data\n", size); 
      skip_size(f, size); 
      break; 

     case 0xC4: 
      size = read_size(f); 
      total += size; 
      printf("DHT: %u bytes of huffman tables\n", size); 
      skip_size(f, size); 
      break; 

     case 0xDA: 
      size = read_size(f); 
      skip_size(f, size); 
      size += find_next_header(f); 
      total += size; 
      printf("SOS: %u bytes of scan data\n", size); 
      break; 

     case 0xD9: 
      printf("EOI: end of image\n"); 
      eoi = true; 
      break; 

     case 0xFE: 
      size = read_size(f); 
      skip_size(f, size); 
      total += size; 
      printf("COM: comment %u bytes\n", size); 
      break; 

     default: 
      die("Expected known encoding byte, got %02x\n", buffer[1]); 
      break; 
     } 
    } while(!eoi); 
    printf("Total size = %u\n", total); 
} 
+0

불행히도 일부 이미지에서만 작동합니다. 이 중 일부는 실패합니다. https://imgur.com/a/YvrOc. – baudcode

+0

"작동하지 않음"이란 정확히 무엇을 의미합니까? 나는 그 이미지들을 다운로드했고, 그것들은 모두 약간의 결과물을 가지고 프로그램을 통과한다. 나는 그것이 무엇이되어야하는지, 그리고 그것이 무엇이되어야하는지에 어떤 노력도 기울이지 않았지만, 일반적으로 출력은 괜찮아 보인다. 물론 이미지가 업로드 한 것과 실제로 동일하지 않을 수도 있습니다. 대부분의 사이트는 업로드 프로세스의 일부로 이미지를 코드화하여 대개 크기를 줄입니다. 따라서 문제가 재현 가능함을 먼저 확인해야 할 수 있습니다 귀하의 링크에서 이미지를 다운로드하십시오. 그런 다음 잘못된 점을 자세히 설명하십시오. –

+0

죄송합니다. 내 코드의 버그입니다. (모든 것이 완벽하게 작동합니다. – baudcode

0

메타 데이터의 양은 인코더에 따라 완전히 달라집니다.은 JPEG 스트림 인 만이 필요한 헤더 2 바이트 SOI 마커. 유일한 바닥 글은 2 바이트 EOI 마커입니다.

그 밖의 모든 것은 t입니다 그는 인코더를 넣습니다.

+0

실제로는 인코더가 합리적인 금액을 추가하고 있습니다.필자는 헤더 필드에서 JPEG 파일에있는 내용을 읽는 프로그램을 작성했지만 마커와 길이를 읽는 것보다 조금 복잡합니다. 그러나 4.1K 데이터 파일에는 3160 바이트의 메타 데이터가 있습니다 (지금까지 말할 수있는 한). 김프에서 가져온 것입니다. 더 낮은 압축률을 가진 동일한 입력 파일 (그림에서 더 자세하게 나타남)은 동일한 3160 바이트의 메타 데이터를 갖는 것으로 보입니다. –

+0

엔코더에 따라 다릅니다. 내 것은 아무 것도 추가하지 않는다. – user3344003

+0

그게 어느 것입니까? 또는 자신의 집에서 만든 것? 나는 집에서 양조되지 않은 인코더의 알려진 양의 오버 헤드가 없기 때문에 Baudcode가 얼마나 많은지 알고 싶다고 생각합니다. –