libJPEG-turbo库使用示例代码
Posted 逍遥一度,恣情江湖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于libJPEG-turbo库使用示例代码的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 libjpeg-turbo 解码 JPEG9 图像?