libjpeg-turbo是一个效率很高的图片处理的C库,所以严格来说放在Go这里不太妥当,但是之后我们会把它封装成Go可以调用的类库。据说libjpeg-turbo在处理jpeg格式图片时比ImageMagick库效率高了三倍,参照示例代码写了一个缩略图的功能:
1 //
2 // main.cpp
3 // libjpegturbo
4 //
5 // Created by 张皓然 on 2018/4/17.
6 // Copyright © 2018年 张皓然. All rights reserved.
7 //
8
9 #include <iostream>
10 #include "/opt/libjpeg-turbo/include/jpeglib.h"
11
12 using namespace std;
13
14 int compress_JPEG_file(string strImageName, string strDstImageName, int quality, int scale_num, int scale_denom) {
15 //创建必要变量,后缀in是源图片信息,out是目标图片信息,buffer是缓冲区
16 struct jpeg_decompress_struct cinfo_in;
17 struct jpeg_compress_struct cinfo_out;
18 struct jpeg_error_mgr jerr_in, jerr_out;
19 FILE *infile, *outfile;
20 JSAMPARRAY buffer;
21 //表示每行的宽度,为width*components
22 int row_stride;
23
24 //初始化对象
25 jpeg_create_decompress(&cinfo_in);
26 jpeg_create_compress(&cinfo_out);
27 //绑定错误结构
28 cinfo_in.err = jpeg_std_error(&jerr_in);
29 cinfo_out.err = jpeg_std_error(&jerr_out);
30 //C库方式打开图片文件,并填入cinfo对象
31 if((infile = fopen(strImageName.c_str(), "rb")) == NULL) {
32 fprintf(stderr, "can't open %s\n", strImageName.c_str());
33 return -1;
34 }
35 if((outfile = fopen(strDstImageName.c_str(), "wb")) == NULL) {
36 fprintf(stderr, "can't open %s\n", strDstImageName.c_str());
37 return -1;
38 }
39 jpeg_stdio_src(&cinfo_in, infile);
40 jpeg_stdio_dest(&cinfo_out, outfile);
41 //读取文件信息
42 jpeg_read_header(&cinfo_in, TRUE);
43
44 //设定文件压缩比例,M/N
45 cinfo_in.scale_num = scale_num;
46 cinfo_in.scale_denom = scale_denom;
47
48 //开始解压缩
49 jpeg_start_decompress(&cinfo_in);
50
51 //将压缩后的信息存入cinfo_out中作为新图片的参数
52 cinfo_out.image_height = cinfo_in.output_height;
53 cinfo_out.image_width = cinfo_in.output_width;
54 cinfo_out.input_components = 3;
55 cinfo_out.in_color_space = JCS_RGB;
56 jpeg_set_defaults(&cinfo_out);
57 //设置图片质量
58 jpeg_set_quality(&cinfo_out, quality, TRUE);
59 //开始压缩
60 jpeg_start_compress(&cinfo_out, TRUE);
61
62 //设定每行的宽度准备写入,并分配缓冲区空间
63 row_stride = cinfo_in.output_width * cinfo_in.output_components;
64 buffer = (*cinfo_in.mem -> alloc_sarray)((j_common_ptr)&cinfo_in, JPOOL_IMAGE, row_stride, 1);
65
66 while(cinfo_in.output_scanline < cinfo_in.output_height) {
67 //从in中读取数据并写入out中
68 jpeg_read_scanlines(&cinfo_in, buffer, 1);
69 jpeg_write_scanlines(&cinfo_out, buffer, 1);
70 }
71
72 //结束,释放变量
73 jpeg_finish_decompress(&cinfo_in);
74 jpeg_destroy_decompress(&cinfo_in);
75
76 jpeg_finish_compress(&cinfo_out);
77 jpeg_destroy_compress(&cinfo_out);
78
79 fclose(infile);
80 fclose(outfile);
81
82 return 0;
83 }
84
85 int main() {
86 clock_t start, finish;
87 start = clock();
88 for(int i = 0; i < 100; i ++) compress_JPEG_file("/Users/zhanghaoran/Desktop/abc.jpg", "/Users/zhanghaoran/Desktop/abc_compress.jpg", 80, 1, 2);
89 finish = clock();
90 cout << "Total : " << (double)(finish - start) / CLOCKS_PER_SEC << endl;
91 }