2411C++,CXImage简单使用

介绍

CxImage是一个可非常简单快速加载,保存,显示和转换图像C++类.

文件格式和链接的C库

Cximage对象基本上是加了一些成员变量保存有用信息一个位图:

cpp 复制代码
 class CxImage
  {
  ...
  protected:
  void* pDib;
//包含标题,调色板,像素
  BITMAPINFOHEADER head;
//标准头文件
  CXIMAGEINFO info;
//扩展信息
  BYTE* pSelection;
//所选区域
  BYTE* pAlpha;
//`α`通道
  CxImage** ppLayers;
//通用图层
  CxImage** ppFrames;
//动画帧
  }

CxImage::head位图头,CxImage::pDib普通位图(如CxImageBMP::Encode的实现所示).
CxImage::info是,包含不同格式间共享的许多信息所有成员函数.

cpp 复制代码
typedef struct tagCxImageInfo {
    DWORD   dwEffWidth;
//`双字`对齐的扫描行宽度
    BYTE*   pImage;
//图像位
    void*   pGhost;
//如果这是重影,则`pGhost`指向身体
    DWORD   dwType;
//原图像格式
    char    szLastError[256];
//调试
    long    nProgress;
//监听
    long    nEscape;
//转义
    long    nBkgndIndex;
//`GIF,PNG,MNG`
    RGBQUAD nBkgndColor;
//`RGB`透明
    BYTE    nQuality;
//`JPEG`
    long    nFrame;
//`TIF,GIF,MNG`:实际帧
    long    nNumFrames;
//`用于TIF,GIF,MNG`:总帧数
    DWORD   dwFrameDelay;
//`GIF,MNG`
    long    xDPI;
//水平分辨率
    long    yDPI;
//垂直分辨率
    RECT    rSelectionBox;
//约束矩形
    BYTE    nAlphaMax;
//最大暗度(淡化)
    bool    bAlphaPaletteEnabled;
//如果启用了调色板中的`α`值,则为`真`.
    bool    bEnabled;
//启用绘画函数
    long    xOffset;
    long    yOffset;
    DWORD   dwEncodeOption;
//对`GIF,TIF:0=def.1=unc,2=fax3,3=fax4,4=pack,5=jpg`
    RGBQUAD last_c;
//用来`GetNearestIndex`优化
    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,PNGTIFF库都会对最终应用增加约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 同上 176
RAW CXIMAGE_SUPPORT_RAW libdcr 132
选项 #define [KB]大小
CxImage核心 所有开关关闭 20
几何变换 CXIMAGE_SUPPORT_TRANSFORMATION 16
处理图像 CXIMAGE_SUPPORT_DSP 24
绘画和窗口相关功能 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

在项目中使用CxImage

CxImgLib.dsw客户区显示了构建应用(demo.exe)期望库,包括CxImage中可用的几乎所有函数和格式.必须先编译所有库,才能链接最终应用.

在源码中,你必须添加#include"ximage.h"

CxImage中添加自定义功能

使用CxImage编写处理图像的新功能并不难.在此,我描述了非常简单的CxImage::Jitter,但它显示了在CxImage中工作时注意的许多方面.

首先,当然是声明:在ximage.hCXIMAGE_SUPPORT_DSP部分中声明bool Jitter(longradius=2);,你可在类的域中声明该函数.

现在是定义:

cpp 复制代码
bool CxImage::Jitter(long radius)
{
//检查图像是否有效,这应该总是是函数中的第一行
    if (!pDib) return false;
//局部变量
    long nx,ny;
//临时图像来保存算法的部分结果
    CxImage tmp(*this,pSelection!=0,true,true);
 //仅在包含所选区域的最小矩形中限制函数的效果(使用`Selection...()`函数),这加快循环速度.
    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;
    }
//`主循环`:在垂直方向扫描图像
    for(long y=ymin; y <ymax; y++){
//监听循环的进度
        info.nProgress = (long)(100*y/head.biHeight);
//让应用快速退出
        if (info.nEscape) break;
//`主循环`:在水平方向扫描图像
        for(long x=xmin; x<xmax; x++){
//如果启用该函数,则仅处理所选区域内的像素
#if CXIMAGE_SUPPORT_SELECTION
            if (SelectionIsInside(x,y))
#endif
//`CXIMAGE_SUPPORT_SELECTION`
            {
//主要算法
                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;
                }
 //在临时图像中保存结果.如果可以,请仅对`24bpp`图像使用`PixelColor`,对`8,4`和`1bpp`图像使用`PixelIndex`:这样更快
                if (head.biClrUsed==0){
                    tmp.SetPixelColor(x,y,GetPixelColor(nx,ny));
                } else {
                    tmp.SetPixelIndex(x,y,GetPixelIndex(nx,ny));
                }
//如果启用了该功能,则还要处理`α`图层中的像素
#if CXIMAGE_SUPPORT_ALPHA
                tmp.AlphaSet(x,y,AlphaGet(nx,ny));
#endif
//`CXIMAGE_SUPPORT_ALPHA`
            }
        }
    }
//保存结果并退出
    Transfer(tmp);
    return true;
}

示例:如何...

...按另一个格式转换一个格式.

cpp 复制代码
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);
}

...加载图像资源

cpp 复制代码
//从`PNG`资源类型加载资源`IDR_PNG1`
CxImage* newImage = new CxImage();
newImage->LoadResource(FindResource(NULL,MAKEINTRESOURCE(IDR_PNG1), "PNG"),CXIMAGE_FORMAT_PNG);
//或
//从`DLL`加载资源`IDR_JPG1`
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);
}
//或:
//加载位图资源;
HBITMAP bitmap = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1)));
CxImage *newImage = new CxImage();
newImage->CreateFromHBITMAP(bitmap);

... 从内存解码图片

cpp 复制代码
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);

...在内存中编码图像

cpp 复制代码
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

cpp 复制代码
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);

...复制/粘贴图像

cpp 复制代码
//复制
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();
//糊
HANDLE hBitmap=NULL;
CxImage *newima = new CxImage();
if (OpenClipboard()) hBitmap=GetClipboardData(CF_DIB);
if (hBitmap) newima->CreateFromHANDLE(hBitmap);
CloseClipboard();

在图片框中显示文件

cpp 复制代码
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);
相关推荐
我不是代码教父2 小时前
[原创](Modern C++)现代C++的关键性概念: 流格式化
c++·字符串格式化·流格式化·cout格式化
利刃大大2 小时前
【回溯+剪枝】找出所有子集的异或总和再求和 && 全排列Ⅱ
c++·算法·深度优先·剪枝
子燕若水2 小时前
mac 手工安装OpenSSL 3.4.0
c++
*TQK*3 小时前
ZZNUOJ(C/C++)基础练习1041——1050(详解版)
c语言·c++·编程知识点
ElseWhereR3 小时前
C++ 写一个简单的加减法计算器
开发语言·c++·算法
*TQK*4 小时前
ZZNUOJ(C/C++)基础练习1031——1040(详解版)
c语言·c++·编程知识点
※DX3906※4 小时前
cpp实战项目—string类的模拟实现
开发语言·c++
萌の鱼5 小时前
leetcode 2080. 区间内查询数字的频率
数据结构·c++·算法·leetcode
xianwu5436 小时前
反向代理模块jmh
开发语言·网络·数据库·c++·mysql
敖行客 Allthinker8 小时前
从 UTC 日期时间字符串获取 Unix 时间戳:C 和 C++ 中的挑战与解决方案
linux·运维·服务器·c++