libJPEG-turbo库使用示例代码

 libJPEG库是用于编码数据为JPEG格式或者解码JPEG格式图片的常用库,OpenCV读取图像底层实现就是利用libJPEG库,而libJPEG-turbo则效率更高。

具体怎么编译编译libJPEG库源码得到lib库的方法很容易搜到,不多做介绍。

下面的代码包含了该库中常用的API用法,包括读取一幅JPEG图片并解码到内存、编码内存中的数据为JPEG图片写入本地等。

  1 #include <iostream>  
  2 #include <stdio.h>  
  3 #include <setjmp.h>  
  4 #include <string.h>  
  5 #include <stdlib.h>  
  6 #include <jpeglib.h>
  7 #include <opencv2/opencv.hpp>
  8 
  9 using namespace std;
 10 
 11 int read_JPEG_file(string strImageName)
 12 {
 13     /* This struct contains the JPEG decompression parameters and pointers to
 14     * working space (which is allocated as needed by the JPEG library).
 15     */
 16     struct jpeg_decompress_struct cinfo;
 17     /* We use our private extension JPEG error handler.
 18     * Note that this struct must live as long as the main JPEG parameter
 19     * struct, to avoid dangling-pointer problems.
 20     */
 21     struct jpeg_error_mgr jerr;
 22     /* More stuff */
 23     FILE * infile;/* source file */
 24     JSAMPARRAY buffer;/* Output row buffer */
 25     int row_stride;/* physical row width in output buffer */
 26 
 27                    /* In this example we want to open the input file before doing anything else,
 28                    * so that the setjmp() error recovery below can assume the file is open.
 29                    * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
 30                    * requires it in order to read binary files.
 31                    */
 32     if ((infile = fopen(strImageName.c_str(), "rb")) == NULL) {
 33         fprintf(stderr, "can't open %s\n", strImageName);
 34         return -1;
 35     }
 36 
 37     /* Step 1: allocate and initialize JPEG decompression object */
 38     /* We set up the normal JPEG error routines, then override error_exit. */
 39     cinfo.err = jpeg_std_error(&jerr);
 40     /* Establish the setjmp return context for my_error_exit to use. */
 41     //if (setjmp(jerr.setjmp_buffer)) {  
 42     /* If we get here, the JPEG code has signaled an error.
 43     * We need to clean up the JPEG object, close the input file, and return.
 44     */
 45     //jpeg_destroy_decompress(&cinfo);  
 46     //fclose(infile);  
 47     //return -1;  
 48     //}  
 49 
 50     /* Now we can initialize the JPEG decompression object. */
 51     jpeg_create_decompress(&cinfo);
 52 
 53     /* Step 2: specify data source (eg, a file) */
 54     jpeg_stdio_src(&cinfo, infile);
 55 
 56     /* Step 3: read file parameters with jpeg_read_header() */
 57     jpeg_read_header(&cinfo, TRUE);
 58     /* We can ignore the return value from jpeg_read_header since
 59     *   (a) suspension is not possible with the stdio data source, and
 60     *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
 61     * See libjpeg.txt for more info.
 62     */
 63     printf("image_width = %d\n", cinfo.image_width);
 64     printf("image_height = %d\n", cinfo.image_height);
 65     printf("num_components = %d\n", cinfo.num_components);
 66 
 67     /* Step 4: set parameters for decompression */
 68     /* In this example, we don't need to change any of the defaults set by
 69     * jpeg_read_header(), so we do nothing here.
 70     */
 71     printf("enter scale M/N:\n");
 72     //scanf("%d/%d", &cinfo.scale_num, &cinfo.scale_denom);  
 73     cinfo.scale_num = 1;
 74     cinfo.scale_denom = 1;
 75     printf("scale to : %d/%d\n", cinfo.scale_num, cinfo.scale_denom);
 76 
 77     /* Step 5: Start decompressor */
 78     jpeg_start_decompress(&cinfo);
 79     /* We can ignore the return value since suspension is not possible
 80     * with the stdio data source.
 81     */
 82 
 83     //输出的图象的信息  
 84     printf("output_width = %d\n", cinfo.output_width);
 85     printf("output_height = %d\n", cinfo.output_height);
 86     printf("output_components = %d\n", cinfo.output_components);
 87 
 88     /* We may need to do some setup of our own at this point before reading
 89     * the data.  After jpeg_start_decompress() we have the correct scaled
 90     * output image dimensions available, as well as the output colormap
 91     * if we asked for color quantization.
 92     * In this example, we need to make an output work buffer of the right size.
 93     */
 94     /* JSAMPLEs per row in output buffer */
 95     row_stride = cinfo.output_width * cinfo.output_components;
 96     /* Make a one-row-high sample array that will go away when done with image */
 97     buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);
 98 
 99     /* Step 6: while (scan lines remain to be read) */
