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

来源:互联网 发布:什么是复杂网络 编辑:程序博客网 时间:2024/05/29 04:04

 

 

 一、先讲编译过程:

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-714150int 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,表示灰度图, 如果是彩色位图,则为3cinfo.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;// 在图像缓冲区里每天的SAMPLEswhile (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;}