VC6怎样将bmp格式图象转换为jpg格式文件?
VC6怎样将bmp格式图象转换为jpg格式文件?
?
利用 IJG 的 jpeg 库。
?
关于如何使用 IJG jpeg 库,请参考前面的文章:
VC6下编译IJG库(用于读取和生成jpg格式图片文件)
?
函数原型:
/**************************************************************************压缩图像到jpeg格式,如果压缩前的图像不是24位图,则强行转换为24位图后压缩**************************************************************************/// strSourceFileName - 原始bmp文件名// strDestFileName - 想要生成的jpg文件名// quality - 图象质量 1-100的数字,比如 60void bmptojpg24x(const char *strSourceFileName, const char *strDestFileName, int quality);?
?
先列出调用方式:
// 将生成的 bmp 转换成 jpg 格式bmptojpg24x("clipboard.bmp", "clipboard.jpg", 60);// 压缩比率:60%// 575* 865 bmp 1,989,568 字节 jpg 46,364 字节 大约 50毫秒// 1000*1498 bmp 5,992,068 字节 jpg 225,699 字节 大约200毫秒// 1335*2000 bmp 10,680,068 字节 jpg 205,151 字节 大约300毫秒?
下面的调用代码加入了执行时间计算:
// 下面的代码加上了转换所需时间的计算// GetTickCount返回(retrieve)从操作系统启动到现在所经过(elapsed)的毫秒数,它的返回值是DWORD。 DWORD t0 = ::GetTickCount();bmptojpg24x("clipboard.bmp", "clipboard.jpg", 60);DWORD t1 = ::GetTickCount();char tstr[32]; sprintf(tstr, "bmptojpg24 use %d ms", t1 - t0); MessageBox(tstr);?
下面是完整的原代码:
/**************************************************************************压缩图像到jpeg格式,如果压缩前的图像不是24位图,则强行转换为24位图后压缩**************************************************************************/// strSourceFileName - 原始bmp文件名// strDestFileName - 想要生成的jpg文件名// quality - 图象质量 1-100的数字,比如 60void bmptojpg24x(const char *strSourceFileName, const char *strDestFileName, int quality){BITMAPFILEHEADER bfh;// bmp文件头BITMAPINFOHEADER bih;// bmp头信息RGBQUAD rq[256];// 调色板int i=0;BYTE *data= NULL;//new BYTE[bih.biWidth*bih.biHeight];BYTE *pData24 = NULL;//new BYTE[bih.biWidth*bih.biHeight];int nComponent = 0;// 打开图像文件FILE *f = fopen(strSourceFileName,"rb");if (f==NULL){TRACE("Open file error!\n");::MessageBox(0, "Open file error!", "bmptojpg24", MB_OK);return;}// 读取文件头fread(&bfh,sizeof(bfh),1,f);// 读取图像信息fread(&bih,sizeof(bih),1,f);// 为了简单,在本例中,只演示8位索引图像switch (bih.biBitCount) {case 8:if (bfh.bfOffBits-1024<54) {fclose(f);return;}data= new BYTE[bih.biWidth*bih.biHeight];pData24 = new BYTE[bih.biWidth*bih.biHeight*3];// 定位调色板,并读取调色板fseek(f,bfh.bfOffBits-1024,SEEK_SET);fread(rq,sizeof(RGBQUAD),256,f);// 读取位图fread(data,bih.biWidth*bih.biHeight,1,f);fclose(f);nComponent = 3;for (i=0;i<bih.biWidth * bih.biHeight ;i++){pData24[i*3] = rq[data[i]].rgbRed;pData24[i*3+1] = rq[data[i]].rgbGreen;pData24[i*3+2] = rq[data[i]].rgbBlue;}break;case 24:{data= new BYTE[bih.biWidth*bih.biHeight*3];pData24 = new BYTE[bih.biWidth*bih.biHeight*3];fseek(f,bfh.bfOffBits,SEEK_SET);fread(data,bih.biWidth*bih.biHeight*3,1,f);fclose(f);for (i = 0;i<bih.biWidth*bih.biHeight;i++){pData24[i*3] = data[i*3+2];pData24[i*3+1] = data[i*3+1];pData24[i*3+2] = data[i*3];}nComponent = 3;break;}case 32:{data= new BYTE[bih.biWidth*bih.biHeight*4];pData24 = new BYTE[bih.biWidth*bih.biHeight*3];fseek(f,bfh.bfOffBits,SEEK_SET);fread(data,bih.biWidth*bih.biHeight*4,1,f);fclose(f);for (i = 0;i<bih.biWidth*bih.biHeight;i++){pData24[i*3] = data[i*4+2];pData24[i*3+1] = data[i*4+1];pData24[i*3+2] = data[i*4];}nComponent = 3;break;}default:{char tmpbuf[32];sprintf(tmpbuf, "bih.biBitCount=%d not supported", bih.biBitCount);::MessageBox(0, tmpbuf, "bmptojpg24", MB_OK);fclose(f);return;}}// 以上图像读取完毕struct jpeg_compress_struct jcs;struct jpeg_error_mgr jem;jcs.err = jpeg_std_error(&jem);jpeg_create_compress(&jcs);f=fopen(strDestFileName,"wb");if (f==NULL) {delete [] data;//delete [] pDataConv;return;}jpeg_stdio_dest(&jcs, f);jcs.image_width = bih.biWidth; // 为图的宽和高,单位为像素 jcs.image_height = bih.biHeight;jcs.input_components = nComponent;// 1,表示灰度图, 如果是彩色位图,则为3 if (nComponent==1)jcs.in_color_space = JCS_GRAYSCALE; //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像 else jcs.in_color_space = JCS_RGB;jpeg_set_defaults(&jcs);//jpeg_set_quality (&jcs, 60, true);jpeg_set_quality (&jcs, quality, true);jpeg_start_compress(&jcs, TRUE);JSAMPROW row_pointer[1];// 一行位图int row_stride;// 每一行的字节数 row_stride = jcs.image_width*nComponent;// 如果不是索引图,此处需要乘以3// 对每一行进行压缩while (jcs.next_scanline < jcs.image_height) { row_pointer[0] = & pData24[(jcs.image_height-jcs.next_scanline-1) * row_stride]; jpeg_write_scanlines(&jcs, row_pointer, 1);}jpeg_finish_compress(&jcs);jpeg_destroy_compress(&jcs);fclose(f);delete [] data;delete [] pData24;//::MessageBox(0, "ok", "bmptojpg24", MB_OK);}?
?
本文所附原代码参考了下面的资料:
利用IJG JPEG Library压缩图像为jpg格式 http://www.vckbase.com/document/viewdoc/?id=1790
?
作了如下改进:
1. 增加了对32位图象的处理,只取 RGB分量,忽略 alpha值;
2. 增加图象质量参数 quality ,可以指定图片压缩 比率,更方便调用;
3. 少量调试信息 MessageBox 。
?
更多参考资料:
1. VC2005 使用IJG读写JPEG格式文件
http://iysm.net/?p=7
2. IJG是什么,有哪些优点 IJG VS IJL?
http://www.cr173.com/html/11042_1.html
3. VC中利用IJG库实现图片由BMP转JPG格式
http://hi.baidu.com/andyleesoft/blog/item/d6f354003fcbbe024bfb5113.html
?
?