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
这个文件中的4522
到4543
行之间。
报错信息如下
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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理