您的位置:首页 > 其它

BMP转JPG(法一)VS2005环境下采用makefile编译、使用libjpeg.lib函数库

2012-04-24 17:40 501 查看

一、先讲编译过程:

1、从www.ijg.org下载源码,解压后得到文件夹jpeg-8d

2、在文件夹里新建jconfig.h文件,将jconfig.vc里的内容拷到jconfig.h中

3、编译.

Run->CMD->进入到C:\Program Files\Microsoft Visual Studio 8\VC\bin目录(不同的VC编译器目录也不一样)下

->运行vcvars32.bat文件,此时



-->到把目录定到我们的代码地方->nmake /f makefile.vc





这样就生成了我们的libjpeg.lib了





二、再讲使用libjpeg.lib库的方法(以BMP转JPG为例):

例子代码:

http://www.rayfile.com/zh-cn/files/c6a7051e-8e7a-11e1-a698-0015c55db73d/



一、建立编译环境

把libjpeg.lib 添加到你的项目中,并指定lib链接目录与头文件链接目录,我的为 ..\jpeg-8d

二、压缩步骤

1、申请并初始化jpeg压缩对象,同时要指定错误处理器

struct jpeg_compress_struct jcs;

// 声明错误处理器,并赋值给jcs.err域
struct jpeg_error_mgr jem;
jcs.err = jpeg_std_error(&jem);

   jpeg_create_compress(&jcs);




2、指定压缩后的图像所存放的目标文件,注意,目标文件应以二进制模式打开

if ((outfile = fopen(filename, "wb")) == NULL) {
  fprintf(stderr, "can't open %s\n", filename);
  return -1;
 }

jpeg_stdio_dest(&cinfo, outfile);




3、设置压缩参数,主要参数有图像宽、高、色彩通道数(1:索引图像,3:其他),色彩空间(JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像),压缩质量等,如下:

cinfo.image_width = width;    // 为图的宽和高,单位为像素
 cinfo.image_height = height;
 cinfo.input_components = depth;         // 在此为1,表示灰度图, 如果是彩色位图,则为3
 cinfo.in_color_space = JCS_GRAYSCALE;   //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像

 // jpeg_set_defaults函数一定要等设置好图像宽、高、
 // 色彩通道数计色彩空间四个参数后才能调用,
 // 因为这个函数要用到这 四个值,
 // 调用jpeg_set_defaults函数后,jpeglib库采用默认的设置对图像进行压缩
 jpeg_set_defaults(&cinfo);

// jpeg_set_defaults函数一定要等设置好图像宽、高、
 // 色彩通道数计色彩空间四个参数后才能调用,
 // 因为这个函数要用到这 四个值,调用jpeg_set_defaults函数后,
 // jpeglib库采用默认的设置对图像进行压缩
   jpeg_set_quality(&cinfo, 80 /*JPEG_QUALITY*/, TRUE );




4、上面的工作准备完成后,就可以压缩了,压缩过程非常简单,首先调用 jpeg_start_compress,然后可以对每一行进行压缩,也 可以对若干行进行压缩,甚至可以对整个的图像进行一次压缩,压缩完成后,记得要调用jpeg_finish_compress函数,如下:



