CxImage






4.65/5 (944投票s)
CxImage 是一个 C++ 类,用于加载、保存、显示、转换 BMP、JPEG、GIF、PNG、TIFF、MNG、ICO、PCX、TGA、WMF、WBMP、JBG、J2K 图像。
前言
距离上一版本多年后,我可以告诉大家,这篇文章经受住了作者的考验,即使我对这个库的局限性的看法没有改变,更新也确实是必要的。
非常感谢所有为这个新版本做出贡献的人,他们提供了数百项大小不一的改进,我的角色主要是将所有部分整合在一起。
简介与许可
CxImage
是一个 C++ 类,它可以非常简单快速地加载、保存、显示和转换图像。
CxImage
类是免费的;至于 TIFF、JPEG、PNG 和 ZLIB 库:“如果您在产品中使用此源代码,无需致谢,但我们将不胜感激。”
CxImage
是开源的,并根据zlib 许可证授权。简而言之,这意味着您可以随意使用该代码,只要您不声称是您自己的。
6.00 版新增内容
完整的错误修复和增强列表已在文档中报告(请参阅 * \doc\cximage_history.htm* 或此链接)。在此,我将重点介绍一些新功能。
使用 CxImage
5.99 版编写的应用程序也应该能与新版本兼容;少数方法的接口已更改,通常是由于新增了参数,但默认行为保持不变。
与旧 DLL 链接的应用程序将无法与新 DLL 一起使用;但如果需要,您可以编辑声明或添加新重载,以便为 DLL 恢复旧接口。需要注意的一个问题是 ENUM_CXIMAGE_FORMATS
:在旧版本中,CXIMAGE_FORMAT_...
的值可能会根据相应 CXIMAGE_SUPPORT_...
开关启用的支持格式而改变。在新版本中,CXIMAGE_FORMAT_...
被分配了唯一的值。静态方法,如 GetNumTypes
、GetTypeIdFromName
、GetTypeIdFromIndex
、GetTypeIndexFromId
,将帮助应用程序管理新策略。
文件格式与链接的 C 库
CxImage
使用以下库的最新版本:Zlib (1.2.3)、Jasper (1.900.1)、LibMNG (1.0.10)、LibPNG (1.2.24)。LibTIFF 3.8.2 可以与 CxImage
链接,但 CxImage
分发版中包含的版本 (3.5.7, 已打补丁) 可以读取带有 OJPEG 压缩或非标准位深度的图像。选择权在您。
j2k 库(现在是 openjpeg)及其关联类 CxImageJ2K
已从项目中移除。JPEG2000 图像通过 Jasper 和 CxImageJAS 支持。
CxImage
6.00 包括一个新类 (CxImageRAW
) 和一个新库 (LibDCR) 来读取数码相机的 RAW 图像;常见文件扩展名包括:RAW、CRW、NEF、CR2、DNG、ORF、ARW、ERF、3FR、DCR、X3F、MEF、RAF、MRW、PEF、SR2。LibDCR 基于 Dave Coffin 的dcraw.c;并提供与原始 dcraw 应用程序相同的功能(请参阅 \raw 目录中包含的 "dcr.dsw" 项目)。GPL v2 下的受限功能已被禁用;请在启用受限代码前阅读 "libdcr.h" 中的许可条款。
CxImageRAW
实现了解码图像的基本功能,唯一可通过 SetCodecOption
控制的选项是关于插值质量(DECODE_QUALITY_LIN=0, DECODE_QUALITY_VNG=1, DECODE_QUALITY_PPG=2, DECODE_QUALITY_AHD=3
)。
CxImagePNG
已得到改进,可以读写所有 PNG_COLOR_TYPE_...
组合。每通道像素深度超过 8 位的 PNG 将被转换为 8 位,这是 CxImage
的主要限制。
CxImageGIF
:改进了对读取动画 GIF 的支持,现在可以在启用 SetRetreiveAllFrames
的情况下,一次性解码所有帧。CxImage
演示程序实现了此选项,并展示了如何播放动画 GIF(当程序询问“文件包含 N 张图像。全部读取?”时,选择“取消”)。
CxImageBMP
:读取和写入 32 位图像(带 alpha 通道)。CxImageICO
:读取和写入 Vista (PNG) 图标;并增加了对写入多页图标的支持。CxImageMNG
:读取带 alpha 通道的 MNG。CxImageSKA
:用于 SKA 图像格式的新类,该格式在某些视频租赁应用程序中使用。
CxImageJPG
:JPEG 格式的子采样(ENCODE_SUBSAMPLE_422, ENCODE_SUBSAMPLE_444
)的新选项,默认值为 4:1:1(高),可设置为 4:2:2(中)或 4:4:4(无)。
下表显示了使用不同子采样压缩的图像中不同程度的伪影。4:4:4 子采样对于边缘锐利的图像很有用,可以减少 JPG 压缩的典型模糊效果。
![]() 原始图像 |
![]() ![]() JPG 图像和伪影, 质量 75,子采样 4:1:1 |
![]() ![]() JPG 图像和伪影, 质量 75,子采样 4:4:4 |
---|
可移植性
该类和项目已在不同的编译器上进行了测试,从 Microsoft VC++6 到 VC++2008,以及 Borland C++ Builder 3 和 6,并部分测试了 wxDev-C++ 和 MinGW。
所有库都提供了 UNICODE 和非-UNICODE 配置(感谢 Eric Jesover)。
首次使用此库的用户,或需要基本模板而不希望包含完整演示项目中的杂乱内容的用户,可以获得一个轻量级版本(cximage600_lite),该版本不包含 C 库,并且有一个小型演示。
控制台 (\demo2) 和 CxImageCrtDll 项目可以使用 VC++Express2005 和 Microsoft Platform SDK 进行构建。如果遇到链接器错误,如“未解析的外部符号...”,请检查所有 C 库是否已编译(设置正确的项目依赖项),或将 *gdi32.lib* 和 *user32.lib* 模块添加到“链接器\输入\附加依赖项”属性中。
CxImage
也支持 Pocket PC 2003;为 VC++2005 编译器提供了一个可用版本和演示(cximage600_ce)(感谢 Vincent Richomme)。对于旧的嵌入式 VC 编译器,主要限制是异常处理的支持。为了克服这个问题,*try
*、*throw
* 和 *catch
* 语句已被三个宏(在 *ximadef.h* 中定义)和 CXIMAGE_SUPPORT_EXCEPTION_HANDLING
定义所取代;这样就可以在不启用异常处理支持的情况下构建库。解决方案可能不是那么优雅,但当禁用异常处理时,对源代码的影响很小,而在启用异常处理的情况下则没有变化。
内置格式(bmp、ico、tga、pcx、gif、ska)的字节序(小端序和大数据序)兼容性通过 ntohs
和 ntohl
处理。
演示
几乎所有新功能都可以在主 CxImage
演示应用程序中进行测试。该演示只是一个测试平台,尽管它提供了一些不错的功能,但它并不打算成为一个严肃的应用程序。
- CQuantizer:该类与“调色板”菜单一起使用。在上一版本中,存在一个四舍五入错误,当白色(255,255,255)有时被转换为(254,254,254)时,该错误非常明显。在新版本中,此错误已修复。
- 复制/粘贴:现在还可以粘贴图元文件图像(例如,从 Office 应用程序)。演示程序内部使用自定义剪贴板格式,以测试
Dump/Undump
方法。
复制作用于活动选区,使用 *\CxImage\Remove Selection* 复制整个图像。 - FloodFill:(*\View\Tools\Flood Fill*)通过一个浮动对话框,您可以测试
FloodFill
的颜色、容差、不透明度和选区。当不透明度=0 且启用选区时,此功能相当于“魔棒”。 - 图表数据提取:(*\Filters\graph data extraction*)从图表中提取数值数据(通过扫描仪获取或从互联网下载)。转换后的值将粘贴到剪贴板,并可以保存到文本文件或 Excel 文件。
数据提取对话框和结果 - RedEyeRemove:(*\Filters\Non Linear\Remove Red Eye*)移除图像中经常出现的红眼效果。您必须选择瞳孔周围的区域,函数将在此区域过滤红色通道。选区也可以是矩形,或包含部分虹膜:过滤器作用于以选区为中心的圆形区域。
原始图像
瞳孔周围的选区RedEyeRemove
后的结果 - SelectiveBlur / UnsharpMask:这些非线性滤镜可以提高图像质量。
SelectiveBlur
在保留细节的同时去除“颗粒状”噪点(jpeg 伪影或数码相机噪点),UnsharpMask
在增强细节的同时不会在“平坦”区域添加噪点。 - 自定义线性滤镜:(*\Filters\Linear\Custom*)一个小型图形界面,用于测试
Filter
函数的新内核(感谢 Priyank Bolia)。 - 直方图:(*\Colors\Histogram\...*)提供了许多菜单来测试具有不同方法的
HistogramStretch
(0 = 亮度,1 = 链接通道,2 = 独立通道);*threshold* 参数提高了算法在图像噪点较多时的鲁棒性。“半饱和”和“全饱和”测试了ConvertColorSpace
、Histogram
和Saturate
的组合,用于拉伸 YUV 色彩空间中的直方图。
原始图像+ HistogramStretch(2,0.005f)
+ “半饱和” - 阈值处理:(*\Colors\Threshold*... 和 *\Colors\Adaptive Threshold*)。
OptimalThreshold
是一种新的图像二值化最佳阈值查找方法,可用算法包括:
1 = Otsu;
2 = Kittler & Illingworth;
3 = 最大熵;
4 = 势差;
0 = 平均所有方法(默认,并在演示中使用);“保留小于阈值的颜色”选项将测试
Threshold2
,这对于过滤带有噪点背景的彩色图像很有用,结果将是一个具有统一背景的彩色图像。AdaptiveThreshold
是OptimalThreshold
的应用,用于构建可变阈值掩码。AdaptiveThreshold
对于亮度不均匀的图像很有用,因为单一阈值无法对整个图像都最优;但总的来说,如果参数没有正确调整,它会产生不好的结果。
原始图像OptimalThreshold
+Threshold
AdaptiveThreshold
- 添加阴影:(*\Filters\Add Shadow*...)此菜单是如何将简单的
CxImage
方法(选区、GaussianBlur
、Mix
)组合起来实现常见效果的一个小例子。
白色背景上的紫色阴影
红色背景上的黑色阴影 - 文本平滑:
DrawStringEx
实现了一个新选项,通过CXTEXTINFO::smooth
,可以通过文本工具(*\View\Tools\Text*)来测试,勾选“抗锯齿”选项。在后期处理中,可以使用
TextBlur
(*\Filters\Non Linear\Text Blur*)获得类似的效果:这是一个非线性滤镜,它只作用于对角线或圆形边缘,而不影响垂直或水平线。下表是不同平滑方法之间的比较。
未平滑处理的DrawStringEx
平滑处理的DrawStringEx
使用TextBlur
进行后期处理
使用线性 3x3 “柔化”Filter
进行后期处理
CxImage 结构
在库的垂直层次结构中,CxImage
位于其他模块的顶部,这不是一个清晰的 OOP 方法,但结果自第一个版本以来一直很好,现在更改为时已晚。不过,您始终可以使用派生类执行特定于格式的操作,例如使用 CxImageTIF
保存多页 TIFF。
连接所有模块和 C 库的粘合剂是 CxFile
,一个虚拟类,它提供了从磁盘或内存文件访问数据的标准方法。
Cximage
对象本质上是一个位图,并添加了一些成员变量来存储有用信息。
class CxImage { ... protected: void* pDib; //contains the header, the palette, the pixels BITMAPINFOHEADER head; //standard header CXIMAGEINFO info; //extended information BYTE* pSelection; //selected region BYTE* pAlpha; //alpha channel CxImage** ppLayers; //generic layers CxImage** ppFrames; //frames for animation }
CxImage::head
是位图头,CxImage::pDib
是一个普通的位图(正如您在 CxImageBMP::Encode
的实现中所见)。
CxImage::info
是一个方便的容器,包含许多在不同格式和所有成员函数之间共享的信息。
typedef struct tagCxImageInfo { DWORD dwEffWidth; //DWORD aligned scan line width BYTE* pImage; //THE IMAGE BITS void* pGhost; //if this is a ghost, pGhost point to the body DWORD dwType; //original image format char szLastError[256]; //debugging long nProgress; //monitor long nEscape; //escape long nBkgndIndex; //used for GIF, PNG, MNG RGBQUAD nBkgndColor; //used for RGB transparency BYTE nQuality; //used for JPEG long nFrame; //used for TIF, GIF, MNG : actual frame long nNumFrames; //used for TIF, GIF, MNG : total number of //frames DWORD dwFrameDelay; //used for GIF, MNG long xDPI; //horizontal resolution long yDPI; //vertical resolution RECT rSelectionBox; //bounding rectangle BYTE nAlphaMax; //max opacity (fade) bool bAlphaPaletteEnabled; //true if alpha values in the palette are // enabled. bool bEnabled; //enables the painting functions long xOffset; long yOffset; DWORD dwEncodeOption; //for GIF, TIF : 0=def.1=unc,2=fax3,3=fax4, // 4=pack,5=jpg RGBQUAD last_c; //for GetNearestIndex optimization BYTE last_c_index; bool last_c_isvalid; long nNumLayers; DWORD dwFlags; } CXIMAGEINFO;
|
![]() |
CxImage::pDib
是背景图像。CxImage::pAlpha
是透明度层。CxImage::pSelection
是选区层,用于为图像处理创建感兴趣的区域。除了这 3 个特定平面外,您还可以添加其他通用层,存储在 CxImage::ppLayers
中。通用层是完整的 CxImage 对象,因此您可以构建复杂的嵌套层结构。CxImage::ppFrames
用于动画图像(GIF)。
CxImage 类成员与操作
CxImage 使用Doxygen 进行文档记录,但由于历史原因,许多不常见的特性仍然未被记录。类成员参考、版本历史和许可证可以在此处 找到。
支持的格式和选项
整个库相当庞大,在主头文件 *ximcfg.h* 中,您可以找到用于启用或禁用特定图形格式或功能的开关。每个 JPG、PNG 和 TIFF 库会为最终应用程序增加约 100KB 的大小,而 CxImage
本身的影响约 50KB。因此,您应该只支持并链接您的应用程序真正需要的格式。
格式 | #define | 所需库 | 大小 [KB] |
BMP GIF ICO TGA PCX WBMP WMF SKA |
CXIMAGE_SUPPORT_BMP |
内置 |
24 |
JPEG | CXIMAGE_SUPPORT_JPG |
jpeg |
88 |
PNG | CXIMAGE_SUPPORT_PNG |
png, zlib |
104 |
MNG | CXIMAGE_SUPPORT_MNG |
mng, zlib, jpeg |
148 |
TIFF | CXIMAGE_SUPPORT_TIF |
tiff, zlib, jpeg |
124 |
JBIG | CXIMAGE_SUPPORT_JBG |
jbig |
28 |
PNM,PPM,PGM RAS |
CXIMAGE_SUPPORT_PNM |
jasper |
176 |
JPEG-2000 | CXIMAGE_SUPPORT_JP2 |
jasper |
176 |
RAW | CXIMAGE_SUPPORT_RAW |
libdcr | 132 |
选项 | #define | 大小 [KB] |
CxImage 核心 | 所有开关关闭 | 20 |
几何变换 | CXIMAGE_SUPPORT_TRANSFORMATION |
16 |
图像处理 | CXIMAGE_SUPPORT_DSP |
24 |
绘图和 Windows 特定函数 | CXIMAGE_SUPPORT_WINDOWS |
12 |
透明度 | CXIMAGE_SUPPORT_ALPHA |
4 |
选区 | CXIMAGE_SUPPORT_SELECTION |
4 |
多层 | CXIMAGE_SUPPORT_LAYERS |
< 4 |
图形格式转换 | CXIMAGE_SUPPORT_DECODE |
< 4 |
插值函数 | CXIMAGE_SUPPORT_INTERPOLATION |
< 4 |
异常处理 | CXIMAGE_SUPPORT_EXCEPTION_HANDLING |
< 4 |
在您的项目中itor 使用 CxImage
CxImgLib.dsw 工作区显示了构建应用程序 (demo.exe) 所需的库,其中包括 CxImage 中几乎所有可用的功能和格式。在链接最终应用程序之前,您必须编译所有库。
构建项目需要几分钟时间才能完成。一切就绪后,选择演示项目并启动应用程序。 |
CxImgLib.dsw![]() |
要在您的项目中itor 使用 CxImage,您必须编辑这些设置。
Project Settings
|- C/C++
| |- Code Generation
| | |- Use run-time library : Multithreaded DLL (must be the same for
| | | all the linked libraries)
| | |- Struct member alignment : must be the same for all the linked
| | | libraries
| |- Precompiled headers : not using precompiled headers
| |- Preprocessor
| |- Additional Include Directories: ..\cximage
|- Link
|- General
|- Object/library modules: ../png/Debug/png.lib
../raw/Debug/libdcr.lib
../jpeg/Debug/jpeg.lib
../zlib/Debug/zlib.lib
../tiff/Debug/tiff.lib
../jasper/Debug/jasper.lib
../cximage/Debug/cximage.lib ...
在您的源代码中,您必须添加 `#include "ximage.h"`
注意:请勿混合调试和发布模块;每个配置都必须使用其各自的库模块。
在 CxImage 中添加自定义函数
使用 CxImage
编写新的图像处理函数并不难。在此,我将描述 CxImage::Jitter
— 它非常简单,但它展示了在 CxImage 中工作时需要注意的许多方面。首先,当然是声明:bool Jitter(long radius=2);
在 *ximage.h* 的 CXIMAGE_SUPPORT_DSP
部分,您可以在类的 `public` 作用域中的任何位置声明该函数。现在是定义。
bool CxImage::Jitter(long radius)
{
// check if the image is valid, this should be always the first line in
// the function
if (!pDib) return false;
// local variables
long nx,ny;
// temporary image to store the partial results of the algorithm
CxImage tmp(*this,pSelection!=0,true,true);
// limit the effects of the functions only in the smallest rectangle that
// holds the selected region (defined with the Selection...() functions ),
// this will speed up the loops.
long xmin,xmax,ymin,ymax;
if (pSelection){
xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
} else {
xmin = ymin = 0;
xmax = head.biWidth; ymax=head.biHeight;
}
// main loop : scan the image in vertical direction
for(long y=ymin; y <ymax; y++){
// monitor the progress of the loops
info.nProgress = (long)(100*y/head.biHeight);
// let the application a way to exit quickly
if (info.nEscape) break;
// main loop : scan the image in horizontal direction
for(long x=xmin; x<xmax; x++){
// if the feature is enabled, process only the pixels inside the
// selected region
#if CXIMAGE_SUPPORT_SELECTION
if (SelectionIsInside(x,y))
#endif //CXIMAGE_SUPPORT_SELECTION
{
// main algorithm
nx=x+(long)((rand()/(float)RAND_MAX - 0.5)*(radius*2));
ny=y+(long)((rand()/(float)RAND_MAX - 0.5)*(radius*2));
if (!IsInside(nx,ny)) {
nx=x;
ny=y;
}
// save the result in the temporary image.
// if you can, use PixelColor only for 24 bpp images,
// and PixelIndex for 8, 4 and 1 bpp images : it's faster
if (head.biClrUsed==0){
tmp.SetPixelColor(x,y,GetPixelColor(nx,ny));
} else {
tmp.SetPixelIndex(x,y,GetPixelIndex(nx,ny));
}
// if the feature is enabled, process also the pixels
// in the alpha layer
#if CXIMAGE_SUPPORT_ALPHA
tmp.AlphaSet(x,y,AlphaGet(nx,ny));
#endif //CXIMAGE_SUPPORT_ALPHA
}
}
}
// save the result and exit
Transfer(tmp);
return true;
}
示例:如何...
...将一种格式转换为另一种格式
CxImage image;
// bmp -> jpg
image.Load("image.bmp", CXIMAGE_FORMAT_BMP);
if (image.IsValid()){
if(!image.IsGrayScale()) image.IncreaseBpp(24);
image.SetJpegQuality(80);
image.Save("image.jpg",CXIMAGE_FORMAT_JPG);
}
// png -> tif
image.Load("image.png", CXIMAGE_FORMAT_PNG);
if (image.IsValid()){
image.Save("image.tif",CXIMAGE_FORMAT_TIF);
}
...加载图像资源
//Load the resource IDR_PNG1 from the PNG resource type
CxImage* newImage = new CxImage();
newImage->LoadResource(FindResource(NULL,MAKEINTRESOURCE(IDR_PNG1),
"PNG"),CXIMAGE_FORMAT_PNG);
或//Load the resource IDR_JPG1 from DLL
CxImage* newImage = new CxImage();
HINSTANCE hdll=LoadLibrary("imagelib.dll");
if (hdll){
HRSRC hres=FindResource(hdll,MAKEINTRESOURCE(IDR_JPG1),"JPG");
newImage->LoadResource(hres,CXIMAGE_FORMAT_JPG,hdll);
FreeLibrary(hdll);
}
或//Load a bitmap resource;
HBITMAP bitmap = ::LoadBitmap(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDB_BITMAP1)));
CxImage *newImage = new CxImage();
newImage->CreateFromHBITMAP(bitmap);
...从内存解码图像
CxImage image((BYTE*)buffer,size,image_type);
或CxMemFile memfile((BYTE*)buffer,size);
CxImage image(&memfile,image_type);
或CxMemFile memfile((BYTE*)buffer,size);
CxImage* image = new CxImage();
image->Decode(&memfile,type);
...将图像编码到内存
long size=0;
BYTE* buffer=0;
image.Encode(buffer,size,image_type);
...
image.FreeMemory(buffer);
或CxMemFile memfile; memfile.Open(); image.Encode(&memfile,image_type); BYTE* buffer = memfile.GetBuffer(); long size = memfile.Size(); ... image.FreeMemory(buffer);
...创建多页 TIFF
CxImage *pimage[3];
pimage[0]=&image1;
pimage[1]=&image2;
pimage[2]=&image3;
FILE* hFile;
hFile = fopen("multipage.tif","w+b");
CxImageTIF multiimage;
multiimage.Encode(hFile,pimage,3);
fclose(hFile);
或FILE* hFile;
hFile = fopen("c:\\multi.tif","w+b");
CxImageTIF image;
image.Load("c:\\1.tif",CXIMAGE_FORMAT_TIF);
image.Encode(hFile,true);
image.Load("c:\\2.bmp",CXIMAGE_FORMAT_BMP);
image.Encode(hFile,true);
image.Load("c:\\3.png",CXIMAGE_FORMAT_PNG);
image.Encode(hFile);
fclose(hFile);
...复制/粘贴图像
//copy
HANDLE hDIB = image->CopyToHandle();
if (::OpenClipboard(AfxGetApp()->m_pMainWnd->GetSafeHwnd())) {
if(::EmptyClipboard()) {
if (::SetClipboardData(CF_DIB,hDIB) == NULL ) {
AfxMessageBox( "Unable to set Clipboard data" );
} } }
CloseClipboard();
//paste
HANDLE hBitmap=NULL;
CxImage *newima = new CxImage();
if (OpenClipboard()) hBitmap=GetClipboardData(CF_DIB);
if (hBitmap) newima->CreateFromHANDLE(hBitmap);
CloseClipboard();
...在 Picture Box 中显示文件
HBITMAP m_bitmap = NULL;
CxImage image("myfile.png", CXIMAGE_FORMAT_PNG);
...
CDC* hdc = m_picture.GetDC();
HBITMAP m_bitmap = image.MakeBitmap(hdc->m_hDC);
HBITMAP hOldBmp = m_picture.SetBitmap(m_bitmap);
if (hOldBmp) DeleteObject(hOldBmp);
if (hdc->m_hDC) m_picture.ReleaseDC(hdc);
...
if (m_bitmap) DeleteObject(m_bitmap);
历史和致谢
从我的 CxDib
类开始,它只实现了内存 DIB,我试图添加一些从文件读取图像的成员。在寻找解决方案时,我在网上找到了一个名为 CImage
的不错的 MFC 类,版本 1.4(1998 年)。CImage
支持 BMP、GIF、PNG 和 JPG,但存在许多小错误,并且使用了复杂的类结构,因此我决定将其剥离到基础,并将 CxDib
与 CImage
的理念合并,以获得新的 CxImage
类。我还更新了 JPG、PNG 和 ZLIB 的库。
使用 CxImage
可以非常轻松地添加新图像类型,因此我添加了 TIFF 库(rev. 6)以及对 ICON
s、MNG、TGA 和 PCX 的基本支持。最后,我添加了一些特定函数,用于从全局 HANDLE
(Windows 剪贴板)和对象(Windows 资源)获取图像。这就是早期版本的故事,以下内容写在文档中。
- CImage © 1995-1998, Alejandro Aguilar Sierra。
- IJG JPEG 库 ©1994-1998, Thomas G. Lane。
- LibPNG v1.2.7 © 1998-2007 Glenn Randers-Pehrson
- LibTIFF v3.5.7 © 1988-1997 Sam Leffler, © 1991-1997 Silicon Graphics, Inc.
- LibMNG v1.0.10 © 2000,2002 Gerard Juyn。
- Gif-RLE © Hutchison Avenue Software Corporation, 1998
- LibJ2K© David Janssens, 2001 - 2002
- LibJBG v1.6 © Markus Kuhn, 2004
- JasPer v1.900.1 © Image Power, UBC, Michael David Adams, 2001 - 2007
- zlib v1.2.3 © 1995-2005 Jean-loup Gailly and Mark Adler
- 感谢 Troels Knakkergaard 在 CxImage 早期版本中的宝贵工作;Rajiv Ramachandran 的
CTwain
代码;Abe 的多页 TIFF 代码;Chris Shearer Cooper 的内存文件建议和代码;Brent Corkum 的BCMenu
代码。
每个库的每个头文件中都有更具体的致谢和免责声明。