카테고리 없음

[크기] JPEG (JFIF) 이미지의 크기 결정

행복을전해요 2021. 1. 5. 20:48

압축 된 데이터에는 SOI 또는 EOI 바이트가 포함되지 않으므로 안전합니다. 그러나 주석, 애플리케이션 데이터 또는 기타 헤더가있을 수 있습니다. 다행히도 길이가 주어지면 이러한 섹션을 식별하고 건너 뛸 수 있습니다.

JPEG 사양은 필요한 사항을 알려줍니다.
http://www.w3.org/Graphics/JPEG/itu-t81.pdf

32 페이지의 표 B.1을 참조하십시오. *가있는 기호는 뒤에 길이 필드가 없습니다 (RST, SOI, EOI, TEM). 다른 사람들은 그렇습니다.

다양한 필드를 건너 뛰어야하지만 그렇게 나쁘지는 않습니다.

통과 방법 :

  1. SOI ( FFD8) 읽기를 시작합니다 . 이것이 시작입니다. 스트림에서 가장 먼저해야합니다.

    • 그런 다음 파일을 진행하여 더 많은 마커를 찾고 헤더를 건너 뜁니다.

    • SOI 마커 ( FFD8) : 손상된 이미지. 이미 EOI를 찾았어야합니다!

    • TEM ( FF01) : 독립형 마커, 계속 진행합니다.

    • RST ( FFD0~ FFD7) : 독립형 마커, 계속 진행합니다. 재시작 마커가 FFD0처음 FFD7부터 다시 반복 되는지 확인할 수 있지만 길이 측정에는 필요하지 않습니다.

    • EOI 마커 ( FFD9) : 완료되었습니다!

    • RST, SOI, EOI, TEM이 아닌 모든 마커 ( FF01~ FFFE, 위의 예외 제외) : 마커 뒤에 다음 2 바이트를 읽습니다. 이는 해당 프레임 헤더의 16 비트 빅 엔디안 길이입니다 (2를 포함하지 않음). -바이트 마커 (길이 필드 포함). 주어진 양을 건너 뜁니다 (이미 해당 바이트를 얻었으므로 일반적으로 길이-2).

    • EOI 이전에 파일 끝이 발생하면 이미지가 손상된 것입니다.

    • EOI를 받으면 JPEG를 통과했으며 길이가 있어야합니다. 스트림에 JPEG가 두 개 이상 예상되는 경우 다른 SOI를 읽어 다시 시작할 수 있습니다.

-------------------

아마도 이런 것

int GetJpgSize(unsigned char *pData, DWORD FileSizeLow, unsigned short *pWidth, unsigned short *pHeight)
{
  unsigned int i = 0;
  
  
    if ((pData[i] == 0xFF) && (pData[i + 1] == 0xD8) && (pData[i + 2] == 0xFF) && (pData[i + 3] == 0xE0)) {
        i += 4;
        
            // Check for valid JPEG header (null terminated JFIF)
                if ((pData[i + 2] == 'J') && (pData[i + 3] == 'F') && (pData[i + 4] == 'I') && (pData[i + 5] == 'F')
                        && (pData[i + 6] == 0x00)) {
                        
                              //Retrieve the block length of the first block since the first block will not contain the size of file
                                    unsigned short block_length = pData[i] * 256 + pData[i + 1];
                                    
                                          while (i < FileSizeLow) {
                                                  //Increase the file index to get to the next block
                                                          i += block_length; 
                                                          
                                                                  if (i >= FileSizeLow) {
                                                                            //Check to protect against segmentation faults
                                                                                      return -1;
                                                                                              }
                                                                                              
                                                                                                      if (pData[i] != 0xFF) {
                                                                                                                return -2;
                                                                                                                        } 
                                                                                                                        
                                                                                                                                if (pData[i + 1] == 0xC0) {
                                                                                                                                          //0xFFC0 is the "Start of frame" marker which contains the file size
                                                                                                                                                    //The structure of the 0xFFC0 block is quite simple [0xFFC0][ushort length][uchar precision][ushort x][ushort y]
                                                                                                                                                              *pHeight = pData[i + 5] * 256 + pData[i + 6];
                                                                                                                                                                        *pWidth = pData[i + 7] * 256 + pData[i + 8];
                                                                                                                                                                        
                                                                                                                                                                                  return 0;
                                                                                                                                                                                          }
                                                                                                                                                                                                  else {
                                                                                                                                                                                                            i += 2; //Skip the block marker
                                                                                                                                                                                                            
                                                                                                                                                                                                                      //Go to the next block
                                                                                                                                                                                                                                block_length = pData[i] * 256 + pData[i + 1];
                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                    //If this point is reached then no size was found
                                                                                                                                                                                                                                                          return -3;
                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                                  else {
                                                                                                                                                                                                                                                                        return -4;
                                                                                                                                                                                                                                                                            } //Not a valid JFIF string
                                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                                                else {
                                                                                                                                                                                                                                                                                    return -5;
                                                                                                                                                                                                                                                                                      } //Not a valid SOI header
                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                        return -6;
                                                                                                                                                                                                                                                                                        }  // GetJpgSize
                                                                                                                                                                                                                                                                                        
-------------------

게시 된 언어가 없기 때문에 이것이 작동할지 확신 할 수 없지만 :

Stream.Seek(0, StreamOffset.End);그럼 당신 은 스트림의 입장을 취할 수 있습니까 ?

사용중인 프레임 워크를 구체적으로 지정하십시오.

문제의 실제 사실은 파일 헤더가 예상 크기를 지정하지 않으면 이미지 끝까지 찾거나 읽어야한다는 것입니다.

편집하다

여러 파일을 스트리밍하려고하므로 스트리밍 친화적 인 컨테이너 형식을 사용하는 것이 좋습니다.

OGG 가 이에 적합해야합니다.

JPEG는 실제로 이미 스트리밍 친화적이지만 스트림으로 전송하기 전에 각 파일에 유효한 종료자가 있는지 확인해야합니다. 그렇지 않으면 예기치 않은 입력으로 앱이 중단 될 위험이 있습니다.

-------------------

파이썬에서는 전체 파일을 문자열 객체로 읽고 FF E0의 첫 번째 발생과 FF D9의 마지막 발생을 찾을 수 있습니다. 아마도 이것들이 당신이 찾고있는 시작과 끝입니까?

f = open("filename.jpg", "r")
s = f.read()
start = s.find("\xff\xe0")
end = s.rfind("\xff\xd9")
imagesize = end - start


출처
https://stackoverflow.com/questions/2005789