VC6怎样将bmp格式图象转换为jpg格式文件?

本文介绍如何使用IJG jpeg库将BMP格式的图像转换为jpg格式,包括函数调用方式、执行时间计算及完整代码示例。

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

VC6怎样将bmp格式图象转换为jpg格式文件?

 

利用 IJG 的 jpeg 库。

 

关于如何使用 IJG jpeg 库,请参考前面的文章:

VC6下编译IJG库(用于读取和生成jpg格式图片文件)

 

函数原型:

Cpp代码 复制代码  收藏代码
  1. /**************************************************************************  
  2. 压缩图像到jpeg格式,如果压缩前的图像不是24位图,则强行转换为24位图后压缩  
  3. **************************************************************************/  
  4. // strSourceFileName - 原始bmp文件名   
  5. // strDestFileName - 想要生成的jpg文件名   
  6. // quality - 图象质量 1-100的数字,比如 60   
  7. void bmptojpg24x(const char *strSourceFileName, const char *strDestFileName, int quality);  
/**************************************************************************
压缩图像到jpeg格式,如果压缩前的图像不是24位图,则强行转换为24位图后压缩
**************************************************************************/
// strSourceFileName - 原始bmp文件名
// strDestFileName - 想要生成的jpg文件名
// quality - 图象质量 1-100的数字,比如 60
void bmptojpg24x(const char *strSourceFileName, const char *strDestFileName, int quality);
 

 

先列出调用方式:

Cpp代码 复制代码  收藏代码
  1. // 将生成的 bmp 转换成 jpg 格式   
  2. bmptojpg24x("clipboard.bmp""clipboard.jpg", 60);   
  3. // 压缩比率:60%   
  4. //  575* 865   bmp  1,989,568 字节 jpg  46,364 字节 大约 50毫秒   
  5. // 1000*1498   bmp  5,992,068 字节 jpg 225,699 字节 大约200毫秒   
  6. // 1335*2000   bmp 10,680,068 字节 jpg 205,151 字节 大约300毫秒  
				// 将生成的 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毫秒
 

下面的调用代码加入了执行时间计算:

Cpp代码 复制代码  收藏代码
  1. // 下面的代码加上了转换所需时间的计算   
  2. // GetTickCount返回(retrieve)从操作系统启动到现在所经过(elapsed)的毫秒数,它的返回值是DWORD。    
  3. DWORD t0 = ::GetTickCount();   
  4. bmptojpg24x("clipboard.bmp""clipboard.jpg", 60);   
  5. DWORD t1 = ::GetTickCount();   
  6. char tstr[32]; sprintf(tstr, "bmptojpg24 use %d ms", t1 - t0); MessageBox(tstr);  
				// 下面的代码加上了转换所需时间的计算
				// 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);
 

下面是完整的原代码:

