libjpeg exit

编译jpeg-9c后得到libjpeg.lib,按照网上的例程,读jpg文件时,只要jpg文件有错误,libjpeg库的函数内部就直接调系统函数exit退出了,这在整合libjpeg库到大型程序里时是绝对不能允许的。仔细查看库里的libjpeg.txt,才知道原来libjpeg能自定义错误处理,例程在example.c文件里的read_JPEG_file。

以下是我整理好的集成接口:
ReadJpg.h

#pragma once
 
HBITMAP readJpegAsBitmap(const char *fileName);


ReadJpg.cpp

#include <stdio.h>
#include <setjmp.h>
#include <windows.h>
extern "C" {
#include <jpeglib.h> 
#include <jerror.h>
}
 
#pragma comment(lib, "libjpeg.lib")
 
struct my_error_mgr {
	struct jpeg_error_mgr pub;
 
	jmp_buf setjmp_buffer;
};
 
typedef struct my_error_mgr *my_error_ptr;
 
METHODDEF(void)
my_error_exit(j_common_ptr cinfo)
{
	my_error_ptr myerr = (my_error_ptr)cinfo->err;
 
	(*cinfo->err->output_message) (cinfo);
 
	longjmp(myerr->setjmp_buffer, 1);
}
 
HBITMAP readJpegAsBitmap(const char *fileName)
{
	BITMAP bmp;
	BITMAPINFO bi = {};
	LPBYTE lpBuf, pb = NULL;
	HBITMAP hBmp = NULL;
	JSAMPARRAY buffer{};
	int row_stride;
	UINT row;
 
	FILE *fp = fopen(fileName, "rb");
	if (fp == NULL)
	{
		return NULL;
	}
 
	unsigned char sign[4];
	fread(sign, 1, 4, fp);
	if (sign[0] != 0xff || sign[1] != 0xd8)
	{
		fclose(fp);
		return NULL;
	}
	fseek(fp, 0, SEEK_SET);
 
	struct jpeg_decompress_struct cinfo;
	struct my_error_mgr jerr;
 
	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = my_error_exit;
 
	if (setjmp(jerr.setjmp_buffer))
	{
		goto failout;
	}
 
	jpeg_create_decompress(&cinfo);
 
	jpeg_stdio_src(&cinfo, fp);
 
	jpeg_read_header(&cinfo, TRUE);
 
	jpeg_start_decompress(&cinfo);
 
	//row = ((cinfo.output_width * 3 + 3) & ~3);
	row_stride = cinfo.output_width * cinfo.output_components;
	buffer = (*cinfo.mem->alloc_sarray)
		((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);
 
	ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
	bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bi.bmiHeader.biWidth = cinfo.output_width;
	bi.bmiHeader.biHeight = cinfo.output_height;
	bi.bmiHeader.biPlanes = 1;
	bi.bmiHeader.biBitCount = 24;
	bi.bmiHeader.biCompression = BI_RGB;
//	bi.bmiHeader.biSizeImage = row * cinfo.output_height;
 
	hBmp = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**)&lpBuf, NULL, 0);
	if (hBmp == NULL)
		goto failout;
 
	GetObject(hBmp, sizeof(BITMAP), (void *)&bmp);
	row = bmp.bmWidthBytes;
 
	pb = lpBuf + row * cinfo.output_height;
	while (cinfo.output_scanline < cinfo.output_height)
	{
		pb -= row;
		jpeg_read_scanlines(&cinfo, buffer, 1);
 
		if (cinfo.out_color_components == 1)
		{
			LPBYTE p = (LPBYTE)buffer[0];
			for (UINT i = 0; i < cinfo.output_width; i++)
			{
				pb[3 * i + 0] = p[i];
				pb[3 * i + 1] = p[i];
				pb[3 * i + 2] = p[i];
			}
		}
		else if (cinfo.out_color_components == 3)
		{
			LPBYTE p = (LPBYTE)buffer[0];
			for (UINT i = 0; i < cinfo.output_width; i++)
			{
				UINT j = i * 3;
				pb[j + 0] = p[j + 2]; // Blue
				pb[j + 1] = p[j + 1]; // Green
				pb[j + 2] = p[j + 0];  // Red
			}
		}
		else
		{
			goto failout;
		}
	}
 
	SetDIBits(NULL, hBmp, 0, cinfo.output_height, lpBuf, &bi, DIB_RGB_COLORS);
 
	jpeg_finish_decompress(&cinfo);
 
failout:
 
	jpeg_destroy_decompress(&cinfo);
 
	fclose(fp);
 
	return hBmp;
}