打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Linux下利用libjpeg实现bmp与jpg相互转换C代码
                            "Linux下利用libjpeg实现bmp与jpg相互转换C代码":关键词linux 利用 libjpeg 实现 bmp jpg 相互 转换 c 代码

      最近在研究libjpeg库的使用,主要是实现bmp位图和jpg图之间的格式互相转换。系统是ubuntu10.04,v6b版本的jpeg库。下载地址:http://www.ijg.org/files/jpegsrc.v6b.tar.gz。代码已经成功移植到tq2440 arm-linux中,能够正常运行,移植方法看这里http://blog.chinaunix.net/uid-11765716-id-172491.html。

首先说说jpg转bmp,参考了http://blog.马开东/mcgrady_tracy/article/details/7439066,并做了修改与完善。代码如下:

  1 #include <stdio.h>  2 #include <setjmp.h>  3 #include <string.h>  4 #include <stdlib.h>  5 #include <jpeglib.h>  6   7  //将value低8位写入array[offset],高8位写入array[offset+1]  8 #define put_2b(array,offset,value)    9          (array[offset] = (char) ((value) & 0xff),  10           array[offset+1] = (char) (((value) >> 8) & 0xff)) 11 #define put_4b(array,offset,value)   12          (array[offset] = (char) ((value) & 0xff),  13           array[offset+1] = (char) (((value) >> 8) & 0xff),  14           array[offset+2] = (char) (((value) >> 16) & 0xff),  15           array[offset+3] = (char) (((value) >> 24) & 0xff)) 16  //写文件头 17 void write_bmp_header(j_decompress_ptr cinfo, file *output_file) 18  { 19          char bmpfileheader[14]; 20          char bmpinfoheader[40]; 21          long headersize, bfsize; 22          int bits_per_pixel, cmap_entries; 23   24         struct colormap{  //颜色表结构 25         uint8 blue; 26         uint8 green; 27         uint8 red; 28         uint8 reserved; 29         }; 30         int step; 31         int i=0; 32         /* compute colormap size and total file size */ 33          if (cinfo->out_color_space == jcs_rgb) { 34                  if (cinfo->quantize_colors) { 35                          /* colormapped rgb */ 36                          bits_per_pixel = 8; 37                          cmap_entries = 256; 38                  } else { 39                          /* unquantized, full color rgb */ 40                          bits_per_pixel = 24; 41                          cmap_entries = 0; 42                  } 43          } else { 44                  /* grayscale output.  we need to fake a 256-entry colormap. */ 45                  bits_per_pixel = 8; 46                  cmap_entries = 256; 47          } 48   49         step = cinfo->output_width * cinfo->output_components; 50   51         while ((step & 3) != 0) step++; 52   53         /* file size */ 54          headersize = 14 + 40 + cmap_entries * 4; /* header and colormap */ 55   56         bfsize = headersize + (long) step * (long) cinfo->output_height; 57   58         /* set unused fields of header to 0 */ 59          memset(bmpfileheader, 0, sizeof(bmpfileheader)); 60          memset(bmpinfoheader, 0 ,sizeof(bmpinfoheader)); 61   62         /* fill the file header */ 63          bmpfileheader[0] = 0x42;/* first 2 bytes are ascii 'b', 'm' */ 64          bmpfileheader[1] = 0x4d; 65          put_4b(bmpfileheader, 2, bfsize); /* bfsize */ 66          /* we leave bfreserved1 & bfreserved2 = 0 */ 67          put_4b(bmpfileheader, 10, headersize); /* bfoffbits */ 68   69         /* fill the info header (microsoft calls this a bitmapinfoheader) */ 70          put_2b(bmpinfoheader, 0, 40);   /* bisize */ 71          put_4b(bmpinfoheader, 4, cinfo->output_width); /* biwidth */ 72          put_4b(bmpinfoheader, 8, cinfo->output_height); /* biheight */ 73          put_2b(bmpinfoheader, 12, 1);   /* biplanes - must be 1 */ 74          put_2b(bmpinfoheader, 14, bits_per_pixel); /* bibitcount */ 75          /* we leave bicompression = 0, for none */ 76          /* we leave bisizeimage = 0; this is correct for uncompressed data */ 77          if (cinfo->density_unit == 2) { /* if have density in dots/cm, then */ 78                  put_4b(bmpinfoheader, 24, (int32) (cinfo->x_density*100)); /* xpels/m */ 79                  put_4b(bmpinfoheader, 28, (int32) (cinfo->y_density*100)); /* xpels/m */ 80          } 81          put_2b(bmpinfoheader, 32, cmap_entries); /* biclrused */ 82          /* we leave biclrimportant = 0 */ 83         //写入文件头 84         if (fwrite(bmpfileheader, 1, 14, output_file) != (size_t) 14) { 85                  printf("write bmpfileheader error\n"); 86          } 87          //写入信息头 88          if (fwrite(bmpinfoheader, 1, 40, output_file) != (size_t) 40) { 89                  printf("write bmpinfoheader error\n"); 90          } 91         //写入颜色表,灰度图 92         if (cmap_entries ==256) { 93             struct colormap rgb[256]; 94             for(i=0;i<256;i++) 95                 {     96                     rgb[i].blue=i; 97                     rgb[i].green=i; 98                     rgb[i].red=i; 99                     rgb[i].reserved=0;100                 }101              //写入颜色表102             if (fwrite(rgb, 1, sizeof(struct colormap)*256, output_file) <0) {103                  printf("write color error\n");104          }105          }106  }107  //写入位图数据108 void write_pixel_data(j_decompress_ptr cinfo, unsigned char *output_buffer, file *output_file)109  {110          int rows, cols;111          int row_width;112          int step;113          unsigned char *tmp = null;114  115         unsigned char *pdata;116  117         row_width = cinfo->output_width * cinfo->output_components;118          step = row_width;119          while ((step & 3) != 0) step++;120  121         pdata = (unsigned char *)malloc(step);122          memset(pdata, 0, step);123         //每次写入一行,并且调整rgb顺序。windows位图存储顺序是bgr,而libjpeg库是rgb124         tmp = output_buffer + row_width * (cinfo->output_height - 1);125          if(cinfo->output_components==3){ //24bit真彩图126          for (rows = 0; rows < cinfo->output_height; rows++) {127                  for (cols = 0; cols < row_width; cols += 3) {128                          pdata[cols + 2] = tmp[cols + 0];129                          pdata[cols + 1] = tmp[cols + 1];130                          pdata[cols + 0] = tmp[cols + 2];131                  }132                  tmp -= row_width;133                  fwrite(pdata, 1, step, output_file);134          }135         }136         else //cinfo->output_components==1,8bit灰度图137         {138             for (rows = 0; rows < cinfo->output_height; rows++) {139                  for (cols = 0; cols < row_width; cols ++) {140                          pdata[cols] = tmp[cols];141                  }142                  tmp -= row_width;143                  fwrite(pdata, 1, step, output_file);144          }145         }146  147         free(pdata);148  }149  //参考了libjpeg库里的example.c150 int read_jpeg_file(const char *input_filename, const char *output_filename)151  {152          struct jpeg_decompress_struct cinfo;153          struct jpeg_error_mgr jerr;154          file *input_file;155          file *output_file;156          js amparray buffer;157          int row_width;158  159         unsigned char *output_buffer;160          unsigned char *tmp = null;161  162         cinfo.err = jpeg_std_error(&jerr);163  164         if ((input_file = fopen(input_filename, "rb")) == null) {165                  fprintf(stderr, "can't open %s\n", input_filename);166                  return -1;167          }168  169         if ((output_file = fopen(output_filename, "wb")) == null) {170  171                 fprintf(stderr, "can't open %s\n", output_filename);172                  return -1;173          }174  175         jpeg_create_decompress(&cinfo);176  177         /* specify data source for decompression */178          jpeg_stdio_src(&cinfo, input_file);179  180         /* read file header, set default decompression parameters */181          (void) jpeg_read_header(&cinfo, true);182  183         /* start decompressor */184          (void) jpeg_start_decompress(&cinfo);185  186         row_width = cinfo.output_width * cinfo.output_components;187  188         buffer = (*cinfo.mem->alloc_sarray)189                  ((j_common_ptr) &cinfo, jpool_image, row_width, 1);190         //写bmp文件头191         write_bmp_header(&cinfo, output_file);192         //分配bmp缓冲区193         output_buffer = (unsigned char *)malloc(row_width * cinfo.output_height);194          memset(output_buffer, 0, row_width * cinfo.output_height);195          tmp = output_buffer;196  197         /* process data */198          while (cinfo.output_scanline < cinfo.output_height) {199                  (void) jpeg_read_scanlines(&cinfo, buffer, 1);200  201                 memcpy(tmp, *buffer, row_width);202                  tmp += row_width;203          }204         //写bmp数据205         write_pixel_data(&cinfo, output_buffer, output_file);206  207         free(output_buffer);208  209         (void) jpeg_finish_decompress(&cinfo);210  211         jpeg_destroy_decompress(&cinfo);212  213         /* close files, if we opened them */214          fclose(input_file);215          fclose(output_file);216         return 0;217  }218  219 int main(int argc, char *argv[])220  {221          if (argc < 3) {222                  //read_jpeg_file("tt.jpg", "tt.bmp");223                  printf("use:appname inputfile outputfile!\n");224          } else {225                  read_jpeg_file(argv[1], argv[2]);226          }227          return 0;228  }229  

