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;
}
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;
}