HBITMAP转储JPG文件,源码示例

这是一个C++函数,用于将HBITMAP类型的位图压缩成JPG文件。函数支持16位(ARGB1555)、24位和32位颜色深度的位图,并使用jpeglib库进行转换。代码中包含了获取位图颜色分量的内联函数,以及对不同颜色深度位图的预处理操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*  获得 A1R5G5B5 红色分量 */
inline BYTE R1555(  unsigned short  clr )
{
	return  ( (clr  &   0x7C00 )  >>   7)  & 0x0ff;
}  
/*  获得 A1R5G5B5 绿色分量 */
inline BYTE G1555(  unsigned short  clr )
{
	return  ( (clr  &   0x03E0 )  >>   2) & 0x0ff ;
}  
/*  获得 A1R5G5B5 蓝色分量 */
inline BYTE B1555( unsigned short  clr )
{
	return  ( (clr  &   0x001F )  <<   3) & 0x0ff;
}
/* 四字节对齐 */
int DWORDAlign( int nBits ) 
{ 
    int nAlignBytes = ( nBits + 31 ) / 32 * 4; 
    return nAlignBytes; 
}
/*
测试环境:VS2008 with SP1 + WinXP with SP3
功能:[HBITMAP bitmap]中指向的位图压缩成名为[const wchar_t* filename]的JPG文件
入口参数:HDC hDC  当前显示设备句柄 
返回值:    TRUE: 成功
            FALSE:失败
说明:只支持16(ARGB1555),24,32 三种颜色深度的 HBITMAP类型
最后修改:kagula,2012-05-15
参考资料
[1]使用jpeglib库实现bmp转jpg (转)
http://www.cppblog.com/cc/archive/2012/02/22/166217.html
[2]bmp轉jpg錯誤總結 + jpeglib使用指南
http://www.guan8.net/Java/409856.html
[3]图片在jpg 格式与bmp24格式之间的转换
http://www.rosoo.net/a/201105/11816.html
[4]依赖库IJG的官网
http://www.ijg.org/
备注:
[1]JPG格式不支持色深超过24位的真彩色图像
*/
BOOL WriteJPGFile(HBITMAP bitmap, const wchar_t* filename,HDC hDC)
{
	BITMAP bmp;
	struct jpeg_compress_struct jcs;
	struct jpeg_error_mgr       jerr;
	FILE                       *outfile;           /* target file */
	JSAMPROW                    row_pointer[1];    /* pointer to JSAMPLE row[s] */
	unsigned int                jcs_row_stride;    /* 目标缓存 每一行的字節數 */
	unsigned int                src_row_stride;    /*   源缓存 每一行的字節數 */

	// create the bitmapinfo header information
	if ( ! GetObject( bitmap, sizeof(BITMAP), (void *)(&bmp) ) ){
		g_log.Add("WriteJPGFile  Could not retrieve bitmap info");
		return FALSE;
	}

	if(bmp.bmBitsPixel<16)
	{
		g_log.Add("WriteJPGFile  只支持16(ARGB1555),24,32 三种深度的 HBITMAP类型");
		return FALSE;
	}

	jcs.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&jcs);
	if ((outfile = _wfopen(filename, L"wb")) == NULL) {
		g_log.Add("WriteJPGFile 无法打开文件");
		return FALSE;
	}

	jpeg_stdio_dest(&jcs, outfile);
	jcs.image_width      = bmp.bmWidth; 
	jcs.image_height     = bmp.bmHeight;
	jcs.input_components =  3;          /* 在此為1,表示灰度圖, 如果是彩色位圖,則為3。经测试此值只能为1或3。*/
	jcs.in_color_space   = JCS_RGB;     /* JCS_GRAYSCALE表示灰度圖,JCS_RGB表示彩色圖像。*/
	jpeg_set_defaults(&jcs);
	jpeg_set_quality(&jcs, JPEG_QUALITY, TRUE);/*[0-100],if 100,quality is best,but size is biggest*/ 
	jpeg_start_compress(&jcs, TRUE);	
	jcs_row_stride = bmp.bmWidth*jcs.input_components; /* JSAMPLEs per row in image_buffer */


	BITMAPINFOHEADER bih = {0};
    bih.biBitCount = bmp.bmBitsPixel;
	/* BI_RGB;16位中,最低的5位表示蓝色分量,中间的5位表示绿色分量,高的5位表示红色分量,一共占用了15位,最高的一位保留,设为0 */
    bih.biCompression = BI_RGB;
    bih.biHeight = bmp.bmHeight;
	bih.biPlanes = bmp.bmPlanes;//总是为1。
    bih.biSize = sizeof(BITMAPINFOHEADER);
    bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;
    bih.biWidth = bmp.bmWidth;

	/* 取源,像素数据信息.begin */
	BYTE * bits = (BYTE *)malloc( bmp.bmWidth*4*(bmp.bmHeight+1) );/* 分配尽可能大的内存 */
	
	// Retrieve the color table (RGBQUAD array) and the bits 
	if (!GetDIBits(hDC, HBITMAP(bitmap), 0, (WORD) bmp.bmHeight, bits, (LPBITMAPINFO)&bih, 
		DIB_RGB_COLORS)) {
			g_log.Add("WriteJPGFile  GetDIB error");
			return FALSE;
	}	
	/* 取源,像素数据信息.end */

	src_row_stride = DWORDAlign(bmp.bmWidthBytes*8);/* 返回每行字节数,必须DWORD对齐 */

	/* 对源缓存中的像素做预处理.begin */
	/* int BitPerPixel = GetDeviceCaps(hDC,BITSPIXEL); 取hDC中的设备颜色深度 */
	if(bmp.bmBitsPixel==32) /* 32 map to 24 */
	{		
		int i=0;
		int j=0;
		for (; j < bmp.bmWidth*bmp.bmHeight*4; i+=3, j+=4)
		{
			*(bits+i)=*(bits+j+2);
			*(bits+i+1)=*(bits+j+1);
			*(bits+i+2)=*(bits+j);
		}
	} else if( bmp.bmBitsPixel==24 ) /* 24 map to 24(Only need exchange the color component) */
	{
		BYTE * bitsT = (BYTE *)malloc(bmp.bmWidth*(bmp.bmHeight+1)*4);/* 分配尽可能大的临时空间 */
		memset(bitsT, 0, bmp.bmWidth*(bmp.bmHeight+1)*4 );

		for(int row=0;row<bmp.bmHeight;row++)
			for(int col=0;col<bmp.bmWidth;col++)
			{
				BYTE *pSrc = bits  + row*src_row_stride + col*3;
				BYTE *pDst = bitsT + row*jcs_row_stride + col*3;

				*(pDst)  = *(pSrc+2),*(pDst+1)= *(pSrc+1),*(pDst+2)= *pSrc;
			}

		memcpy(bits,bitsT,bmp.bmWidth*(bmp.bmHeight+1)*3);
		free(bitsT);
	} else if(bmp.bmBitsPixel==16) /* 16 map to 24 */
	{		
		BYTE * bitsT = (BYTE *)malloc(bmp.bmWidth*(bmp.bmHeight+1)*4);/* 分配尽可能大的临时空间 */
		memset(bitsT, 0, bmp.bmWidth*(bmp.bmHeight+1)*4 );

		for(int row=0;row<bmp.bmHeight;row++)
			for(int col=0;col<bmp.bmWidth;col++)
			{
				BYTE *pSrc = bits  + row*src_row_stride + col*2;
				BYTE *pDst = bitsT + row*jcs_row_stride + col*3;

				unsigned short clr16 = *(pSrc) | *(pSrc+1)<<8;
				
				*(pDst)  = R1555(clr16);
				*(pDst+1)= G1555(clr16);
				*(pDst+2)= B1555(clr16);
			}

		memcpy(bits,bitsT,bmp.bmWidth*(bmp.bmHeight+1)*3);
		free(bitsT);
	}
	/* 对源缓存中的像素做预处理.end */

	/* 使用While语句进行,逐行壓縮 */
	while (jcs.next_scanline < jcs.image_height) {
            row_pointer[0] = & bits[(jcs.image_height - jcs.next_scanline - 1) * jcs_row_stride];
 		    /* row_pointer[0] = & bits[jcs.next_scanline * row_stride]; 不做水平翻转*/
            jpeg_write_scanlines(&jcs, row_pointer, 1);		
	}
	
	jpeg_finish_compress(&jcs);
	fclose(outfile);
	free(bits);	
	jpeg_destroy_compress(&jcs);

	return TRUE;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kagula086

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值