代码中已经加了注释,编译方法:gcc jpg2bmp.c -ljpeg -o jpg2bmp 。 交叉编译:arm-linux-gcc jpg2bmp.c -ljpeg -o jpg2bmp。其中libjpeg库的移植可以参考:http://blog.chinaunix.net/uid-11765716-id-172491.html。运行方法:

./jpg2bmp test.jpg test.bmp ,其中test.jpg是测试图像。

    bmp转jpg代码可以参考:http://www.makaidong.com/tiandsp/archive/2012/11/30/2796758.html,我发现网上很多利用libjpeg实现jpg转bmp的代码都有些问题,不能直接使用。

此文来自: 马开东博客 转载请注明出处 网址: http://www.makaidong.com

我对代码经过修改整理后,能够编译通过并且正确实现压缩24bit真彩图或者8bit灰度图。代码如下:

  1 /*  2  * bmp2jpg.c  3  *  4  *  created on: jun 16, 2013  5  *      author: root  6  */  7 #include <stdio.h>  8 #include <setjmp.h>  9 #include <string.h> 10 #include <stdlib.h> 11 #include <jpeglib.h> 12  13 file *bmpfile;//输入文件 14 int image_width,image_height,image_size,bits_per_pixel,headersize,depth; 15 unsigned char *src_data;//位图数据 16  17 int get_2b(unsigned char*a,int offset) 18 { 19     return a[offset+1]<<8|a[offset]; 20 } 21 int get_4b(unsigned char*a,int offset) 22 { 23     return (a[offset+3]<<24)|(a[offset+2]<<16)|(a[offset+1]<<8)|a[offset]; 24 } 25 //读取位图文件头和位图数据 26 void read_bmp_header(char *bmpfilename) 27 { 28     unsigned char bmpfileheader[14];//文件头 29     unsigned char bmpinfoheader[40];//信息头 30     bmpfile=fopen(bmpfilename,"r");// 31     if(bmpfile<0) 32         printf("open bmp file error!\n"); 33     printf("open bmp file success!\n"); 34     //读取bmp文件头 35     fread(bmpfileheader,14,1,bmpfile); 36     int type=get_2b(bmpfileheader,0); 37     printf("type=0x%x\n",type); 38     int filesize=get_4b(bmpfileheader,2); 39     printf("filesize=%d bytes\n",filesize); 40     headersize=get_4b(bmpfileheader,10); 41     printf("headersize=%d bytes\n",headersize); 42     if(headersize>54) 43         printf("colormap size=%d bytes\n",headersize-54); 44     //读取bmp信息头 45     fseek(bmpfile,14,seek_set); 46     fread(bmpinfoheader,40,1,bmpfile); 47     image_width=get_4b(bmpinfoheader,4); 48     /*图像的宽度必须被4整除,否则jpg图像会变形!!! 49     这个很多代码里都没有说明,我在压缩图片时发现有些图片能够正确压缩,有些图片压缩后变形 50     经过仔细研究发现是宽度有问题*/ 51     while (image_width%4!=0) 52         image_width++; 53     printf("weight=%d\n",image_width); 54     image_height=get_4b(bmpinfoheader,8); 55     printf("height=%d\n",image_height); 56     bits_per_pixel=get_2b(bmpinfoheader,14); 57     printf("bits_per_pixel=%d\n",bits_per_pixel); 58     depth=bits_per_pixel/8; 59     image_size=image_width*image_height*depth; 60     src_data=(unsigned char *)malloc(image_size); 61     fseek(bmpfile,headersize,seek_set); 62     fread(src_data,sizeof(unsigned char)*image_size,1,bmpfile); 63     fclose(bmpfile); 64 } 65 //参考了libjpeg库里的example.c 66 void write_jpeg_file (char * outfilename, unsigned char * buffer,int quality) 67 { 68     struct jpeg_compress_struct cinfo; 69     struct jpeg_error_mgr jerr; 70     file * outfile; 71     unsigned char *dst_data; 72     int i,j; 73     //char *point; 74     js amprow row_pointer[1]; 75     //js amparray buffer; 76     int row_stride; 77     cinfo.err = jpeg_std_error(&jerr); 78     jpeg_create_compress(&cinfo); 79     //打开输出jpg文件 80     if ((outfile = fopen(outfilename, "w+")) == null) { 81     fprintf(stderr, "can't open %s\n", outfilename); 82     exit(1); 83     } 84  85     jpeg_stdio_dest(&cinfo, outfile); 86     cinfo.image_width = image_width;     /* image width and height, in pixels */ 87     cinfo.image_height = image_height; 88     cinfo.input_components = depth;        /* # of color components per pixel */ 89     cinfo.in_color_space = (depth==3) ? jcs_rgb : jcs_grayscale;     /* colorspace of input image */ 90  91     jpeg_set_defaults(&cinfo); 92     jpeg_set_quality(&cinfo, quality, true /* limit to baseline-jpeg values */); 93     dst_data=(unsigned char *)malloc(image_size*sizeof(unsigned char)); 94     //调整rgb顺序bgr->rgb 95     for(i=0;i<image_height;i++){ 96         for(j=0;j<image_width;j++) 97         { 98             if(depth==1)//灰度图 99                 *(dst_data+i*image_width+j)=*(src_data+i*image_width+j);100             else //真彩图101                 {102                     *(dst_data+i*image_width*depth+j*3+0)=*(src_data+i*image_width*depth+j*3+2);103                     *(dst_data+i*image_width*depth+j*3+1)=*(src_data+i*image_width*depth+j*3+1);104                     *(dst_data+i*image_width*depth+j*3+2)=*(src_data+i*image_width*depth+j*3+0);105                 }106         }107     }108     jpeg_start_compress(&cinfo, true);109 110     row_stride = image_width * cinfo.input_components;    /* js amples per row in image_buffer */111     112     while (cinfo.next_scanline < cinfo.image_height) {113          row_pointer[0] = & dst_data[(cinfo.image_height - cinfo.next_scanline - 1) * row_stride];//cinfo.next_scanline * row_stride114          (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);115 116     }117 118     jpeg_finish_compress(&cinfo);119     fclose(outfile);120     jpeg_destroy_compress(&cinfo);121     free(src_data);122     free(dst_data);123 }124 int main(int argc,char *argv[])125 {126     if(argc<4)127         printf("use:appname inputname outputname quality\n");128     else{129         read_bmp_header(argv[1]);130         write_jpeg_file(argv[2],src_data,atoi(argv[3]));131         }132     return 0;133 }

编译方法上面已经说了,都是相同的。编译后运行:./bmp2jpg test.bmp test.jpg 70 ,其中test.bmp是输入图像,70是jpg的压缩质量。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
保存BMP图像的JAVA类
MFC读取jpeg
引用 CreateDIBSection
linux 平台camera失去YUV数据转RGB888及加BMP头文件
大陆女星名单
梅花精品集
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服