zoukankan      html  css  js  c++  java
  • CPP 替代 PIL 图片处理(缩略图生成)

    python中使用PIL(Pyhton Image Library)进行图片处理,好处就是编写简单方便,但是不能很好利用机器多核的特点,于是在项目中决定使用cpp来实现图片处理。

    项目中的图片处理主要是生成缩略图。网上收集了一些cpp图片处理库,并进行了对比:

    在项目中需要对jpg、png、gif格式的图片进行处理,可行的cpp库有Img、FreeImage、GD,而安装使用后进行效率对比,决定使用FreeImage。

    折腾了一个星期,把可用程序完成,并和PIL进行对比(这里是使用python commands库运行上传图片demo,上传时使用threading多进行并发):

    注意:

    1、测试时上传多张大图片时内存很快用完,所以要测试要排除内存用完的影响,内存耗尽会影响测试。(上传数量控制一下)

    2、linux机器上传时,记得ulimit -n 调大文件句柄打开数,以免影响测试。

    测试结果还是挺理想,准备正式推广。

    FreeImage cpp 缩略图生成代码:

      1 #include "stdio.h"
      2 #include "stdlib.h"
      3 #include "unistd.h"
      4 #include <sys/time.h>
      5 #include <sys/stat.h>  
      6 #include "FreeImage.h"
      7 
      8 #ifdef _DEBUG
      9 #pragma comment(lib, "FreeImaged.lib")
     10 #else
     11 #pragma comment(lib, "FreeImage.lib")
     12 #endif
     13 
     14 #define THUM_TYPE_SMALL 1
     15 #define THUM_TYPE_MID 2
     16 
     17 const float IMAGE_NEED_CROP_RATIO = 3.0;
     18 const float IMAGE_CROP_RATIO = 1.76;
     19 const int MID_IMAGE_LIMIT_SIZE = 3*1024*1024;
     20 
     21 struct ImageSize{
     22     int width;
     23     int height;
     24 };
     25 
     26 inline void print_size(ImageSize img_size, const char* str)
     27 {
     28     printf("%s : %d %d
    ", str, img_size.width, img_size.height);
     29 }
     30 
     31 inline bool is_long_image(ImageSize img_size)
     32 {
     33 
     34     if(float(img_size.height) / img_size.width > IMAGE_NEED_CROP_RATIO)
     35         return true;    
     36     else
     37         return false;
     38 }
     39 
     40 inline bool is_panorama_image(ImageSize img_size)
     41 {
     42     
     43     if(float(img_size.width) / img_size.height > IMAGE_NEED_CROP_RATIO)
     44         return true;
     45     else
     46         return false;
     47 }
     48 
     49 inline bool is_need_crop(ImageSize img_size)
     50 {
     51     if(is_long_image(img_size))
     52         return true;
     53     
     54     if(is_panorama_image(img_size))
     55         return true;
     56     
     57     return false;
     58 }
     59 
     60 inline bool is_need_resize(ImageSize img_size, ImageSize des_img_size)
     61 {
     62     int width = img_size.width;
     63     int height = img_size.height;
     64     int des_width = des_img_size.width;
     65     int des_height = des_img_size.height;    
     66     if((width < des_width) && (height < des_height))
     67         return false;
     68     else
     69         return true;
     70 }
     71 
     72 inline ImageSize get_crop_size(ImageSize img_size)
     73 {
     74     if(is_long_image(img_size))
     75         img_size.height = img_size.width * IMAGE_CROP_RATIO;
     76     else if(is_panorama_image(img_size))
     77         img_size.width = img_size.height * IMAGE_CROP_RATIO;
     78     
     79     return img_size;
     80 }
     81 
     82 inline ImageSize get_resize_size(ImageSize img_size, ImageSize des_img_size)
     83 {
     84     int width = img_size.width;
     85     int height = img_size.height;
     86     int des_width = des_img_size.width;
     87     int des_height = des_img_size.height;    
     88             
     89     float ratio = 1.0;
     90     if(height > width)
     91         ratio = float(des_height) / height;
     92     else
     93         ratio = float(des_width) / width;
     94     
     95     img_size.width = width * ratio;
     96     img_size.height = height * ratio;
     97 
     98     return img_size;
     99 }
    100 
    101 
    102 inline FIBITMAP * get_crop_picture(FIBITMAP *sourcePic)
    103 {
    104     
    105     int src_width, src_height;
    106     
    107     //获取图片大小 
    108     src_width  = FreeImage_GetWidth(sourcePic);
    109     src_height = FreeImage_GetHeight(sourcePic);        
    110     
    111     struct ImageSize src_size = {src_width, src_height};
    112     
    113     if(!is_need_crop(src_size))
    114         return sourcePic;
    115         
    116     struct ImageSize crop_size = get_crop_size(src_size);
    117     //print_size(crop_size, "crop_size");
    118     
    119     FIBITMAP * cropPic = FreeImage_Copy(sourcePic, 0, 0, crop_size.width, crop_size.height);
    120     
    121     FreeImage_Unload(sourcePic);
    122     sourcePic = NULL;
    123     
    124     return cropPic;
    125     
    126 }
    127 
    128 inline FIBITMAP * get_resize_picture(FIBITMAP *sourcePic, ImageSize des_size)
    129 {
    130     
    131     int src_width, src_height;
    132     
    133     //获取图片大小 
    134     src_width  = FreeImage_GetWidth(sourcePic);
    135     src_height = FreeImage_GetHeight(sourcePic);        
    136     
    137     struct ImageSize src_size = {src_width, src_height};
    138     
    139     if(!is_need_resize(src_size, des_size))
    140         return sourcePic;
    141         
    142     struct ImageSize resize_size = get_resize_size(src_size, des_size);
    143     //print_size(resize_size, "resize_size");
    144 
    145     FIBITMAP * resizePic = FreeImage_Rescale(sourcePic, resize_size.width, resize_size.height, FILTER_BOX);    
    146     
    147     FreeImage_Unload(sourcePic);
    148     sourcePic = NULL;
    149     
    150     return resizePic;
    151 
    152 }
    153 
    154 int get_file_size1(const char * src_pic_path)
    155 {
    156     struct stat stat_buf;
    157     stat(src_pic_path, &stat_buf);
    158     int file_size =  stat_buf.st_size;
    159     
    160     return file_size;
    161 }
    162 
    163 int get_file_size2(const char * src_pic_path)
    164 {
    165     FILE * fp = fopen(src_pic_path, "rb");
    166     if(fp == NULL)
    167         return 0;
    168     
    169     fseek (fp, 0, SEEK_END); 
    170     int src_file_size = ftell(fp);
    171     fclose(fp);    
    172     
    173     return src_file_size;
    174 }
    175 
    176 int gen_symbolic_link(const char *src_pic_path, const char *des_pic_path)
    177 {
    178     char cmd[200];
    179     sprintf(cmd, "ln -s %s %s", src_pic_path, des_pic_path);
    180     int sh_ret = system(cmd);
    181     
    182     return sh_ret;
    183 }
    184 
    185 int gen_small_thumbnail(const char *src_pic_path, const char *des_pic_path, int des_width, int des_height)
    186 {
    187     //printf("gen_small_thumbnail:%s --> %s w:%d, h:%d
    ", src_pic_path, des_pic_path, des_width, des_height);
    188         
    189     struct ImageSize des_size = {des_width, des_height};
    190     
    191     FIBITMAP *sourcePic = NULL, *finalPic = NULL;
    192     FreeImage_Initialise();
    193     FREE_IMAGE_FORMAT pic_type = FIF_UNKNOWN;
    194     
    195     //获取图片格式 
    196     pic_type = FreeImage_GetFileType (src_pic_path, 0);
    197     //printf("xxxxxxx:%d %d 
    ", pic_type, FIT_BITMAP);
    198     //是否支持该格式类型 
    199     if(!FreeImage_FIFSupportsReading(pic_type))
    200         return 480;
    201         
    202     //载入图片 
    203     sourcePic = FreeImage_Load(pic_type, src_pic_path, 0);
    204     
    205     //剪切图片 
    206     sourcePic = get_crop_picture(sourcePic);
    207     if(!sourcePic)
    208         return 481;
    209     
    210     //缩略图片 
    211     sourcePic = get_resize_picture(sourcePic, des_size);
    212     if(!sourcePic)
    213         return 482;
    214     
    215     int returnValue = 0;
    216     
    217     //位图转换 
    218     finalPic = FreeImage_ConvertTo24Bits(sourcePic); 
    219     
    220     //保存图片 
    221     if(!FreeImage_Save(FIF_JPEG, finalPic, des_pic_path, JPEG_DEFAULT))
    222         returnValue = 499;
    223     
    224     //释放资源 
    225     FreeImage_Unload(sourcePic);
    226     FreeImage_Unload(finalPic);
    227     sourcePic = NULL;
    228     finalPic = NULL;
    229     FreeImage_DeInitialise();
    230     
    231     return returnValue;
    232 }
    233 
    234 int gen_mid_thumbnail(const char *src_pic_path, const char *des_pic_path, int des_width, int des_height)
    235 {
    236     //printf("gen_mid_thumbnail:%s --> %s w:%d, h:%d
    ", src_pic_path, des_pic_path, des_width, des_height);
    237     struct ImageSize des_size = {des_width, des_height};
    238     
    239     FIBITMAP *sourcePic = NULL, *finalPic = NULL;
    240     FreeImage_Initialise();
    241     FREE_IMAGE_FORMAT pic_type = FIF_UNKNOWN;
    242     
    243     //获取图片格式 
    244     pic_type = FreeImage_GetFileType (src_pic_path, 0);
    245     //printf("xxxxxxx:%d %d 
    ", pic_type, FIT_BITMAP);
    246     //是否支持该格式类型 
    247     if(!FreeImage_FIFSupportsReading(pic_type))
    248         return 480;
    249         
    250     //载入图片 
    251     sourcePic = FreeImage_Load(pic_type, src_pic_path, 0);
    252     
    253     struct ImageSize src_size = {FreeImage_GetWidth(sourcePic), FreeImage_GetHeight(sourcePic)}; 
    254     
    255     //缩略图片 
    256     int returnValue = 0;
    257         
    258     sourcePic = get_resize_picture(sourcePic, des_size);
    259     if(!sourcePic)
    260         return 482;    
    261 
    262     //int src_file_size = get_file_size2(src_pic_path);
    263     int file_size = get_file_size1(src_pic_path);
    264     
    265     if(is_need_resize(src_size, des_size) || file_size > MID_IMAGE_LIMIT_SIZE){
    266         //位图转换 
    267         finalPic = FreeImage_ConvertTo24Bits(sourcePic); 
    268     
    269         //保存图片 
    270         if(!FreeImage_Save(FIF_JPEG, finalPic, des_pic_path, JPEG_DEFAULT))
    271             returnValue = 499;
    272     }else{
    273         int sh_ret = gen_symbolic_link(src_pic_path, des_pic_path);
    274         //if(src_file_size > MID_IMAGE_LIMIT_SIZE)
    275         //printf("src_file_size:%d file_size:%d sh:%d
    ", src_file_size, file_size, sh_ret);    
    276     }
    277     
    278     //释放资源 
    279     FreeImage_Unload(sourcePic);
    280     FreeImage_Unload(finalPic);
    281     sourcePic = NULL;
    282     finalPic = NULL;
    283     FreeImage_DeInitialise();
    284     
    285     return returnValue;
    286 }
    287 
    288 /*
    289 
    290 usage:
    291 
    292     ./cpp_gen_thum src_pic_path des_pic_path height width type
    293     
    294     源文件地址 生成文件地址 目标高 目标宽 类型 
    295 
    296 */ 
    297 
    298 int main(int argc, char* argv[])
    299 {
    300 
    301     struct timeval t1,t2;
    302     double timeuse;
    303     gettimeofday(&t1,NULL);
    304 
    305     int height = atoi(argv[3]);
    306     int width = atoi(argv[4]);
    307     int thum_type = atoi(argv[5]);
    308     int result = 1;
    309     
    310     if(thum_type == THUM_TYPE_SMALL){
    311         result = gen_small_thumbnail(argv[1], argv[2], height, width);
    312     }else if(thum_type == THUM_TYPE_MID){
    313         result = gen_mid_thumbnail(argv[1], argv[2], height, width);
    314     }
    315     
    316     printf("%d", result);
    317     
    318 //    int small_res = gen_small_thumbnail(argv[1], argv[2], 120, 120);
    319 //    int mid_res = gen_mid_thumbnail(argv[1], argv[3], 640, 640);
    320 //    
    321 //    gettimeofday(&t2,NULL);
    322 //    timeuse = t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec)/1000000.0;
    323 //    printf("Use Time:%f small_res:%d filename:%s
    		  mid_res:%d filename:%s
    ", 
    324 //        timeuse, small_res, argv[2], mid_res, argv[3]);
    325     return 0;
    326 }
    View Code
  • 相关阅读:
    算法第五章作业
    算法第四章作业
    算法第四章上机实践报告
    算法第三章作业——动态规划
    算法第三章上机实践报告
    分治法的思想与体会
    算法第二章上机实践报告
    c++代码规范及《数学之美》读后感
    bugkuctf web部分(前8题)解题报告
    第二次博客作业
  • 原文地址:https://www.cnblogs.com/GO-NO-1/p/7700072.html
Copyright © 2011-2022 走看看