VC/MFC怎样将位图CBitmap对象保存成为jpg格式文件?
前面几篇文章中已经实现了将 CBitmap 对象保存为 bmp 格式文件,以及将 bmp 格式转换成 jpg 格式,中间绕了一道弯,为什么不直接将 CBitmap 对象直接存为 jpg 格式呢?
可以借鉴下面的资料,该文中实现了先将 bmp 文件加载为 CBitmap 对象,然后使用 IJG jpeg 库函数保存为 jpg 格式文件:
VC中利用IJG库实现图片由BMP转JPG格式
http://hi.baidu.com/andyleesoft/blog/item/d6f354003fcbbe024bfb5113.html
我对该文中的代码进行了测试和调整,分解成两个函数:
1. 将CBitmap对象存为jpg格式文件,命名为 IJG_bmp2jpg;
1. 将bmp文件加载为CBitmap对象,然后调用第一个函数来保存为jpg格式文件。
/****函数功能:CBitmap存为JPG******/
/*入口:CBitmap对象,目标文件地址,压缩质量*/
bool IJG_bmp2jpg(CBitmap& cbmp, CString Dfilepath,int quality)
{
BITMAP bmp;
cbmp.GetBitmap(&bmp);//获取图像信息
if (bmp.bmBitsPixel<8)
{
AfxMessageBox("不支持8位以下图像转换。");
return false;
}
byte * p = new byte[bmp.bmWidth * bmp.bmHeight*bmp.bmBitsPixel/8];//创建空间,大小=像素*每像素所占字节数
cbmp.GetBitmapBits(bmp.bmWidth * bmp.bmHeight*bmp.bmBitsPixel/8,p);//将图像数据复制到内存
if (bmp.bmBitsPixel==32)//32位需要特殊处理,去掉其中透明字节,并且需要改变RGB顺序
{
for (long i=0, j=0;j<bmp.bmWidth * bmp.bmHeight*4 ;i+=3,j+=4)
{
*(p+i)=*(p+j+2);
*(p+i+1)=*(p+j+1);
*(p+i+2)=*(p+j);
}
}
/************以下利用IJG库进行格式转换******************/
struct jpeg_compress_struct jcs; /*声明JPEG压缩对象*/
struct jpeg_error_mgr jem; /*声明错误处理器*/
JSAMPLE *image_buffer=(JSAMPLE *)p; /*转换的源图像缓冲区指向之前申请的内存*/
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
int row_stride; /*每行字节数*/
jcs.err=jpeg_std_error(&jem);
jpeg_create_compress(&jcs); /*initialize the JPEG compression object.*/
FILE* f=fopen(Dfilepath,"wb"); /*建立JPEG文件*/
if(f==NULL)
{
AfxMessageBox("建立JPEG文件失败。");
fclose(f);
delete []p;
return false ;
}
jpeg_stdio_dest(&jcs, f); /*将目标文件与转换结果相关联*/
jcs.image_width = bmp.bmWidth; /* image width and height, in pixels */
jcs.image_height = bmp.bmHeight;
jcs.input_components = (bmp.bmBitsPixel/8>=3?3:bmp.bmBitsPixel/8); /* # of color components per pixel */
jcs.in_color_space = JCS_RGB; /* colorspace of input image */
jpeg_set_defaults(&jcs);
jpeg_set_quality(&jcs, quality, TRUE /* limit to baseline-JPEG values */);
jpeg_start_compress(&jcs, TRUE); /*开始压缩*/
row_stride=jcs.image_width*jcs.input_components;
while (jcs.next_scanline<jcs.image_height)
{
row_pointer[0] = & image_buffer[jcs.next_scanline * row_stride];
(void) jpeg_write_scanlines(&jcs, row_pointer, 1);
}
jpeg_finish_compress(&jcs);
fclose(f);
jpeg_destroy_compress(&jcs);
delete []p;
return true;
}
/****函数功能:bmp转JPG******/
/*入口:源文件地址,目标文件地址,压缩质量*/
bool IJG_bmp2jpg(CString Sfilepath,CString Dfilepath,int quality)
{
CBitmap cbmp;
HBITMAP hbitmap=(HBITMAP)::LoadImage(NULL,Sfilepath,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);//位图句柄,读取外部位图
if (hbitmap==NULL)
{
AfxMessageBox("源图像读取错误");
return false;
}
cbmp.Attach(hbitmap);//将外部图像引入CBITMAP
return IJG_bmp2jpg(cbmp, Dfilepath, quality);
}
调用方式如下:
//bool IJG_bmp2jpg(CString Sfilepath,CString Dfilepath,int quality)
IJG_bmp2jpg("clipboard.bmp", "clipboard2.jpg", 60);
//bool IJG_bmp2jpg(CBitmap cbm,CString Dfilepath,int quality)
IJG_bmp2jpg(*cbm, "clipboard3.jpg", 60);