windows7 64位機上,libjpeg-turbo的安裝和使用
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
libjpeg-turbo是對libjpeg的擴充套件,支援SIMD指令,如X86架構的MMX、SSE、SSE2、3DNOW,ARM架構的NEON,在對jpeg進行編碼和解碼的過程中能提高速度。
MMX:多媒體擴充套件的縮寫,第六代CPU晶片重要特點,57條指令。
SSE2:SIMD流技術擴充套件2,144個新增指令,被MMX優化過的程式很容易被SSE2進行更深層次的優化。
NEON:可加速多媒體和訊號處理演算法,它是ARM系列處理器的128位SIMD架構擴充套件。
在速度上,libjpeg-turbo一般是libjpeg的2-4倍。它既能呼叫libjpegAPI,又可呼叫TurboJPEG API。可以使用libjpeg-turbo替代libjpeg。
編譯libjpeg-turbo:
1、 從https://sourceforge.net/projects/libjpeg-turbo/通過TortoiseSVN下載libjpeg-turbo最新原始碼,將其儲存到D:\soft\libjpeg-turbo資料夾下;
2、 從http://www.cmake.org/下載最新版的CMake,並安裝;
3、 在D:\soft\libjpeg-turbo資料夾下手動建立一個vs2010資料夾;
4、 開啟CMake,其中where isthe source code選項,選擇D:/soft/libjpeg-turbo/libjpeg-turbo;where to build thebinaries選項,選擇D:/soft/libjpeg-turbo/vs2010;
5、 點選Configure,在彈出的對話方塊中選擇VisualStudio 10,其它預設,點選Finish;
6、 如果有紅色框顯示,繼續點選Configure(將CMAKE_INSTALL_PREFIX中的value改為D:\libjpeg-turbo);
7、 點選Generate,此時會在vs2010資料夾中看到libjpeg-turbo.sln檔案;
8、 從https://sourceforge.net/projects/nasm/下載最新版的nasm;
9、 將nasm安裝到D:\ProgramFiles\NASM資料夾下,並將其中的nasm.exe和ndisasm.exe兩個檔案拷貝到C:\ProgramFiles\Microsoft Visual Studio 10.0\VC\bin下(如果是64位,則拷貝到C:\ProgramFiles (x86)\Microsoft Visual Studio 10.0\VC\bin),將其D:\ProgramFiles\NASM新增到系統環境變數中;
10、 開啟libjpeg-turbo.sln,分別在Debug和Release下,選擇Solution Explorer裡的Solution libjpeg-turbo,點選右鍵,執行”Rebuild Solution”,然後選中INSTALL, build;
11、 全部完成後會在D:\libjpeg-turbo資料夾下生成bin、doc、lib、include四個資料夾,編譯成功(說明:預設的Debgu和Release下生成的所有資料夾都相同,注意區分);
12、 開啟vs2010,新建一個控制檯應用程式,為vs2010配置libjpeg-turbo環境:選擇View--> Properties Manager-->分別選中Debug和Release上的Microsoft.Cpp.Win32.user,點選右鍵-->Properties:VC++ Directories,Include Directories:D:\libjpeg-turbo\include;Library Directories:D:\libjpeg-turbo\lib;
13、 選中工程-->Properties-->Configuration Properties-->Linker-->Input-->AdditionalDependencies:Debug和Release,新增相應的.lib庫;
14、 將D:\libjpeg-turbo\bin加入到windows系統環境變數Path中,重啟。
新建一個控制檯工程:
1、將jconfig.h檔案拷貝到該工程目錄下;
2、stdafx.h:
#pragma once#include "targetver.h"#include <stdio.h>#include "D:/Soft/libjpegturbo/libjpegturbo/jpeglib.h"
3、stdafx.cpp:
#include "stdafx.h"// TODO: reference any additional headers you need in STDAFX.H// and not in this file#ifdef _DEBUG #pragma comment(lib, "D:/Soft/libjpegturbo/vs2010/Debug/jpeg-static.lib")#else #pragma comment(lib, "D:/Soft/libjpegturbo/vs2010/Release/jpeg-static.lib")#endif
4、main.cpp:
#include "stdafx.h"#include <iostream>#include <stdio.h>#include <setjmp.h>#include <string.h>#include <stdlib.h>using namespace std;int read_JPEG_file(string strImageName){ /* This struct contains the JPEG decompression parameters and pointers to * working space (which is allocated as needed by the JPEG library). */ struct jpeg_decompress_struct cinfo; /* We use our private extension JPEG error handler. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ struct jpeg_error_mgr jerr; /* More stuff */ FILE * infile;/* source file */ JSAMPARRAY buffer;/* Output row buffer */ int row_stride;/* physical row width in output buffer */ /* In this example we want to open the input file before doing anything else, * so that the setjmp() error recovery below can assume the file is open. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to read binary files. */ if ((infile = fopen(strImageName.c_str(), "rb")) == NULL) { fprintf(stderr, "can't open %s\n", strImageName); return -1; } /* Step 1: allocate and initialize JPEG decompression object */ /* We set up the normal JPEG error routines, then override error_exit. */ cinfo.err = jpeg_std_error(&jerr); /* Establish the setjmp return context for my_error_exit to use. */ //if (setjmp(jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ //jpeg_destroy_decompress(&cinfo); //fclose(infile); //return -1; //} /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress(&cinfo); /* Step 2: specify data source (eg, a file) */ jpeg_stdio_src(&cinfo, infile); /* Step 3: read file parameters with jpeg_read_header() */ jpeg_read_header(&cinfo, TRUE); /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. * See libjpeg.txt for more info. */ printf("image_width = %d\n", cinfo.image_width); printf("image_height = %d\n", cinfo.image_height); printf("num_components = %d\n", cinfo.num_components); /* Step 4: set parameters for decompression */ /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ printf("enter scale M/N:\n"); //scanf("%d/%d", &cinfo.scale_num, &cinfo.scale_denom); cinfo.scale_num = 2; cinfo.scale_denom = 4; printf("scale to : %d/%d\n", cinfo.scale_num, cinfo.scale_denom); /* Step 5: Start decompressor */ jpeg_start_decompress(&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ //輸出的圖象的資訊 printf("output_width = %d\n", cinfo.output_width); printf("output_height = %d\n", cinfo.output_height); printf("output_components = %d\n", cinfo.output_components); /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. */ /* JSAMPLEs per row in output buffer */ row_stride = cinfo.output_width * cinfo.output_components; /* Make a one-row-high sample array that will go away when done with image */ buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ while (cinfo.output_scanline < cinfo.output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ jpeg_read_scanlines(&cinfo, buffer, 1); /* Assume put_scanline_someplace wants a pointer and sample count. */ //put_scanline_someplace(buffer[0], row_stride); } /* Step 7: Finish decompression */ jpeg_finish_decompress(&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* Step 8: Release JPEG decompression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_decompress(&cinfo); /* After finish_decompress, we can close the input file. * Here we postpone it until after no more JPEG errors are possible, * so as to simplify the setjmp error logic above. (Actually, I don't * think that jpeg_destroy can do an error exit, but why assume anything...) */ fclose(infile); /* At this point you may want to check to see whether any corrupt-data * warnings occurred (test whether jerr.pub.num_warnings is nonzero). */ return 0;}int write_JPEG_file(string strImageName, int quality){ unsigned char* image_buffer; /* Points to large array of R,G,B-order data */ int image_height = 200; /* Number of rows in image */ int image_width = 400; /* Number of columns in image */ /* This struct contains the JPEG compression parameters and pointers to * working space (which is allocated as needed by the JPEG library). * It is possible to have several such structures, representing multiple * compression/decompression processes, in existence at once. We refer * to any one struct (and its associated working data) as a "JPEG object". */ struct jpeg_compress_struct cinfo; /* This struct represents a JPEG error handler. It is declared separately * because applications often want to supply a specialized error handler * (see the second half of this file for an example). But here we just * take the easy way out and use the standard error handler, which will * print a message on stderr and call exit() if compression fails. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ struct jpeg_error_mgr jerr; /* More stuff */ FILE * outfile; /* target file */ JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ int row_stride; /* physical row width in image buffer */ /* Step 1: allocate and initialize JPEG compression object */ /* We have to set up the error handler first, in case the initialization * step fails. (Unlikely, but it could happen if you are out of memory.) * This routine fills in the contents of struct jerr, and returns jerr's * address which we place into the link field in cinfo. */ cinfo.err = jpeg_std_error(&jerr); /* Now we can initialize the JPEG compression object. */ jpeg_create_compress(&cinfo); /* Step 2: specify data destination (eg, a file) */ /* Note: steps 2 and 3 can be done in either order. */ /* Here we use the library-supplied code to send compressed data to a * stdio stream. You can also write your own code to do something else. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to write binary files. */ if ((outfile = fopen(strImageName.c_str(), "wb")) == NULL) { fprintf(stderr, "can't open %s\n", strImageName); //exit(1); return -1; } jpeg_stdio_dest(&cinfo, outfile); /* Step 3: set parameters for compression */ /* First we supply a description of the input image. * Four fields of the cinfo struct must be filled in: */ cinfo.image_width = image_width; /* image width and height, in pixels */ cinfo.image_height = image_height; cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ /* Now use the library's routine to set default compression parameters. * (You must set at least cinfo.in_color_space before calling this, * since the defaults depend on the source color space.) */ jpeg_set_defaults(&cinfo); /* Now you can set any non-default parameters you wish to. * Here we just illustrate the use of quality (quantization table) scaling: */ jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); /* Step 4: Start compressor */ /* TRUE ensures that we will write a complete interchange-JPEG file. * Pass TRUE unless you are very sure of what you're doing. */ jpeg_start_compress(&cinfo, TRUE); /* Step 5: while (scan lines remain to be written) */ /* jpeg_write_scanlines(...); */ /* Here we use the library's state variable cinfo.next_scanline as the * loop counter, so that we don't have to keep track ourselves. * To keep things simple, we pass one scanline per call; you can pass * more if you wish, though. */ row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ image_buffer = new unsigned char[row_stride * cinfo.image_height]; memset(image_buffer, 0xff, row_stride * cinfo.image_height); int line = 0; //while (cinfo.next_scanline < cinfo.image_height) { while (line < cinfo.image_height) { /* jpeg_write_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could pass * more than one scanline at a time if that's more convenient. */ //row_pointer[0] = &image_buffer[cinfo.next_scanline * row_stride]; row_pointer[0] = &image_buffer[line * row_stride]; jpeg_write_scanlines(&cinfo, row_pointer, 1); line ++; } delete image_buffer; /* Step 6: Finish compression */ jpeg_finish_compress(&cinfo); /* After finish_compress, we can close the output file. */ fclose(outfile); /* Step 7: release JPEG compression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_compress(&cinfo); return 0;}struct Image{ int bpp; int width; int height; unsigned char* data;};struct jerror_mgr{ jpeg_error_mgr base; jmp_buf jmp;};METHODDEF(void) jerror_exit(j_common_ptr jinfo){ jerror_mgr* err = (jerror_mgr*)jinfo->err; longjmp(err->jmp, 1);}METHODDEF(void) joutput_message(j_common_ptr){}bool Image_LoadJpeg(Image* image, unsigned char* img_data, unsigned int img_size){ jpeg_decompress_struct jinfo; jerror_mgr jerr; jinfo.err = jpeg_std_error(&jerr.base); jerr.base.error_exit = jerror_exit; jerr.base.output_message = joutput_message; jpeg_create_decompress(&jinfo); image->data = NULL; if (setjmp(jerr.jmp)) goto bail; jpeg_mem_src(&jinfo, img_data, img_size); if (jpeg_read_header(&jinfo, TRUE) != JPEG_HEADER_OK) goto bail; jinfo.dct_method = JDCT_FLOAT; // change this to JDCT_ISLOW on Android/iOS if (!jpeg_start_decompress(&jinfo)) goto bail; if (jinfo.num_components != 1 && jinfo.num_components != 3) goto bail; image->data = new (std::nothrow) unsigned char [jinfo.output_width * jinfo.output_height * jinfo.output_components]; if (!image->data) goto bail; { JSAMPROW ptr = image->data; while (jinfo.output_scanline < jinfo.output_height) { if (jpeg_read_scanlines(&jinfo, &ptr, 1) != 1) goto bail; ptr += jinfo.output_width * jinfo.output_components; } } if (!jpeg_finish_decompress(&jinfo)) goto bail; image->bpp = jinfo.output_components; image->width = jinfo.output_width; image->height = jinfo.output_height; jpeg_destroy_decompress(&jinfo); return true;bail: jpeg_destroy_decompress(&jinfo); if (image->data) delete [] image->data; return false;}struct ImageData { unsigned char *pixels; long width; long height;};int TestImage(string strSrcImageName, string strDstImageName){ //read struct jpeg_decompress_struct cinfo_decompress; FILE* infile; int row_stride; struct jpeg_error_mgr jerr; if ((infile = fopen(strSrcImageName.c_str(), "rb")) == NULL) { fprintf(stderr, "can't open %s\n", strSrcImageName); return -1; } cinfo_decompress.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo_decompress); jpeg_stdio_src(&cinfo_decompress, infile); int ret = jpeg_read_header(&cinfo_decompress, TRUE); if (ret != JPEG_HEADER_OK) return -1; jpeg_start_decompress(&cinfo_decompress); row_stride = cinfo_decompress.output_width * cinfo_decompress.output_components; int buffer_height = 1; JSAMPARRAY buffer = (JSAMPARRAY)malloc(sizeof(JSAMPROW) * buffer_height); buffer[0] = (JSAMPROW)malloc(sizeof(JSAMPLE) * row_stride); //JSAMPARRAY buffer = (*cinfo_decompress.mem->alloc_sarray)((j_common_ptr)&cinfo_decompress, JPOOL_IMAGE, row_stride, 1); ImageData *imageData; imageData = new ImageData; imageData->width = cinfo_decompress.output_width; imageData->height = cinfo_decompress.output_height; imageData->pixels = new unsigned char [cinfo_decompress.output_width * cinfo_decompress.output_height * cinfo_decompress.output_components]; long counter = 0; while (cinfo_decompress.output_scanline < cinfo_decompress.output_height) { jpeg_read_scanlines(&cinfo_decompress, buffer, 1); memcpy(imageData->pixels + counter, buffer[0], row_stride); counter += row_stride; } jpeg_finish_decompress(&cinfo_decompress); jpeg_destroy_decompress(&cinfo_decompress); fclose(infile); //write unsigned char* image_buffer; int image_height = cinfo_decompress.output_height; int image_width = cinfo_decompress.output_width; FILE * outfile; JSAMPROW row_pointer[1]; int row_stride_dst; struct jpeg_compress_struct cinfo_compress; cinfo_compress.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo_compress); if ((outfile = fopen(strDstImageName.c_str(), "wb")) == NULL) { fprintf(stderr, "can't open %s\n", strDstImageName); //exit(1); return -1; } jpeg_stdio_dest(&cinfo_compress, outfile); cinfo_compress.image_width = image_width; cinfo_compress.image_height = image_height; cinfo_compress.input_components = 3; cinfo_compress.in_color_space = JCS_YCbCr; int quality = 70; jpeg_set_defaults(&cinfo_compress); jpeg_set_quality(&cinfo_compress, quality, TRUE); jpeg_start_compress(&cinfo_compress, TRUE); row_stride_dst = image_width * 3; image_buffer = new unsigned char[row_stride_dst * cinfo_compress.image_height]; memcpy(image_buffer, imageData->pixels, row_stride_dst * cinfo_compress.image_height); while (cinfo_compress.next_scanline < cinfo_compress.image_height) { row_pointer[0] = &image_buffer[cinfo_compress.next_scanline * row_stride_dst]; jpeg_write_scanlines(&cinfo_compress, row_pointer, 1); } jpeg_finish_compress(&cinfo_compress); fclose(outfile); jpeg_destroy_compress(&cinfo_compress); if (imageData) { delete imageData; imageData = NULL; } if (image_buffer) delete [] image_buffer; return 0;}int main(int argc, char* argv[]){ string strImageName = "1.jpg"; int flag1 = read_JPEG_file(strImageName); if (flag1 == 0) cout<<"read ok!"<<endl; else cout<<"read error!"<<endl; strImageName = "2.bmp"; int flag2 = write_JPEG_file(strImageName, 80); if (flag2 == 0) cout<<"write ok!"<<endl; else cout<<"write error!"<<endl; string strSrcImageName = "a.jpg"; string strDstImageName = "b.jpg"; int flag3 = TestImage(strSrcImageName, strDstImageName); if (flag3 == 0) cout<<"test ok!"<<endl; else cout<<"test error!"<<endl; return 0;}
參考文獻:
1、 http://libjpeg-turbo.virtualgl.org/
2、 http://www.linuxsir.org/bbs/thread374093.html
3、 http://blog.sina.com.cn/s/blog_a5b979d30101af56.html
4、 http://blog.csdn.net/jwzhangjie/article/details/8807409
5、 http://blog.csdn.net/hongwazi_2010/article/details/9153087