Friday, February 11, 2011

 

Using jpeglib on Windows - decoding (디코딩)

앞서 포스팅한 jpeglib 문제 해결에 이어서,

jpeg 파일을 jpeglib를 이용하여 디코딩하는 루틴을 설명합니다.

코드에 코멘트를 잘 달아놓았으므로 이해하는데 큰 문제는 없을 겁니다.

Step 1. 파일 첫머리에 다음과 같이 include를 해줍니다.

// jpeglib를 사용하기 위한 include 파일.
//
#include "jinclude.h"
#include "jpeglib.h"

Step 2. 디코딩 함수는 다음과 같습니다.

a_pFilename -> jpeg 파일 이름입니다.
a_pBuffer -> 이미지를 담을 버퍼에 대한 포인터입니다.
버퍼는 함수 내부에서 자동으로 할당합니다.

bool read(char *a_pFilename, JSAMPLE **a_pBuffer)
{

// JPEG 파일을 해석합니다.
// 해석 과정에서 width, height, color space, bytes per pixel 같은 값들이
// 추출됩니다.
//

// Data strucure required for decoding JPEG file.
//
struct jpeg_decompress_struct cInfo;
struct jpeg_error_mgr cErrMgr;

FILE *pFile;
int iRowStride, i;
JSAMPARRAY pRows;


// 파일 이름부터 체크하고,
//
if( !a_pFilename )
return false;

// 파일을 엽니다.
// 반드시 binary mode로 열어야 합니다.
//
pFile = fopen(a_pFilename, "rb");
if( !pFile )
return false;

// 1. Install error manager.
//
cInfo.err = jpeg_std_error(&cErrMgr);

// 2. Create JPEG decompressor object.
//
jpeg_create_decompress(&cInfo);

// 3. Specify the data source.
//
jpeg_stdio_src(&cInfo, pFile);

// 4. Read JPEG Header to extract image information.
//
(void) jpeg_read_header(&cInfo, TRUE);

// 이 시점부터 cInfo 구조체를 통해 jpeg image의 원래 정보들에 접근할 수 있습니다.
// 예를 들면, width, height, color space, number of components per pixel 등등
//

// 5. JPEG 이미지를 어떤 출력 포맷으로 디코딩할 것인지 지정합니다.
// 여기서는 JCS_RGB 포맷으로 디코딩합니다.
// 이전 포스팅에서 추가한 JCS_BGRA 포맷을 지정하면 32bit BGRA 포맷으로
// 디코딩됩니다. 출력포맷은 반드시 아래 Step 6에서 jpeg_start_decompress() 함수 호출
// 이전에 지정해야 합니다.

//
cInfo.out_color_space = JCS_RGB;

// 6. Initiate decompress procedure.
// 이 함수는 decoding을 위한 전처리를 하는 함수입니다.
// cInfo.output_width, cInfo.output_height와 같이 최종 출력 이미지에 대한
// 정보들이 여기에서 계산됩니다.
//

(void) jpeg_start_decompress(&cInfo);

// 7. 이미지 디코딩을 위한 메모리를 할당합니다.
// 디코더는 2단계의 버퍼를 사용합니다. 하나는 Row buffer로서 각 line별로 출력 버퍼를
// 가리킵니다. 다른 하나는 이미지 버퍼로서 실제 이미지를 저장합니다.
// 일반적인 경우, 각 Row[i]는 이미지 버퍼에서 i번째 line의 시작 주소를 저장합니다.
//

// 이미지의 한 scanline의 크기 계산.
//
iRowStride = cInfo.output_width * cInfo.output_components;

// 이미지 버퍼를 할당한다.
//
(*a_pBuffer) = new JSAMPLE[ iRowStride * cInfo.output_height ];
if( !(*a_pBuffer) )
{
// Allocation failed.
jpeg_destroy_decompress(&cInfo);
fclose(pFile);
return false;
}

// Row 버퍼를 할당한다.
// 여기서는 한번에 한 줄씩만 디코딩한다.
//
pRows = new JSAMPROW[ 1 ];
if( !pRows )
{
// Allocation failed.
delete[] (*a_pBuffer);
(*a_pBuffer) = NULL;
jpeg_destroy_decompress(&cInfo);
fclose(pFile);
return false;
}

// 디코딩 루프: 모든 line이 디코딩될 때까지 반복한다.
//
i = 0;
while (cInfo.output_scanline < cInfo.output_height)
{
// Decode it !
pRows[0] = (JSAMPROW)( (*a_pBuffer) + iRowStride * i); // Row 버퍼 설정
(void) jpeg_read_scanlines(&cInfo, pRows, 1); // 디코딩 함수 호출
i++;
}

// 8. Finish decompression.
//
(void) jpeg_finish_decompress(&cInfo);

// 9. Reclaim resources and return.
//
delete[] pRows;
jpeg_destroy_decompress(&cInfo);
fclose(pFile);

return true;
}

Comments: Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?