jpeg_start_compress(&cinfo, TRUE);

 row_stride = width;        // 在图像缓冲区里每天的SAMPLEs
 
 while (cinfo.next_scanline < cinfo.image_height)// 对每一次进行压缩
 {
  row_pointer[0] = & data[cinfo.next_scanline * row_stride];
  (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
 }
 
 jpeg_finish_compress(&cinfo);     // 压缩完成后,记得要调用jpeg_finish_compress函数




5、最后就是释放压缩工作过程中所申请的资源了,主要就是jpeg压缩对象,由于在本例中我是直接用的局部变量,所以只需调用jpeg_destroy_compress这个函数即可,如下:

jpeg_destroy_compress(&cinfo);



四、代码改进

有网友反映我的代码运行后的效果只是一片的灰色,这里向大家道歉,因为自己没有去验证过。

于是我在原有的基础上参考了文章: http://blog.csdn.net/chenyujing1234/article/details/7730478
后,修改我的代码如下。

虽然不是全部的灰色,但还是出现图像失真的问题。有待改进。。。。

//#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <afxwin.h>
#include "jpeglib.h"

 
// 参考 http://space.itpub.net/7232789/viewspace-714150 int main()
{
	FILE *fd;							// 源文件句柄
	FILE *outfile;						// 目标文件句柄
	int ret;
	unsigned char *data;
	long sizeImage;
	char *filename = "palm2.jpg";
	int width = 670;
	int height = 503;
	int depth = 3;
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;			// 声音错误处理器,并赋值给jcs.err域					
	JSAMPROW row_pointer[1];			// 一行位图, 指向JSAMPLE row[s]
	int     row_stride;					// 每一行的字节数

	sizeImage = width*height*sizeof(unsigned char)*4;
	data = (unsigned char*)malloc(sizeImage);
 	fd = fopen("palm.bmp", "rb");// 打开要压缩的源文件
	if(!fd)
	{
		printf("ERROR1: Can not open the image.\n");
		free(data);
		return -1;
	}
	//int sizeHead = sizeof(BITMAPINFOHEADER);
	
	//fseek(fd, 1078, SEEK_SET);	//  跳过bmp文件头,直接读取掌纹图像数据
	ret = fread(data, sizeof(unsigned char)*sizeImage, 1, fd);
	if(ret == 0)
	{
		if(ferror(fd))
		{
			printf("\nERROR2: Can not read the pixel data.\n");
			free(data);
			fclose(fd);
			return -1;
		}
	}

	
	//RGB顺序调整
	for (int i=0, j=0; j < width*height*4; i+=3, j+=4)
	{
		*(data+i)=*(data+j+2);
		*(data+i+1)=*(data+j+1);
		*(data+i+2)=*(data+j);
	}

	cinfo.err = jpeg_std_error(&jerr);	// 指定错误处理器
	// 第一步: 
	//        初始化jpeg压缩对象 
	jpeg_create_compress(&cinfo);
	// 第二步: 
	//        指定压缩后的图像所存放的目标文件,目标文件以二进制模式打开
	if ((outfile = fopen(filename, "wb")) == NULL) {
		fprintf(stderr, "can't open %s\n", filename);
		return -1;
	}
	jpeg_stdio_dest(&cinfo, outfile);

	// 第三步:
	//        设置压缩参数,主要参数有图像宽、高、色彩通道数(1:索引图像,3:其他),
	//        色彩空间(JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像),压缩质量
	cinfo.image_width = width;				// 为图的宽和高,单位为像素
	cinfo.image_height = height;
	cinfo.input_components = depth;         // 在此为1,表示灰度图, 如果是彩色位图,则为3
	cinfo.in_color_space = JCS_RGB;   //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像

	// jpeg_set_defaults函数一定要等设置好图像宽、高、
	// 色彩通道数计色彩空间四个参数后才能调用,
	// 因为这个函数要用到这 四个值,
	// 调用jpeg_set_defaults函数后,jpeglib库采用默认的设置对图像进行压缩
	jpeg_set_defaults(&cinfo);

	
	// jpeg_set_defaults函数一定要等设置好图像宽、高、
	// 色彩通道数计色彩空间四个参数后才能调用,
	// 因为这个函数要用到这 四个值,调用jpeg_set_defaults函数后,
	// jpeglib库采用默认的设置对图像进行压缩
	  jpeg_set_quality(&cinfo, 50 , TRUE );

	// 第四步:
	//       上面的工作准备完成后,就可以压缩了,
	//        压缩过程非常简单,首先调用 jpeg_start_compress,
	//		  然后可以对每一行进行压缩,也 可以对若干行进行压缩,
	//        甚至可以对整个的图像进行一次压缩
	jpeg_start_compress(&cinfo, TRUE);

	row_stride = width*depth;								// 在图像缓冲区里每天的SAMPLEs
	
	while (cinfo.next_scanline < cinfo.image_height)// 对每一次进行压缩
	{
		//这里我做过修改,由于jpg文件的图像是倒的,所以改了一下读的顺序
		//这是原代码:
		//row_pointer[0] = &data[cinfo.next_scanline * row_stride];
		row_pointer[0] = &data[(cinfo.image_height - cinfo.next_scanline - 1) * row_stride];
		(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}
	
	jpeg_finish_compress(&cinfo);					// 压缩完成后,记得要调用jpeg_finish_compress函数
	// 第五步:
	//        最后就是释放压缩工作过程中所申请的资源了,
	//        主要就是jpeg压缩对象
	jpeg_destroy_compress(&cinfo);

	free(data);  
	fclose(fd);
	fclose(outfile);

	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: