65.9K
CodeProject 正在变化。 阅读更多。
Home

CxImage

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.65/5 (944投票s)

2001年8月12日

Zlib

13分钟阅读

viewsIcon

14448267

downloadIcon

301881

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_... 被分配了唯一的值。静态方法,如 GetNumTypesGetTypeIdFromNameGetTypeIdFromIndexGetTypeIndexFromId,将帮助应用程序管理新策略。

文件格式与链接的 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)的字节序(小端序和大数据序)兼容性通过 ntohsntohl 处理。

演示

几乎所有新功能都可以在主 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* 参数提高了算法在图像噪点较多时的鲁棒性。“半饱和”和“全饱和”测试了 ConvertColorSpaceHistogramSaturate 的组合,用于拉伸 YUV 色彩空间中的直方图。

    原始图像

    + HistogramStretch(2,0.005f)

    + “半饱和”
  • 阈值处理:(*\Colors\Threshold*... 和 *\Colors\Adaptive Threshold*)。OptimalThreshold 是一种新的图像二值化最佳阈值查找方法,可用算法包括:
    1 = Otsu;
    2 = Kittler & Illingworth;
    3 = 最大熵;
    4 = 势差;
    0 = 平均所有方法(默认,并在演示中使用);

    “保留小于阈值的颜色”选项将测试 Threshold2,这对于过滤带有噪点背景的彩色图像很有用,结果将是一个具有统一背景的彩色图像。
    AdaptiveThresholdOptimalThreshold 的应用,用于构建可变阈值掩码。AdaptiveThreshold 对于亮度不均匀的图像很有用,因为单一阈值无法对整个图像都最优;但总的来说,如果参数没有正确调整,它会产生不好的结果。


    原始图像


    OptimalThreshold + Threshold


    AdaptiveThreshold

  • 添加阴影:(*\Filters\Add Shadow*...)此菜单是如何将简单的 CxImage 方法(选区、GaussianBlurMix)组合起来实现常见效果的一个小例子。

    白色背景上的紫色阴影

    红色背景上的黑色阴影
  • 文本平滑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 对象也是一组图层。每个图层中的缓冲区仅在需要时分配。

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
CXIMAGE_SUPPORT_GIF
CXIMAGE_SUPPORT_ICO
CXIMAGE_SUPPORT_TGA
CXIMAGE_SUPPORT_PCX
CXIMAGE_SUPPORT_WBMP
CXIMAGE_SUPPORT_WMF
CXIMAGE_SUPPORT_SKA

内置

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
CXIMAGE_SUPPORT_RAS

jasper

176
JPEG-2000 CXIMAGE_SUPPORT_JP2
CXIMAGE_SUPPORT_JPC
CXIMAGE_SUPPORT_PGX

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
CXIMAGE_SUPPORT_ENCODE
< 4
插值函数 CXIMAGE_SUPPORT_INTERPOLATION < 4
异常处理 CXIMAGE_SUPPORT_EXCEPTION_HANDLING < 4

在您的项目中itor 使用 CxImage

CxImgLib.dsw 工作区显示了构建应用程序 (demo.exe) 所需的库,其中包括 CxImage 中几乎所有可用的功能和格式。在链接最终应用程序之前,您必须编译所有库。
在同一个工作区中,您可以找到用于构建不同库和应用程序的项目。

  • CxImage:cximage.lib - 静态库
  • CxImageCrtDll:cximagecrt.dll - 不使用 mfc 的 DLL
  • CxImageMfcDll:cximage.dll - 使用 mfc 的 DLL
  • Demo:demo.exe - 与 cximage.lib 和 C 库链接的程序
  • DemoDll:demodll.exe - 与 cximagecrt.dll 链接的程序
  • libdcr、jasper、jbig、jpeg、png、tiff、zlib:静态 C 库

构建项目需要几分钟时间才能完成。一切就绪后,选择演示项目并启动应用程序。

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,但存在许多小错误,并且使用了复杂的类结构,因此我决定将其剥离到基础,并将 CxDibCImage 的理念合并,以获得新的 CxImage 类。我还更新了 JPG、PNG 和 ZLIB 的库。

使用 CxImage 可以非常轻松地添加新图像类型,因此我添加了 TIFF 库(rev. 6)以及对 ICONs、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 代码。

每个库的每个头文件中都有更具体的致谢和免责声明。

© . All rights reserved.