本文首发于个人博客https://kezunlin.me/post/83828674/,欢迎阅读!
compile and use libjpeg-turbo on windows 10
Series
Guide
build requirements
Build Requirements
- cmake 2.8
- NASM 2.13
- Visual Studio 2015
- libjpeg-turbo 1.5.4
(1) If using
NASM
, 2.05 or later is required for an x86-64 build.(2)
nasm.exe/yasm.exe
should be in your PATH.
download
git clone https://github.com/libjpeg-turbo/libjpeg-turbo.git
# or
wget https://codeload.github.com/libjpeg-turbo/libjpeg-turbo/zip/master
install nasm
wget http://www.nasm.us/pub/nasm/releasebuilds/2.13.03rc1/win64/nasm-2.13.03rc1-installer-x64.exe
add C:Program FilesNASM
to env path.
compile libjpeg
cmake-gui
CMAKE_BUILD_TYPE = Release
ENABLE_SHARED = ON
CMAKE_INSTALL_PREFIX = d:/libjpeg-turbo64
NASM = C:/Program Files/NASM/nasm.exe
configure and generate sln
, compile with visual studio 2015
and install.
usage with cmake
libjpegturbo-config.cmake
set(LIBJPEGTURBO_FOUND TRUE) # auto
set(LIBJPEGTURBO_ROOT_DIR "d:/libjpeg-turbo64")
find_path(LIBJPEGTURBO_INCLUDE_DIR NAMES jpeglib.h turbojpeg.h PATHS "${LIBJPEGTURBO_ROOT_DIR}/include")
mark_as_advanced(LIBJPEGTURBO_INCLUDE_DIR) # show entry in cmake-gui
find_library(LIBJPEGTURBO_JPEG_LIBRARY NAMES jpeg.lib PATHS "${LIBJPEGTURBO_ROOT_DIR}/lib")
mark_as_advanced(LIBJPEGTURBO_JPEG_LIBRARY) # show entry in cmake-gui
find_library(LIBJPEGTURBO_TURBOJPEG_LIBRARY NAMES turbojpeg.lib PATHS "${LIBJPEGTURBO_ROOT_DIR}/lib")
mark_as_advanced(LIBJPEGTURBO_TURBOJPEG_LIBRARY) # show entry in cmake-gui
# use xxx_INCLUDE_DIRS and xxx_LIBRARIES in CMakeLists.txt
set(LIBJPEGTURBO_INCLUDE_DIRS ${LIBJPEGTURBO_INCLUDE_DIR} )
set(LIBJPEGTURBO_LIBRARIES ${LIBJPEGTURBO_JPEG_LIBRARY} ${LIBJPEGTURBO_TURBOJPEG_LIBRARY} )
message( "libjpegturbo-config.cmake " ${LIBJPEGTURBO_ROOT_DIR})
CMakeLists.txt
find_package(LIBJPEGTURBO REQUIRED)
include_directories(${LIBJPEGTURBO_INCLUDE_DIRS})
add_executable (example_jpeg
${CMAKE_CURRENT_SOURCE_DIR}/src/example/example_jpeg.cpp
)
target_link_libraries (example_jpeg
${LIBJPEGTURBO_LIBRARIES}
)
add_executable (example_turbojpeg
${CMAKE_CURRENT_SOURCE_DIR}/src/example/example_turbojpeg.cpp
)
target_link_libraries (example_turbojpeg
${LIBJPEGTURBO_LIBRARIES}
)
Example Code
jpeglib vs turbojpeg
jpeglib
- include:
#include "jpeglib.h"
- lib:
jpeg.lib
- dll:
jpeg62.dll
turbojpeg
- include:
#include "turbojpeg.h"
- lib:
turbojpeg.lib
- dll:
turbojpeg.dll
turbojpeg is (3-5x) faster than jpeglib.
jpeglib
#include <iostream>
#include <fstream>
#include <ctime>
#include "jpeglib.h"
typedef unsigned char BYTE;
bool CompressJPEG(
/*IN*/BYTE *src, int width, int height, int depth,
/*OUT*/BYTE **dst, unsigned long *dstLen
)
{
// NOTICE: dst space must be created outside before passing in.
struct jpeg_compress_struct jcs;
struct jpeg_error_mgr jem;
jcs.err = jpeg_std_error(&jem);
jpeg_create_compress(&jcs);
jpeg_mem_dest(&jcs, dst, dstLen);
jcs.image_width = width;
jcs.image_height = height;
jcs.input_components = depth;
jcs.in_color_space = JCS_RGB;
jpeg_set_defaults(&jcs);
jpeg_set_quality(&jcs, 80, true);
jcs.jpeg_color_space = JCS_YCbCr;
jcs.comp_info[0].h_samp_factor = 2;
jcs.comp_info[0].v_samp_factor = 2;
jpeg_start_compress(&jcs, TRUE);
JSAMPROW row_pointer[1];
int row_stride = jcs.image_width*jcs.num_components;
while (jcs.next_scanline<jcs.image_height)
{
row_pointer[0] = &src[jcs.next_scanline*row_stride];
jpeg_write_scanlines(&jcs, row_pointer, 1);
}
jpeg_finish_compress(&jcs);
jpeg_destroy_compress(&jcs);
return true;
}
bool DeompressJPEG(
/*IN*/BYTE *src, unsigned long srcLen,
/*OUT*/BYTE **dst, unsigned long *dstLen, int *width, int *height, int *depth
)
{
// NOTICE: dst space will be created inside.
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err=jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_mem_src(&cinfo,src,srcLen);
jpeg_read_header(&cinfo,TRUE);
jpeg_start_decompress(&cinfo);
(*width) = cinfo.output_width;
(*height) = cinfo.output_height;
(*depth) = cinfo.num_components;
(*dstLen) = (*width)*(*height)*(*depth);
BYTE *tmp_dst = new BYTE[*dstLen];
JSAMPROW row_pointer[1];
int row_stride = cinfo.image_width*cinfo.num_components;
while (cinfo.output_scanline<cinfo.output_height)
{
row_pointer[0] = &tmp_dst[cinfo.output_scanline*row_stride];
jpeg_read_scanlines(&cinfo,row_pointer,1);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
*dst = tmp_dst;
return true;
}
void compress_jpeg_to_file(
/*IN*/BYTE *src,int width, int height, int components, int color_space,int quality,
/*OUT*/char *dst_filename
)
{
/* 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(dst_filename, "wb")) == NULL) {
fprintf(stderr, "can't open %s\n", dst_filename);
exit(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 = width; /* image width and height, in pixels */
cinfo.image_height = height;
cinfo.input_components = components; /* # of color components per pixel */
cinfo.in_color_space = (J_COLOR_SPACE)color_space; /* colorspace of input image */
/* Now use the library's routine to set default compression parameters.
* (You must set at least cinfo.in_color_spac