코드/C++

libjpeg 사용하기

야곰야곰+책벌레 2022. 8. 23. 17:10
728x90
반응형

jpeg format을 손 코드로 해보려다가 포기. 그냥 잘 만들어진 open source를 써야겠다는 생각이 들었다.

그중에서 가장 많이 쓰이는 것으로 보이는 libjpeg를 사용하기로 했다.

 

libjpeg-turbo - Browse /2.1.4 at SourceForge.net

Package signatures To ensure the integrity of the libjpeg-turbo binary packages, the RPM and DEB files and the source tarball are signed using the following key: http://www.libjpeg-turbo.org/key/LJT-GPG-KEY http://pool.sks-keyservers.net/pks/lookup?op=get&

sourceforge.net

여기서 자신의 운영체제에 맞게 다운로드하면 된다. 나는 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
반응형