• FreeImage编译及遇到问题解决


    FreeImage编译及遇到问题解决

    1、下载freeImage源码包

    wget http://downloads.sourceforge.net/freeimage/FreeImage3170.zip
    #解压
    unzip FreeImage3170.zip -d freeImage
    

    2、Linux下编译

    编译环境及工具说明

    • 操作系统:Ubuntu 16.04 64位,内核版本4.4.0-31
    • 编译工具: gcc 5.4 工具链
    • 硬件环境:Intel(R) Core(TM) i5-4460处理器 + 8GB内存

    进入freeImage源码目录下,执行make命令。

    2.1、类型转换错误

    这个问题出现在dcraw_common.cpp这个文件中的45224543行之间。
    报错信息如下

    Source/LibRawLite/./internal/dcraw_common.cpp: 在成员函数‘void LibRaw::vng_interpolate()’中:
    Source/LibRawLite/./internal/dcraw_common.cpp:4546:3: 错误:在 {} 内将‘128’从‘int’转换为较窄的类型‘signed char’ [-Wnarrowing]
       };
       ^
    Source/LibRawLite/./internal/dcraw_common.cpp:4546:3: 错误:在 {} 内将‘136’从‘int’转换为较窄的类型‘signed char’ [-Wnarrowing]
    Source/LibRawLite/./internal/dcraw_common.cpp:4546:3: 错误:在 {} 内将‘128’从‘int’转换为较窄的类型‘signed char’ [-Wnarrowing]
    Source/LibRawLite/./internal/dcraw_common.cpp:4546:3: 错误:在 {} 内将‘136’从‘int’转换为较窄的类型‘signed char’ [-Wnarrowing]
    Source/LibRawLite/./internal/dcraw_common.cpp:4546:3: 错误:在 {} 内将‘128’从‘int’转换为较窄的类型‘signed char’ [-Wnarrowing]
    Source/LibRawLite/./internal/dcraw_common.cpp:4546:3: 错误:在 {} 内将‘136’从‘int’转换为较窄的类型‘signed char’ [-Wnarrowing]
    

    我们把有问题的这段代码摘出来,可以看到{}中以十六进制表示的数字,有的是超过127的,因为字面整数默认是int类型,所以这里会出现这个错误。

    void CLASS vng_interpolate()
    {
      static const signed char *cp, terms[] = {
        -2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01,
        -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01,
        -2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03,
        -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06,
        -2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04,
        -1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01,
        -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40,
        -1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11,
        -1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11,
        -1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22,
        -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44,
        -1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10,
        -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04,
        +0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40,
        +0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20,
        +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08,
        +0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20,
        +0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44,
        +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60,
        +0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80,
        +1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40,
        +1,+0,+2,+1,0,0x10
      }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
    

    将上面的代码改为下面的形式即可

    void CLASS vng_interpolate()
    {
      static const signed char *cp, terms[] = {
        -2,-2,+0,-1,0,(char)0x01, -2,-2,+0,+0,1,(char)0x01, -2,-1,-1,+0,0,(char)0x01,
        -2,-1,+0,-1,0,(char)0x02, -2,-1,+0,+0,0,(char)0x03, -2,-1,+0,+1,1,(char)0x01,
        -2,+0,+0,-1,0,(char)0x06, -2,+0,+0,+0,1,(char)0x02, -2,+0,+0,+1,0,(char)0x03,
        -2,+1,-1,+0,0,(char)0x04, -2,+1,+0,-1,1,(char)0x04, -2,+1,+0,+0,0,(char)0x06,
        -2,+1,+0,+1,0,(char)0x02, -2,+2,+0,+0,1,(char)0x04, -2,+2,+0,+1,0,(char)0x04,
        -1,-2,-1,+0,0,(char)0x80, -1,-2,+0,-1,0,(char)0x01, -1,-2,+1,-1,0,(char)0x01,
        -1,-2,+1,+0,1,(char)0x01, -1,-1,-1,+1,0,(char)0x88, -1,-1,+1,-2,0,(char)0x40,
        -1,-1,+1,-1,0,(char)0x22, -1,-1,+1,+0,0,(char)0x33, -1,-1,+1,+1,1,(char)0x11,
        -1,+0,-1,+2,0,(char)0x08, -1,+0,+0,-1,0,(char)0x44, -1,+0,+0,+1,0,(char)0x11,
        -1,+0,+1,-2,1,(char)0x40, -1,+0,+1,-1,0,(char)0x66, -1,+0,+1,+0,1,(char)0x22,
        -1,+0,+1,+1,0,(char)0x33, -1,+0,+1,+2,1,(char)0x10, -1,+1,+1,-1,1,(char)0x44,
        -1,+1,+1,+0,0,(char)0x66, -1,+1,+1,+1,0,(char)0x22, -1,+1,+1,+2,0,(char)0x10,
        -1,+2,+0,+1,0,(char)0x04, -1,+2,+1,+0,1,(char)0x04, -1,+2,+1,+1,0,(char)0x04,
        +0,-2,+0,+0,1,(char)0x80, +0,-1,+0,+1,1,(char)0x88, +0,-1,+1,-2,0,(char)0x40,
        +0,-1,+1,+0,0,(char)0x11, +0,-1,+2,-2,0,(char)0x40, +0,-1,+2,-1,0,(char)0x20,
        +0,-1,+2,+0,0,(char)0x30, +0,-1,+2,+1,1,(char)0x10, +0,+0,+0,+2,1,(char)0x08,
        +0,+0,+2,-2,1,(char)0x40, +0,+0,+2,-1,0,(char)0x60, +0,+0,+2,+0,1,(char)0x20,
        +0,+0,+2,+1,0,(char)0x30, +0,+0,+2,+2,1,(char)0x10, +0,+1,+1,+0,0,(char)0x44,
        +0,+1,+1,+2,0,(char)0x10, +0,+1,+2,-1,1,(char)0x40, +0,+1,+2,+0,0,(char)0x60,
        +0,+1,+2,+1,0,(char)0x20, +0,+1,+2,+2,0,(char)0x10, +1,-2,+1,+0,0,(char)0x80,
        +1,-1,+1,+1,0,(char)0x88, +1,+0,+1,+2,0,(char)0x08, +1,+0,+2,-1,0,(char)0x40,
        +1,+0,+2,+1,0,(char)0x10
      }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
    

    2.2 C++11的原始字符串与宏定义R产生的错误

    这个错误是因为gcc 5.4这里支持的是C++ 11的标准,C++11中引入了原始字符串的新特性,使用R""方式来定义一个不进行转义的字符串。而在FreeImage的一些代码中,使用了R作为一些宏函数的参数,导致一些场合会将其当做是一个原始字符串。

    先来看一下报错信息

    Source/LibWebP/./src/dsp/dsp.upsampling_mips_dsp_r2.c:37:34: 错误:原始字符串分隔符中有无效字符‘ ’
           "shll_s.w         %["#R"],      %["#R"],        9              
    	"     
                                 ^     
    Source/LibWebP/./src/dsp/dsp.upsampling_mips_dsp_r2.c:37:48: 错误:原始字符串分隔符中有无效字符‘ ’
           "shll_s.w         %["#R"],      %["#R"],        9              
    	"     
                                               ^     
    Source/LibWebP/./src/dsp/dsp.upsampling_mips_dsp_r2.c:40:34: 错误:原始字符串分隔符中有无效字符‘ ’
           "precrqu_s.qb.ph  %["#R"],      %["#R"],        $zero          
    	"     
                                 ^     
    Source/LibWebP/./src/dsp/dsp.upsampling_mips_dsp_r2.c:40:48: 错误:原始字符串分隔符中有无效字符‘ ’
           "precrqu_s.qb.ph  %["#R"],      %["#R"],        $zero          
    	"     
                                               ^     
    Source/LibWebP/./src/dsp/dsp.upsampling_mips_dsp_r2.c:43:34: 错误:原始字符串分隔符中有无效字符‘ ’
           "srl              %["#R"],      %["#R"],        24             
    	"     
                                 ^     
    Source/LibWebP/./src/dsp/dsp.upsampling_mips_dsp_r2.c:43:48: 错误:原始字符串分隔符中有无效字符‘ ’
           "srl              %["#R"],      %["#R"],        24             
    	"     
    

    报错的文件是dsp.upsampling_mips_dsp_r2.c。这是一个.c的文件,使用gcc编译也会出现这个错误。

    报错的代码如下(dsp.upsampling_mips_dsp_r2.c 22-49)

    #if !defined(WEBP_YUV_USE_TABLE)
    
    #define YUV_TO_RGB(Y, U, V, R, G, B) do {                                      
        const int t1 = kYScale * Y;                                                
        const int t2 = kVToG * V;                                                  
        R = kVToR * V;                                                             
        G = kUToG * U;                                                             
        B = kUToB * U;                                                             
        R = t1 + R;                                                                
        G = t1 - G;                                                                
        B = t1 + B;                                                                
        R = R + kRCst;                                                             
        G = G - t2 + kGCst;                                                        
        B = B + kBCst;                                                             
        __asm__ volatile (                                                         
          "shll_s.w         %["#R"],      %["#R"],        9              
    	"     
          "shll_s.w         %["#G"],      %["#G"],        9              
    	"     
          "shll_s.w         %["#B"],      %["#B"],        9              
    	"     
          "precrqu_s.qb.ph  %["#R"],      %["#R"],        $zero          
    	"     
          "precrqu_s.qb.ph  %["#G"],      %["#G"],        $zero          
    	"     
          "precrqu_s.qb.ph  %["#B"],      %["#B"],        $zero          
    	"     
          "srl              %["#R"],      %["#R"],        24             
    	"     
          "srl              %["#G"],      %["#G"],        24             
    	"     
          "srl              %["#B"],      %["#B"],        24             
    	"     
          : [R]"+r"(R), [G]"+r"(G), [B]"+r"(B)                                     
          :                                                                        
        );                                                                         
      } while (0)
    

    上面代码中的第16行起,有多处是R"], 的形式。这里编译器会将其当做一个原始字符串,从而导致错误。
    做如下修改,将所有的R都使用Red替代。

    #if !defined(WEBP_YUV_USE_TABLE)
    
    #define YUV_TO_RGB(Y, U, V, Red, G, B) do {                                      
        const int t1 = kYScale * Y;                                                
        const int t2 = kVToG * V;                                                  
        Red = kVToR * V;                                                             
        G = kUToG * U;                                                             
        B = kUToB * U;                                                             
        Red = t1 + Red;                                                                
        G = t1 - G;                                                                
        B = t1 + B;                                                                
        Red = Red + kRCst;                                                             
        G = G - t2 + kGCst;                                                        
        B = B + kBCst;                                                             
        __asm__ volatile (                                                         
          "shll_s.w         %["#Red"],      %["#Red"],      9              
    	"     
          "shll_s.w         %["#G"],        %["#G"],        9              
    	"     
          "shll_s.w         %["#B"],        %["#B"],        9              
    	"     
          "precrqu_s.qb.ph  %["#Red"],      %["#Red"],      $zero          
    	"     
          "precrqu_s.qb.ph  %["#G"],        %["#G"],        $zero          
    	"     
          "precrqu_s.qb.ph  %["#B"],        %["#B"],        $zero          
    	"     
          "srl              %["#Red"],      %["#Red"],      24             
    	"     
          "srl              %["#G"],        %["#G"],        24             
    	"     
          "srl              %["#B"],        %["#B"],        24             
    	"     
          : [R]"+r"(R), [G]"+r"(G), [B]"+r"(B)                                     
          :                                                                        
        );                                                                         
      } while (0)
    

    这个错误还会出现在Source/LibWebP/./src/dsp/dsp.yuv_mips_dsp_r2.c文件中,修改的方式是一样的。

    2.3 tmpnam与mkstemp的选择

    这并不是一个错误,只是一个警告。

    Source/LibJXR/./image/encode/strenc.o:在函数‘StrIOEncInit’中:
    strenc.c:(.text+0x17cc): 警告: the use of `tmpnam' is dangerous, better use `mkstemp'
    

    tmpnam函数是危险的,建议使用mkstemp。原因是mkstemp调用完成后,就已经生成并打开了一个临时文件,而tmpnam只是生成了一个临时文件的文件名,并没有创建文件,不能保证其一定不存在!!!
    这里就不做修改了。

    2.4 安装到指定目录

    编译完成后,可以使用make install命令进行安装。默认的安装目录是/usr下。我们可以使用如下命令指定安装目录。

    > sudo make DESTDIR=/home/o/code/freeimage install
    [sudo] o 的密码: 
    make -f Makefile.gnu install 
    make[1]: Entering directory '/media/o/work/development_library/FreeImage'
    install -d /home/o/code/freeimage/usr/include /home/o/code/freeimage/usr/lib
    install -m 644 -o root -g root Source/FreeImage.h /home/o/code/freeimage/usr/include
    install -m 644 -o root -g root libfreeimage.a /home/o/code/freeimage/usr/lib
    install -m 755 -o root -g root libfreeimage-3.17.0.so /home/o/code/freeimage/usr/lib
    ln -sf libfreeimage-3.17.0.so /home/o/code/freeimage/usr/lib/libfreeimage.so.3
    ln -sf libfreeimage.so.3 /home/o/code/freeimage/usr/lib/libfreeimage.so	
    make[1]: Leaving directory '/media/o/work/development_library/FreeImage'
    

    到安装目录下查看一下

    /home/o/code/freeimage/usr [o@o-pc] [12:05]
    > tree
    .
    ├── include
    │   └── FreeImage.h
    └── lib
        ├── libfreeimage-3.17.0.so
        ├── libfreeimage.a
        ├── libfreeimage.so -> libfreeimage.so.3
        └── libfreeimage.so.3 -> libfreeimage-3.17.0.so
    
    2 directories, 5 files
    

    3、VS2015进行编译

    我当前下载的版本,里面没有带VS2015的工程文件。但是有VS2005/2008/2013的。

    直接使用VS2015打开源码目录下的FreeImage.2013.sln文件,然后升级 VC++ 编译器和库

    3.1 源码的修改

    1、将文件tif_config.h中的

    #ifdef _WIN32
    #define snprintf _snprintf	// 将此行注释掉
    #define lfind _lfind
    #endif // _WIN32
    

    修改为

    #ifdef _WIN32
    //#define snprintf _snprintf
    #define lfind _lfind
    #endif // _WIN32
    

    早期的VC自带的C标准库中确实没有snprintf这个函数,只有_snprintf。但是VS2015下是有的,所以这里不注释掉会有重定义的问题。
    也可以修改为

    #ifdef _WIN32
    #if defined(_MSC_VER) && _MSC_VER < 1900
    #define snprintf _snprintf
    #endif
    #define lfind _lfind
    #endif // _WIN32
    

    3.2 编译和生成

    直接构建解决方案即可。编译完成后可以到源码目录下的Dist目录拷贝FreeImage.h和库文件。

  • 相关阅读:
    Weekly blog for week 1908
    Weekly blog for week 1907
    Weekly blog for week 1905&1906
    Weekly blog for week 1904
    Write Week 3 Blog beforehand
    Add Week 2 Blog
    First week of a new year
    Andriod-Log
    bat
    学习方法
  • 原文地址:https://www.cnblogs.com/oloroso/p/5777959.html
Copyright © 2020-2023  润新知