利用 IJG 的 jpeg 库。
关于如何使用 IJG jpeg 库,请参考前面的文章:
函数原型:
/************************************************************************** 压缩图像到jpeg格式,如果压缩前的图像不是24位图,则强行转换为24位图后压缩 **************************************************************************/ // strSourceFileName - 原始bmp文件名 // strDestFileName - 想要生成的jpg文件名 // quality - 图象质量 1-100的数字,比如 60 void 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的数字,比如 60 void 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