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

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

 

利用 IJG 的 jpeg 库。

 

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

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

 

函数原型:

/**************************************************************************
压缩图像到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

 

 

你可能感兴趣的:(jpg)