728x90
반응형
jpeg format을 손 코드로 해보려다가 포기. 그냥 잘 만들어진 open source를 써야겠다는 생각이 들었다.
그중에서 가장 많이 쓰이는 것으로 보이는 libjpeg를 사용하기로 했다.
여기서 자신의 운영체제에 맞게 다운로드하면 된다. 나는 VS2015의 C++를 사용할 것이기 때문에 C++용을 받았다. 다운로드된 파일의 압축을 풀면 다음과 같다.
bin 폴더 아래 dll들과 lib 폴더 아래 lib 파일 그리고 include에 들어 있는 헤드 파일을 사용하면 된다. ligjpeg는 static을 지원하기에 lib에 포함된 jpeg-static.lib만 사용하기로 했다. 프로젝트에 lib을 추가한 후 다음과 같이 사용하면 된다.
<읽어오기>
bool JpegCtrl::Load(wstring filepath, ImageEx& image, int _channels)
{
jpeg_decompress_struct cinfo;
return read_jpeg_file(cinfo, filepath, image);
}
int JpegCtrl::read_jpeg_file(jpeg_decompress_struct& cinfo, wstring& filepath, ImageEx& image)
{
my_error_mgr jerr;
FILE* infile; // source file
unsigned char* rowptr[1]; // pointer to an array
int row_stride; // physical row width in output buffer
_wfopen_s(&infile, filepath.c_str(), L"rb");
if (infile == nullptr)
return false;
// Step 1. allocate and initialize JPEG decompression object
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = JpegCtrl::my_error_exit;
if (setjmp(jerr.setjmp_buffer))
{
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return 0;
}
jpeg_create_decompress(&cinfo);
// Step 2. specify data source (eg. a file)
jpeg_stdio_src(&cinfo, infile);
// Step 3. read file parameters with jpeg_read_header()
(void)jpeg_read_header(&cinfo, TRUE);
// Step 4. set parameters form decompression
// Step 5. Start decompressor
(void)jpeg_start_decompress(&cinfo);
int nCols = cinfo.output_width;
int nRows = cinfo.output_height;
int nChannels = cinfo.num_components;
image.Create(nRows, nCols, nChannels, ColorFormat::ColorFormatBGR);
//row_stride = cinfo.output_width * cinfo.output_components;
//buffer = (cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);
// Step 6. while (scan lines remain to be read)
while (cinfo.output_scanline < cinfo.output_height)
{
rowptr[0] = image.Get(0) + image.WidthStep() * cinfo.output_scanline;
(void)jpeg_read_scanlines(&cinfo, rowptr, 1);
//put_scanline_someplace(buffer[0], row_stride);
}
// Step 7. Finish decompression
(void)jpeg_finish_decompress(&cinfo);
// Step 8. Release JPEG decompression object
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return 1;
}
<저장하기>
bool JpegCtrl::Save(wstring filepath, ImageEx& image, int quality)
{
jpeg_compress_struct cinfo;
jpeg_error_mgr jerr;
FILE* outfile; // target file
unsigned char* rowptr[1]; // pointer to an array
int row_stride; // physical row width in image buffer
// Step 1. allocate and intialize JPEG compression object
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
// Step 2. specify data destination (eg, a file)
_wfopen_s(&outfile, filepath.c_str(), L"wb");
if (outfile == nullptr)
return false;
jpeg_stdio_dest(&cinfo, outfile);
// Step 3. set parameters for compression
cinfo.image_width = image.Cols(); // image width and height, in pixels
cinfo.image_height = image.Rows();
cinfo.input_components = image.Channels(); // # of color components per pixel
cinfo.in_color_space = JCS_RGB; // colorspace of input image
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE);
// Step 4. Start compressor
jpeg_start_compress(&cinfo, TRUE);
// Step 5. while (scan lines remain to be written)
// row_stride = image_width * 3; // JSAMPLEs per row in image_buffer
while (cinfo.next_scanline < cinfo.image_height)
{
rowptr[0] = image.Get(0) + image.WidthStep() * cinfo.next_scanline;
// row_pointer[0] = &image_buffer[cinfo.next_scanline * row_stride];
(void)jpeg_write_scanlines(&cinfo, rowptr, 1);
}
// Step 6. Finish compression
jpeg_finish_compress(&cinfo);
fclose(outfile);
// Step 7. release JPEG compression object
jpeg_destroy_compress(&cinfo);
return true;
}
<결과>
728x90
반응형
'코드 > C++' 카테고리의 다른 글
[C++] 마우스 이벤트 후킹 (0) | 2022.05.11 |
---|---|
[C++] string ↔ wstring 변환 (4) | 2022.02.24 |
[C++] XMLLite를 이용한 XML 파일 읽어오기 (0) | 2021.11.08 |
[C++] 3점을 지나는 외접원의 중심점 구하기 (0) | 2021.04.20 |
[C++] Char의 형 변환 (0) | 2021.04.20 |