100     /*           jpeg_read_scanlines(...); */
101     /* Here we use the library's state variable cinfo.output_scanline as the
102     * loop counter, so that we don't have to keep track ourselves.
103     */
104     while (cinfo.output_scanline < cinfo.output_height) {
105         /* jpeg_read_scanlines expects an array of pointers to scanlines.
106         * Here the array is only one element long, but you could ask for
107         * more than one scanline at a time if that's more convenient.
108         */
109         jpeg_read_scanlines(&cinfo, buffer, 1);
110         /* Assume put_scanline_someplace wants a pointer and sample count. */
111         //put_scanline_someplace(buffer[0], row_stride);  
112     }
113 
114     /* Step 7: Finish decompression */
115     jpeg_finish_decompress(&cinfo);
116     /* We can ignore the return value since suspension is not possible
117     * with the stdio data source.
118     */
119 
120     /* Step 8: Release JPEG decompression object */
121     /* This is an important step since it will release a good deal of memory. */
122     jpeg_destroy_decompress(&cinfo);
123 
124     /* After finish_decompress, we can close the input file.
125     * Here we postpone it until after no more JPEG errors are possible,
126     * so as to simplify the setjmp error logic above.  (Actually, I don't
127     * think that jpeg_destroy can do an error exit, but why assume anything...)
128     */
129     fclose(infile);
130 
131     /* At this point you may want to check to see whether any corrupt-data
132     * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
133     */
134 
135     return 0;
136 }
137 
138 int write_JPEG_file(string strImageName, int quality)
139 {
140     unsigned char* image_buffer;    /* Points to large array of R,G,B-order data */
141     int image_height = 780; /* Number of rows in image */
142     int image_width = 1040;  /* Number of columns in image */
143 
144                             /* This struct contains the JPEG compression parameters and pointers to
145                             * working space (which is allocated as needed by the JPEG library).
146                             * It is possible to have several such structures, representing multiple
147                             * compression/decompression processes, in existence at once.  We refer
148                             * to any one struct (and its associated working data) as a "JPEG object".
149                             */
150     struct jpeg_compress_struct cinfo;
151 
152     /* This struct represents a JPEG error handler.  It is declared separately
153     * because applications often want to supply a specialized error handler
154     * (see the second half of this file for an example).  But here we just
155     * take the easy way out and use the standard error handler, which will
156     * print a message on stderr and call exit() if compression fails.
157     * Note that this struct must live as long as the main JPEG parameter
158     * struct, to avoid dangling-pointer problems.
159     */
160     struct jpeg_error_mgr jerr;
161     /* More stuff */
162     FILE * outfile;     /* target file */
163     JSAMPROW row_pointer[1];    /* pointer to JSAMPLE row[s] */
164     int row_stride;     /* physical row width in image buffer */
165 
166                         /* Step 1: allocate and initialize JPEG compression object */
167 
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     cinfo.err = jpeg_std_error(&jerr);
174     /* Now we can initialize the JPEG compression object. */
175     jpeg_create_compress(&cinfo);
176 
177     /* Step 2: specify data destination (eg, a file) */
178     /* Note: steps 2 and 3 can be done in either order. */
179 
180     /* Here we use the library-supplied code to send compressed data to a
181     * stdio stream.  You can also write your own code to do something else.
182     * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
183     * requires it in order to write binary files.
184     */
185     if ((outfile = fopen(strImageName.c_str(), "wb")) == NULL) {
186         fprintf(stderr, "can't open %s\n", strImageName);
187         //exit(1);  
188         return -1;
189     }
190     jpeg_stdio_dest(&cinfo, outfile);
191 
192     /* Step 3: set parameters for compression */
193     /* First we supply a description of the input image.
194     * Four fields of the cinfo struct must be filled in:
195     */
196     cinfo.image_width = image_width;    /* image width and height, in pixels */
197     cinfo.image_height = image_height;
198     cinfo.input_components = 3;     /* # of color components per pixel */
199     cinfo.in_color_space = JCS_RGB;     /* colorspace of input image */
200                                         /* Now use the library's routine to set default compression parameters.
201                                         * (You must set at least cinfo.in_color_space before calling this,
202                                         * since the defaults depend on the source color space.)
203                                         */
204     jpeg_set_defaults(&cinfo);
205     /* Now you can set any non-default parameters you wish to.
206     * Here we just illustrate the use of quality (quantization table) scaling:
207     */
208     jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
209 
210     /* Step 4: Start compressor */
211     /* TRUE ensures that we will write a complete interchange-JPEG file.
212     * Pass TRUE unless you are very sure of what you're doing.
213     */
214     jpeg_start_compress(&cinfo, TRUE);
215 
216     /* Step 5: while (scan lines remain to be written) */
217     /*           jpeg_write_scanlines(...); */
218     /* Here we use the library's state variable cinfo.next_scanline as the
219     * loop counter, so that we don't have to keep track ourselves.
220     * To keep things simple, we pass one scanline per call; you can pass
221     * more if you wish, though.
222     */
223     row_stride = image_width * 3;   /* JSAMPLEs per row in image_buffer */
224 
225     image_buffer = new unsigned char[row_stride * cinfo.image_height];
226     memset(image_buffer, 0xff, row_stride * cinfo.image_height);
227 
228     int line = 0;
229     //while (cinfo.next_scanline < cinfo.image_height) {  
230     while (line < cinfo.image_height) {
231         /* jpeg_write_scanlines expects an array of pointers to scanlines.
232         * Here the array is only one element long, but you could pass
233         * more than one scanline at a time if that's more convenient.
234         */
235         //row_pointer[0] = &image_buffer[cinfo.next_scanline * row_stride];  
236         row_pointer[0] = &image_buffer[line * row_stride];
237         jpeg_write_scanlines(&cinfo, row_pointer, 1);
238 
239         line++;
240     }
241 
242     delete image_buffer;
243 
244     /* Step 6: Finish compression */
245     jpeg_finish_compress(&cinfo);
246     /* After finish_compress, we can close the output file. */
247     fclose(outfile);
248 
249     /* Step 7: release JPEG compression object */
250     /* This is an important step since it will release a good deal of memory. */
251     jpeg_destroy_compress(&cinfo);
252 
253     return 0;
254 }
255 
256 struct Image
257 {
258     int bpp;
259     int width;
260     int height;
261     unsigned char* data;
262 };
263 
264 struct jerror_mgr
265 {
266     jpeg_error_mgr base;
267     jmp_buf        jmp;
268 };
269 
270 METHODDEF(void) jerror_exit(j_common_ptr jinfo)
271 {
272     jerror_mgr* err = (jerror_mgr*)jinfo->err;
273     longjmp(err->jmp, 1);
274 }
275 
276 METHODDEF(void) joutput_message(j_common_ptr)
277 {
278 }
279 
280 bool Image_LoadJpeg(Image* image, unsigned char* img_data, unsigned int img_size)
281 {
282     jpeg_decompress_struct jinfo;
283     jerror_mgr jerr;
284 
285     jinfo.err = jpeg_std_error(&jerr.base);
286     jerr.base.error_exit = jerror_exit;
287     jerr.base.output_message = joutput_message;
288     jpeg_create_decompress(&jinfo);
289 
290     image->data = NULL;
291 
292     if (setjmp(jerr.jmp)) goto bail;
293 
294     jpeg_mem_src(&jinfo, img_data, img_size);
295 
296     if (jpeg_read_header(&jinfo, TRUE) != JPEG_HEADER_OK) goto bail;
297 
298     jinfo.dct_method = JDCT_FLOAT; // change this to JDCT_ISLOW on Android/iOS  
299 
300     if (!jpeg_start_decompress(&jinfo)) goto bail;
301 
302     if (jinfo.num_components != 1 && jinfo.num_components != 3) goto bail;
303 
304     image->data = new (std::nothrow) unsigned char[jinfo.output_width * jinfo.output_height * jinfo.output_components];
305     if (!image->data) goto bail;
306 
307     {
308         JSAMPROW ptr = image->data;
309         while (jinfo.output_scanline < jinfo.output_height)
310         {
311             if (jpeg_read_scanlines(&jinfo, &ptr, 1) != 1) goto bail;
312 
313             ptr += jinfo.output_width * jinfo.output_components;
314         }
315     }
316 
317     if (!jpeg_finish_decompress(&jinfo)) goto bail;
318 
319     image->bpp = jinfo.output_components;
320     image->width = jinfo.output_width;
321     image->height = jinfo.output_height;
322 
323     jpeg_destroy_decompress(&jinfo);
324 
325     return true;
326 
327 bail:
328     jpeg_destroy_decompress(&jinfo);
329     if (image->data) delete[] image->data;
330 
331     return false;
332 }
333 
334 struct ImageData {
335     unsigned char *pixels;
336     long  width;
337     long height;
338 };
339 
340 int TestImage(string strSrcImageName, string strDstImageName)
341 {
342     //read  
343     struct jpeg_decompress_struct cinfo_decompress;
344     FILE* infile;
345     int row_stride;
346     struct jpeg_error_mgr jerr;
347 
348     if ((infile = fopen(strSrcImageName.c_str(), "rb")) == NULL) {
349         fprintf(stderr, "can't open %s\n", strSrcImageName);
350         return -1;
351     }
352 
353     cinfo_decompress.err = jpeg_std_error(&jerr);
354     jpeg_create_decompress(&cinfo_decompress);
355     jpeg_stdio_src(&cinfo_decompress, infile);
356     int ret = jpeg_read_header(&cinfo_decompress, TRUE);
357     if (ret != JPEG_HEADER_OK) return -1;
358     jpeg_start_decompress(&cinfo_decompress);
359     row_stride = cinfo_decompress.output_width * cinfo_decompress.output_components;
360     int buffer_height = 1;
361     JSAMPARRAY buffer = (JSAMPARRAY)malloc(sizeof(JSAMPROW) * buffer_height);
362     buffer[0] = (JSAMPROW)malloc(sizeof(JSAMPLE) * row_stride);
363     //JSAMPARRAY buffer = (*cinfo_decompress.mem->alloc_sarray)((j_common_ptr)&cinfo_decompress, JPOOL_IMAGE, row_stride, 1);  
364     ImageData *imageData;
365     imageData = new ImageData;
366     imageData->width = cinfo_decompress.output_width;
367     imageData->height = cinfo_decompress.output_height;
368 
369     imageData->pixels = new unsigned char[cinfo_decompress.output_width * cinfo_decompress.output_height * cinfo_decompress.output_components];
370     long counter = 0;
371 
372     while (cinfo_decompress.output_scanline < cinfo_decompress.output_height) {
373         jpeg_read_scanlines(&cinfo_decompress, buffer, 1);
374         memcpy(imageData->pixels + counter, buffer[0], row_stride);
375         counter += row_stride;
376     }
377 
378     jpeg_finish_decompress(&cinfo_decompress);
379     jpeg_destroy_decompress(&cinfo_decompress);
380 
381     fclose(infile);
382 
383     //write  
384     unsigned char* image_buffer;
385     int image_height = cinfo_decompress.output_height;
386     int image_width = cinfo_decompress.output_width;
387     FILE * outfile;
388     JSAMPROW row_pointer[1];
389     int row_stride_dst;
390     struct jpeg_compress_struct cinfo_compress;
391     cinfo_compress.err = jpeg_std_error(&jerr);
392     jpeg_create_compress(&cinfo_compress);
393 
394     if ((outfile = fopen(strDstImageName.c_str(), "wb")) == NULL) {
395         fprintf(stderr, "can't open %s\n", strDstImageName);
396         //exit(1);  
397         return -1;
398     }
399 
400     jpeg_stdio_dest(&cinfo_compress, outfile);
401 
402     cinfo_compress.image_width = image_width;
403     cinfo_compress.image_height = image_height;
404     cinfo_compress.input_components = 3;
405     cinfo_compress.in_color_space = JCS_EXT_RGB;
406 
407     int quality = 70;
408     jpeg_set_defaults(&cinfo_compress);
409     jpeg_set_quality(&cinfo_compress, quality, TRUE);
410     jpeg_start_compress(&cinfo_compress, TRUE);
411 
412     row_stride_dst = image_width * 3;
413 
414     image_buffer = new unsigned char[row_stride_dst * cinfo_compress.image_height];
415     memcpy(image_buffer, imageData->pixels, row_stride_dst * cinfo_compress.image_height);
416 
417     while (cinfo_compress.next_scanline < cinfo_compress.image_height) {
418         row_pointer[0] = &image_buffer[cinfo_compress.next_scanline * row_stride_dst];
419         jpeg_write_scanlines(&cinfo_compress, row_pointer, 1);
420     }
421 
422     jpeg_finish_compress(&cinfo_compress);
423     fclose(outfile);
424     jpeg_destroy_compress(&cinfo_compress);
425 
426     if (imageData) {
427         delete imageData;
428         imageData = NULL;
429     }
430 
431     if (image_buffer)
432         delete[] image_buffer;
433 
434     return 0;
435 }
436 
437 int main(int argc, char* argv[])
438 {
439     string strImageName = "data/srcImg/moon.jpg";
440     int flag1 = read_JPEG_file(strImageName);
441     if (flag1 == 0) cout << "read ok!" << endl;
442     else cout << "read error!" << endl;
443 
444     strImageName = "2.bmp";
445     int flag2 = write_JPEG_file(strImageName, 80);
446     if (flag2 == 0) cout << "write ok!" << endl;
447     else cout << "write error!" << endl;
448 
449     string strSrcImageName = "data/srcImg/moon.jpg";
450     string strDstImageName = "b.jpg";
451     int flag3 = TestImage(strSrcImageName, strDstImageName);
452     if (flag3 == 0) cout << "test ok!" << endl;
453     else cout << "test error!" << endl;
454 
455     return 0;
456 }
View Code

 

posted @ 2017-11-01 22:33  一度逍遥  阅读(9128)  评论(1编辑  收藏  举报