Cpp代码 复制代码  收藏代码
  1. /**************************************************************************  
  2. 压缩图像到jpeg格式,如果压缩前的图像不是24位图,则强行转换为24位图后压缩  
  3. **************************************************************************/  
  4. // strSourceFileName - 原始bmp文件名   
  5. // strDestFileName - 想要生成的jpg文件名   
  6. // quality - 图象质量 1-100的数字,比如 60   
  7. void bmptojpg24x(const char *strSourceFileName, const char *strDestFileName, int quality)   
  8. {   
  9.     BITMAPFILEHEADER bfh;       // bmp文件头   
  10.     BITMAPINFOHEADER bih;       // bmp头信息   
  11.     RGBQUAD rq[256];            // 调色板   
  12.     int i=0;   
  13.   
  14.     BYTE *data= NULL;//new BYTE[bih.biWidth*bih.biHeight];   
  15.     BYTE *pData24 = NULL;//new BYTE[bih.biWidth*bih.biHeight];   
  16.     int nComponent = 0;   
  17.   
  18.     // 打开图像文件   
  19.     FILE *f = fopen(strSourceFileName,"rb");   
  20.     if (f==NULL)   
  21.     {   
  22.         TRACE("Open file error!\n");   
  23.         ::MessageBox(0, "Open file error!""bmptojpg24", MB_OK);   
  24.         return;   
  25.     }   
  26.     // 读取文件头   
  27.     fread(&bfh,sizeof(bfh),1,f);   
  28.     // 读取图像信息   
  29.     fread(&bih,sizeof(bih),1,f);   
  30.     // 为了简单,在本例中,只演示8位索引图像   
  31.     switch (bih.biBitCount)    
  32.     {   
  33.     case 8:   
  34.         if (bfh.bfOffBits-1024<54)    
  35.         {   
  36.             fclose(f);   
  37.             return;   
  38.         }   
  39.         data= new BYTE[bih.biWidth*bih.biHeight];   
  40.         pData24 = new BYTE[bih.biWidth*bih.biHeight*3];   
  41.   
  42.         // 定位调色板,并读取调色板   
  43.         fseek(f,bfh.bfOffBits-1024,SEEK_SET);      
  44.         fread(rq,sizeof(RGBQUAD),256,f);   
  45.         // 读取位图   
  46.         fread(data,bih.biWidth*bih.biHeight,1,f);   
  47.         fclose(f);   
  48.         nComponent = 3;   
  49.         for (i=0;i<bih.biWidth * bih.biHeight ;i++)   
  50.         {   
  51.             pData24[i*3] = rq[data[i]].rgbRed;   
  52.             pData24[i*3+1] = rq[data[i]].rgbGreen;   
  53.             pData24[i*3+2] = rq[data[i]].rgbBlue;   
  54.         }   
  55.         break;   
  56.     case 24:   
  57.         {   
  58.             data= new BYTE[bih.biWidth*bih.biHeight*3];   
  59.             pData24 = new BYTE[bih.biWidth*bih.biHeight*3];   
  60.             fseek(f,bfh.bfOffBits,SEEK_SET);       
  61.             fread(data,bih.biWidth*bih.biHeight*3,1,f);   
  62.             fclose(f);   
  63.             for (i = 0;i<bih.biWidth*bih.biHeight;i++)   
  64.             {   
  65.                 pData24[i*3] = data[i*3+2];   
  66.                 pData24[i*3+1] = data[i*3+1];   
  67.                 pData24[i*3+2] = data[i*3];   
  68.             }   
  69.             nComponent = 3;   
  70.             break;   
  71.         }   
  72.     case 32:   
  73.         {   
  74.             data= new BYTE[bih.biWidth*bih.biHeight*4];   
  75.             pData24 = new BYTE[bih.biWidth*bih.biHeight*3];   
  76.             fseek(f,bfh.bfOffBits,SEEK_SET);       
  77.             fread(data,bih.biWidth*bih.biHeight*4,1,f);   
  78.             fclose(f);   
  79.             for (i = 0;i<bih.biWidth*bih.biHeight;i++)   
  80.             {   
  81.                 pData24[i*3] = data[i*4+2];   
  82.                 pData24[i*3+1] = data[i*4+1];   
  83.                 pData24[i*3+2] = data[i*4];   
  84.             }   
  85.             nComponent = 3;   
  86.             break;   
  87.         }   
  88.     default:   
  89.         {   
  90.             char tmpbuf[32];   
  91.             sprintf(tmpbuf, "bih.biBitCount=%d not supported", bih.biBitCount);   
  92.             ::MessageBox(0, tmpbuf, "bmptojpg24", MB_OK);   
  93.             fclose(f);   
  94.             return;   
  95.         }   
  96.     }   
  97.   
  98.     // 以上图像读取完毕   
  99.   
  100.     struct jpeg_compress_struct jcs;   
  101.     struct jpeg_error_mgr jem;   
  102.     jcs.err = jpeg_std_error(&jem);   
  103.   
  104.     jpeg_create_compress(&jcs);   
  105.   
  106.     f=fopen(strDestFileName,"wb");   
  107.     if (f==NULL)    
  108.     {   
  109.         delete [] data;   
  110.         //delete [] pDataConv;   
  111.         return;   
  112.     }   
  113.     jpeg_stdio_dest(&jcs, f);   
  114.     jcs.image_width = bih.biWidth;          // 为图的宽和高,单位为像素    
  115.     jcs.image_height = bih.biHeight;   
  116.     jcs.input_components = nComponent;          // 1,表示灰度图, 如果是彩色位图,则为3    
  117.     if (nComponent==1)   
  118.         jcs.in_color_space = JCS_GRAYSCALE; //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像    
  119.     else    
  120.         jcs.in_color_space = JCS_RGB;   
  121.   
  122.     jpeg_set_defaults(&jcs);       
  123.     //jpeg_set_quality (&jcs, 60, true);   
  124.     jpeg_set_quality (&jcs, quality, true);   
  125.   
  126.     jpeg_start_compress(&jcs, TRUE);   
  127.   
  128.     JSAMPROW row_pointer[1];            // 一行位图   
  129.     int row_stride;                     // 每一行的字节数    
  130.   
  131.     row_stride = jcs.image_width*nComponent;        // 如果不是索引图,此处需要乘以3   
  132.   
  133.     // 对每一行进行压缩   
  134.     while (jcs.next_scanline < jcs.image_height) {   
  135.         row_pointer[0] = & pData24[(jcs.image_height-jcs.next_scanline-1) * row_stride];   
  136.         jpeg_write_scanlines(&jcs, row_pointer, 1);   
  137.     }   
  138.   
  139.     jpeg_finish_compress(&jcs);   
  140.   
  141.     jpeg_destroy_compress(&jcs);   
  142.   
  143.     fclose(f);   
  144.     delete [] data;   
  145.     delete [] pData24;   
  146.   
  147.     //::MessageBox(0, "ok", "bmptojpg24", MB_OK);   
  148. }  
/**************************************************************************
压缩图像到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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值