Jpeglib读取jpg文件

转载自:

https://blog.csdn.net/blues1021/article/details/45424695#

1.下载编译库

下载库:

http://www.ijg.org/ 网址下面的windows版本的。本文下载的是jpegsr9a.zip。

编译库:

libjpeg,以vs2008为例, 首先要把jconfig.vc复制为jconfig.h。

打开VS2008的command line prompt命令行提示符,切换到解压的libjpeg目录下,输入"nmake -f makefile.vc"

完成后取出libjpeg.lib就行了

2.项目中引入库
将编译出来的lib目录和lib名称配置到VC的linker中,头文件引入就可以了。

3.实例代码(Jpeglib读取图像函数说明见代码注释)


  
  
  1. //// JEPGFile.cpp : Defines the entry point for the console application.
  2. ////
  3. //
  4. #include "stdafx.h"
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include "jpeglib.h"
  9. #define PUT_2B(array,offset,value) \
  10. (array[offset] = (char) ((value) & 0xFF), \
  11. array[offset+1] = (char) (((value) >> 8) & 0xFF))
  12. #define PUT_4B(array,offset,value) \
  13. (array[offset] = (char) ((value) & 0xFF), \
  14. array[offset+1] = (char) (((value) >> 8) & 0xFF), \
  15. array[offset+2] = (char) (((value) >> 16) & 0xFF), \
  16. array[offset+3] = (char) (((value) >> 24) & 0xFF))
  17. void write_bmp_header(j_decompress_ptr cinfo, FILE *output_file)
  18. {
  19. //cinfo已经转换为小端模式了
  20. char bmpfileheader[ 14];
  21. char bmpinfoheader[ 40];
  22. long headersize, bfSize;
  23. int bits_per_pixel, cmap_entries;
  24. int step;
  25. /* Compute colormap size and total file size */
  26. if (cinfo->out_color_space == JCS_RGB) {
  27. if (cinfo->quantize_colors) {
  28. /* Colormapped RGB */
  29. bits_per_pixel = 8;
  30. cmap_entries = 256;
  31. } else {
  32. /* Unquantized, full color RGB */
  33. bits_per_pixel = 24;
  34. cmap_entries = 0;
  35. }
  36. } else {
  37. /* Grayscale output. We need to fake a 256-entry colormap. */
  38. bits_per_pixel = 8;
  39. cmap_entries = 256;
  40. }
  41. step = cinfo->output_width * cinfo->output_components;
  42. while ((step & 3) != 0) step++;
  43. /* File size */
  44. headersize = 14 + 40 + cmap_entries * 4; /* Header and colormap */
  45. bfSize = headersize + ( long) step * ( long) cinfo->output_height;
  46. /* Set unused fields of header to 0 */
  47. memset(bmpfileheader, 0, sizeof(bmpfileheader));
  48. memset(bmpinfoheader, 0 , sizeof(bmpinfoheader));
  49. /* Fill the file header */
  50. bmpfileheader[ 0] = 0x42; /* first 2 bytes are ASCII 'B', 'M' */
  51. bmpfileheader[ 1] = 0x4D;
  52. PUT_4B(bmpfileheader, 2, bfSize); /* bfSize */
  53. /* we leave bfReserved1 & bfReserved2 = 0 */
  54. PUT_4B(bmpfileheader, 10, headersize); /* bfOffBits */
  55. /* Fill the info header (Microsoft calls this a BITMAPINFOHEADER) */
  56. PUT_2B(bmpinfoheader, 0, 40); /* biSize */
  57. PUT_4B(bmpinfoheader, 4, cinfo->output_width); /* biWidth */
  58. PUT_4B(bmpinfoheader, 8, cinfo->output_height); /* biHeight */
  59. PUT_2B(bmpinfoheader, 12, 1); /* biPlanes - must be 1 */
  60. PUT_2B(bmpinfoheader, 14, bits_per_pixel); /* biBitCount */
  61. /* we leave biCompression = 0, for none */
  62. /* we leave biSizeImage = 0; this is correct for uncompressed data */
  63. if (cinfo->density_unit == 2) { /* if have density in dots/cm, then */
  64. PUT_4B(bmpinfoheader, 24, (INT32) (cinfo->X_density* 100)); /* XPels/M */
  65. PUT_4B(bmpinfoheader, 28, (INT32) (cinfo->Y_density* 100)); /* XPels/M */
  66. }
  67. PUT_2B(bmpinfoheader, 32, cmap_entries); /* biClrUsed */
  68. /* we leave biClrImportant = 0 */
  69. if (fwrite(bmpfileheader, 1, 14, output_file) != ( size_t) 14) {
  70. printf( "write bmpfileheader error\n");
  71. }
  72. if (fwrite(bmpinfoheader, 1, 40, output_file) != ( size_t) 40) {
  73. printf( "write bmpinfoheader error\n");
  74. }
  75. if (cmap_entries > 0) {
  76. }
  77. }
  78. void write_pixel_data(j_decompress_ptr cinfo, unsigned char *output_buffer, FILE *output_file)
  79. {
  80. int rows, cols;
  81. int row_width;
  82. int step;
  83. unsigned char *tmp = NULL;
  84. unsigned char *pdata;
  85. row_width = cinfo->output_width * cinfo->output_components;
  86. step = row_width;
  87. while ((step & 3) != 0) step++;
  88. pdata = ( unsigned char *) malloc(step);
  89. memset(pdata, 0, step);
  90. // JPEG左上角的开始一行行写的数据,转换为BMP的从左下角开始一行行写的数据
  91. // 也就是JPEG最末的行放置到BMP最开始行,JPEG最开始行放置到BMP最末行就对了。
  92. tmp = output_buffer + row_width * (cinfo->output_height - 1);
  93. for (rows = 0; rows < cinfo->output_height; rows++) {
  94. for (cols = 0; cols < row_width; cols += 3) {
  95. // 大端模式转换为小端模式
  96. pdata[cols + 2] = tmp[cols + 0];
  97. pdata[cols + 1] = tmp[cols + 1];
  98. pdata[cols + 0] = tmp[cols + 2];
  99. }
  100. tmp -= row_width;
  101. fwrite(pdata, 1, step, output_file);
  102. }
  103. free(pdata);
  104. }
  105. /*读JPEG文件相当于解压文件*/
  106. int read_jpeg_file(const char *input_filename, const char *output_filename)
  107. {
  108. struct jpeg_decompress_struct cinfo;
  109. struct jpeg_error_mgr jerr;
  110. FILE *input_file;
  111. FILE *output_file;
  112. JSAMPARRAY buffer;
  113. int row_width;
  114. unsigned char *output_buffer;
  115. unsigned char *tmp = NULL;
  116. cinfo.err = jpeg_std_error(&jerr);
  117. if ((input_file = fopen(input_filename, "rb")) == NULL) {
  118. fprintf( stderr, "can't open %s\n", input_filename);
  119. return -1;
  120. }
  121. if ((output_file = fopen(output_filename, "wb")) == NULL) {
  122. fprintf( stderr, "can't open %s\n", output_filename);
  123. return -1;
  124. }
  125. // Initialization of JPEG compression objects
  126. jpeg_create_decompress(&cinfo);
  127. /* Specify data source for decompression */
  128. jpeg_stdio_src(&cinfo, input_file);
  129. /* 1.设置读取jpg文件头部,Read file header, set default decompression parameters */
  130. ( void) jpeg_read_header(&cinfo, TRUE);
  131. /* 2.开始解码数据 Start decompressor */
  132. ( void) jpeg_start_decompress(&cinfo);
  133. row_width = cinfo.output_width * cinfo.output_components;
  134. /* 3.跳过读取的头文件字节Make a one-row-high sample array that will go away when done with image */
  135. buffer = (*cinfo.mem->alloc_sarray)
  136. ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_width, 1);
  137. write_bmp_header(&cinfo, output_file);
  138. output_buffer = ( unsigned char *) malloc(row_width * cinfo.output_height);
  139. memset(output_buffer, 0, row_width * cinfo.output_height);
  140. tmp = output_buffer;
  141. /* 4.Process data由左上角从上到下行行扫描 */
  142. while (cinfo.output_scanline < cinfo.output_height) {
  143. ( void) jpeg_read_scanlines(&cinfo, buffer, 1);
  144. memcpy(tmp, *buffer, row_width);
  145. tmp += row_width;
  146. }
  147. // 写入数据,注意大小端转换和图像数据坐标表示差异在内存中的顺序
  148. write_pixel_data(&cinfo, output_buffer, output_file);
  149. free(output_buffer);
  150. ( void) jpeg_finish_decompress(&cinfo);
  151. jpeg_destroy_decompress(&cinfo);
  152. /* Close files, if we opened them */
  153. fclose(input_file);
  154. fclose(output_file);
  155. return 0;
  156. }
  157. int write_jpeg_file(char * filename, int quality)
  158. {
  159. struct jpeg_compress_struct cinfo;
  160. unsigned char * image_buffer;
  161. int i = 0;
  162. struct jpeg_error_mgr jerr;
  163. /* More stuff */
  164. FILE * outfile; /* target file */
  165. JSAMPROW row_pointer[ 1]; /* pointer to JSAMPLE row[s] */
  166. int row_stride; /* physical row width in image buffer */
  167. /* Step 1: allocate and initialize JPEG compression object */
  168. /* We have to set up the error handler first, in case the initialization
  169. * step fails. (Unlikely, but it could happen if you are out of memory.)
  170. * This routine fills in the contents of struct jerr, and returns jerr's
  171. * address which we place into the link field in cinfo.
  172. */
  173. /*1.第一步创建jpeg compress 对象*/
  174. cinfo.err = jpeg_std_error(&jerr);
  175. /* Now we can initialize the JPEG compression object. */
  176. jpeg_create_compress(&cinfo);
  177. /* Step 2: specify data destination (eg, a file) */
  178. /* Note: steps 2 and 3 can be done in either order. */
  179. /* Here we use the library-supplied code to send compressed data to a
  180. * stdio stream. You can also write your own code to do something else.
  181. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
  182. * requires it in order to write binary files.
  183. */
  184. /*写的方式打开文件*/
  185. if ((outfile = fopen(filename, "wb")) == NULL) {
  186. fprintf( stderr, "can't open %s\n", filename);
  187. exit( 1);
  188. }
  189. jpeg_stdio_dest(&cinfo, outfile);
  190. /* Step 3: set parameters for compression */
  191. /* First we supply a description of the input image.
  192. * Four fields of the cinfo struct must be filled in:
  193. */
  194. /*2.设置 压缩参数 libjpeg中的宽度和高度是两个全局的
  195. 我这默认设置成640 480。根据demo中的说明color_space必须
  196. 得设置*/
  197. cinfo.image_width = 640; /* image width and height, in pixels */
  198. cinfo.image_height = 480;
  199. cinfo.input_components = 3; /* # of color components per pixel */
  200. cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
  201. /* Now use the library's routine to set default compression parameters.
  202. * (You must set at least cinfo.in_color_space before calling this,
  203. * since the defaults depend on the source color space.)
  204. */
  205. jpeg_set_defaults(&cinfo);
  206. /* Now you can set any non-default parameters you wish to.
  207. * Here we just illustrate the use of quality (quantization table) scaling:
  208. */
  209. /*设置quality为2*/
  210. jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
  211. /* Step 4: Start compressor */
  212. /* TRUE ensures that we will write a complete interchange-JPEG file.
  213. * Pass TRUE unless you are very sure of what you're doing.
  214. */
  215. /*3. 开始压缩*/
  216. jpeg_start_compress(&cinfo, TRUE);
  217. /* Step 5: while (scan lines remain to be written) */
  218. /* jpeg_write_scanlines(...); */
  219. /* Here we use the library's state variable cinfo.next_scanline as the
  220. * loop counter, so that we don't have to keep track ourselves.
  221. * To keep things simple, we pass one scanline per call; you can pass
  222. * more if you wish, though.
  223. */
  224. row_stride = 640 * 3; /* JSAMPLEs per row in image_buffer */
  225. image_buffer = ( unsigned char*) malloc( 640* 480* 3);
  226. if ( NULL == image_buffer)
  227. {
  228. return -1;
  229. }
  230. for(i= 0; i< 640* 480; i++)
  231. {
  232. // 4.构造的数据,数据是RGB形式Pixel
  233. image_buffer[i* 3] = 255 /*i*255*/;
  234. image_buffer[i* 3+ 1] = 255 /*128-(i*255)&0x7f*/;
  235. image_buffer[i* 3+ 2] = 0 /*255-(i*255)&0xff*/;
  236. }
  237. while (cinfo.next_scanline < cinfo.image_height) {
  238. /* jpeg_write_scanlines expects an array of pointers to scanlines.
  239. * Here the array is only one element long, but you could pass
  240. * more than one scanline at a time if that's more convenient.
  241. */
  242. // 5.将数据扫描输入,image_buffer数据是RGB形式Pixel
  243. row_pointer[ 0] = & image_buffer[cinfo.next_scanline * row_stride];
  244. ( void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
  245. }
  246. /* Step 6: Finish compression */
  247. // 6.完成压缩
  248. jpeg_finish_compress(&cinfo);
  249. /* After finish_compress, we can close the output file. */
  250. fclose(outfile);
  251. /* Step 7: release JPEG compression object */
  252. /* This is an important step since it will release a good deal of memory. */
  253. jpeg_destroy_compress(&cinfo);
  254. /* And we're done! */
  255. }
  256. int main(int argc, char *argv[])
  257. {
  258. read_jpeg_file( "f:\\data\\animal.jpg", "f:\\data\\animal.bmp");
  259. write_jpeg_file( "f:\\data\\createJpg.jpg", 2);
  260. return 0;
  261. }


猜你喜欢

转载自blog.csdn.net/weixin_41342624/article/details/89153591
今日推荐