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              \n\t"     \
                             ^     
Source/LibWebP/./src/dsp/dsp.upsampling_mips_dsp_r2.c:37:48: 錯誤:原始字符串分隔符中有無效字符‘ ’
       "shll_s.w         %["#R"],      %["#R"],        9              \n\t"     \
                                           ^     
Source/LibWebP/./src/dsp/dsp.upsampling_mips_dsp_r2.c:40:34: 錯誤:原始字符串分隔符中有無效字符‘ ’
       "precrqu_s.qb.ph  %["#R"],      %["#R"],        $zero          \n\t"     \
                             ^     
Source/LibWebP/./src/dsp/dsp.upsampling_mips_dsp_r2.c:40:48: 錯誤:原始字符串分隔符中有無效字符‘ ’
       "precrqu_s.qb.ph  %["#R"],      %["#R"],        $zero          \n\t"     \
                                           ^     
Source/LibWebP/./src/dsp/dsp.upsampling_mips_dsp_r2.c:43:34: 錯誤:原始字符串分隔符中有無效字符‘ ’
       "srl              %["#R"],      %["#R"],        24             \n\t"     \
                             ^     
Source/LibWebP/./src/dsp/dsp.upsampling_mips_dsp_r2.c:43:48: 錯誤:原始字符串分隔符中有無效字符‘ ’
       "srl              %["#R"],      %["#R"],        24             \n\t"     \

報錯的文件是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              \n\t"     \
      "shll_s.w         %["#G"],      %["#G"],        9              \n\t"     \
      "shll_s.w         %["#B"],      %["#B"],        9              \n\t"     \
      "precrqu_s.qb.ph  %["#R"],      %["#R"],        $zero          \n\t"     \
      "precrqu_s.qb.ph  %["#G"],      %["#G"],        $zero          \n\t"     \
      "precrqu_s.qb.ph  %["#B"],      %["#B"],        $zero          \n\t"     \
      "srl              %["#R"],      %["#R"],        24             \n\t"     \
      "srl              %["#G"],      %["#G"],        24             \n\t"     \
      "srl              %["#B"],      %["#B"],        24             \n\t"     \
      : [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              \n\t"     \
      "shll_s.w         %["#G"],        %["#G"],        9              \n\t"     \
      "shll_s.w         %["#B"],        %["#B"],        9              \n\t"     \
      "precrqu_s.qb.ph  %["#Red"],      %["#Red"],      $zero          \n\t"     \
      "precrqu_s.qb.ph  %["#G"],        %["#G"],        $zero          \n\t"     \
      "precrqu_s.qb.ph  %["#B"],        %["#B"],        $zero          \n\t"     \
      "srl              %["#Red"],      %["#Red"],      24             \n\t"     \
      "srl              %["#G"],        %["#G"],        24             \n\t"     \
      "srl              %["#B"],        %["#B"],        24             \n\t"     \
      : [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和庫文件。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM