2411C++,CXImage简单使用

ops/2024/12/1 8:49:33/

介绍

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

文件格式和链接的C库

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

 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是,包含不同格式间共享的许多信息所有成员函数.

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,SKACXIMAGE_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_JPGjpeg88
PNGCXIMAGE_SUPPORT_PNGpng,zlib104
MNGCXIMAGE_SUPPORT_MNGmng,zlib,jpeg148
TIFFCXIMAGE_SUPPORT_TIFTIFF,zlib,jpeg124
JBIGCXIMAGE_SUPPORT_JBGjbig28
PNM,PPM,PGM,RASCXIMAGE_SUPPORT_PNM,CXIMAGE_SUPPORT_RASjasper176
JPEG-2000格式CXIMAGE_SUPPORT_JP2``CXIMAGE_SUPPORT_JPC``CXIMAGE_SUPPORT_PGX同上176
RAWCXIMAGE_SUPPORT_RAWlibdcr132
选项#define[KB]大小
CxImage核心所有开关关闭20
几何变换CXIMAGE_SUPPORT_TRANSFORMATION16
处理图像CXIMAGE_SUPPORT_DSP24
绘画和窗口相关功能CXIMAGE_SUPPORT_WINDOWS12
透明CXIMAGE_SUPPORT_ALPHA4
选区CXIMAGE_SUPPORT_SELECTION4
多层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);,你可在类的域中声明该函数.
现在是定义:

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_SELECTIONif (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_ALPHAtmp.AlphaSet(x,y,AlphaGet(nx,ny));
#endif
//`CXIMAGE_SUPPORT_ALPHA`}}}
//保存结果并退出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);
}

…加载图像资源

//从`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);

… 从内存解码图片

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);

…复制/粘贴图像

//复制
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();

在图片框中显示文件

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);

http://www.ppmy.cn/ops/138150.html

相关文章

shell编程之sed

一、sed工作原理 sed是一种流编程器&#xff0c;配合正则表达式使用来处理文本。 原理&#xff1a;首先&#xff0c;把当前处理的行存储在临时缓冲区&#xff08;模式空间&#xff09;&#xff0c;接着用sed命令处理缓冲区中的内容&#xff0c;处理完成之后&#xff0c;把缓冲…

scala的名次排名

1.准备一个空的List 2.读取文件—按行读取 3.添加学生到List 对有序的列表&#xff0c;从前开始向后一一比较 (1).如果当前的分数不等于预设分数&#xff0c;则名次1&#xff0c;更新预设分数 (2).如果当前的分数等于预设分数&#xff0c;则名次不变 4.排名 实例操作代码如…

JavaScript 进阶教程:深入理解函数、事件和模块化

在上一节中&#xff0c;我们学习了 JavaScript 的基础语法&#xff0c;并通过一个简单计数器案例感受了它的实际应用。这一节将进一步深入学习 JavaScript 中的重要概念&#xff0c;如函数的高级用法、事件机制以及模块化开发&#xff0c;为更复杂的项目开发打下基础。 一、深入…

android将pcm byte[]通过Librtmp进行rtmp推流

需求 我们这边做的功能是智能戒指&#xff0c;戒指可以录音&#xff0c;然后app通过蓝牙连接&#xff0c;将音频的byte[]进行rtmp推流 技术 因为我们不涉及直播&#xff0c;也不涉及视频&#xff0c;工期也比较短&#xff0c;只是音频推流&#xff0c;所以没用更复杂的ffmpe…

【MySQL-6】MySQL的复合查询

目录 1. 整体学习的思维导图 2. 回顾基本查询 3. 多表查询 4. 自连接 5. 子查询 5.1 单行子查询 5.2 多行子查询 5.3 多列子查询 5.4 在from子句中使用子查询 6. 合并查询 1. 整体学习的思维导图 2. 回顾基本查询 使用scott数据库中的表&#xff0c;完成以下查询&am…

Ansible自动化一键部署单节点集群架构

自动化部署利器&#xff1a;Ansible 一键部署脚本 在现代IT基础设施管理中&#xff0c;Ansible以其简洁、强大的自动化能力脱颖而出。以下是精心打造的Ansible自动化一键部署脚本&#xff0c;旨在简化部署流程&#xff0c;提升效率&#xff0c;确保一致性和可靠性。 通过这个…

模拟器快速上手,助力HarmonyOS应用/服务高效开发

文章目录 1 创建模拟器1&#xff09;打开设备管理界面2&#xff09;设置本地模拟器实例存储路径3&#xff09;创建一个模拟器&#xff08;1&#xff09;选择模拟器设备&#xff08;2&#xff09;创建模拟器&#xff08;3&#xff09;启动模拟器&#xff08;4&#xff09;关闭模…

微服务篇-微服务保护:使用 Sentinel 来实现请求限流、线程隔离、服务熔断和 Fallback 备用方案的使用

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 微服务保护 1.1 请求限流方案 1.2 线程隔离方案 1.3 服务熔断方案 2.0 Sentinel 2.1 Sentinel 安装 2.2 微服务整合 3.0 Sentinel-请求限流 4.0 Sentinel-线程隔离…