Files
EzUI/sources/Bitmap.cpp

181 lines
4.5 KiB
C++
Raw Permalink Normal View History

2026-01-24 22:42:46 +08:00
#include "Bitmap.h"
#include <gdiplus.h>
namespace ezui {
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL;
Gdiplus::GetImageEncodersSize(&num, &size);
if (size == 0) {
return -1; // Failure
}
pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));
if (pImageCodecInfo == NULL) {
return -1; // Failure
}
Gdiplus::GetImageEncoders(num, size, pImageCodecInfo);
for (UINT j = 0; j < num; ++j)
{
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; // Success
}
}
free(pImageCodecInfo);
return -1; // Failure
}
Bitmap::Bitmap(int width, int height) {
Create(width, height);
}
Bitmap::Bitmap(HDC dc, const Rect& rect) {
Create(rect.Width, rect.Height);
::BitBlt(this->GetDC(), 0, 0, rect.Width, rect.Height, dc, rect.X, rect.Y, SRCCOPY);
}
void Bitmap::Create(int width, int height) {
m_width = width;
m_height = height;
memset(&m_bmpInfo, 0, sizeof(m_bmpInfo));
BITMAPINFOHEADER& bmih = m_bmpInfo.bmiHeader;
bmih.biSize = sizeof(bmih);
bmih.biBitCount = 32;
bmih.biCompression = BI_RGB;
bmih.biPlanes = 1;
bmih.biWidth = width;
bmih.biHeight = -height;
bmih.biSizeImage = width * height * 4;
m_bmp = ::CreateDIBSection(NULL, &m_bmpInfo, DIB_RGB_COLORS, (void**)&m_point, NULL, 0);
::memset(m_point, 0, bmih.biSizeImage);
this->GetDC();
}
int Bitmap::Width()const {
return m_width;
}
int Bitmap::Height() const {
return m_height;
}
void Bitmap::SetPixel(int x, int y, const Color& color) {
DWORD* point = (DWORD*)this->m_point + (x + y * this->Width());//起始地址+坐标偏移
((BYTE*)point)[3] = color.GetA();//修改A通道数值
((BYTE*)point)[2] = color.GetR();//修改R通道数值
((BYTE*)point)[1] = color.GetG();//修改G通道数值
((BYTE*)point)[0] = color.GetB();//修改B通道数值
}
Color Bitmap::GetPixel(int x, int y) const {
DWORD* point = (DWORD*)this->m_point + (x + y * this->Width());//起始地址+坐标偏移
BYTE a, r, g, b;
a = ((BYTE*)point)[3];
r = ((BYTE*)point)[2];//修改R通道数值
g = ((BYTE*)point)[1];//修改G通道数值
b = ((BYTE*)point)[0];//修改B通道数值
return Color(r, g, b, a);
}
byte* Bitmap::GetPixel()
{
return (byte*)this->m_point;
}
void Bitmap::Earse(const Rect& _rect) {
Rect rect = _rect;
if (rect.X < 0) {
rect.X = 0;
rect.Width += rect.X;
}
if (rect.Y < 0) {
rect.Y = 0;
rect.Height += rect.Y;
}
if (rect.GetBottom() > Height()) {
rect.Height = this->Height() - rect.Y;
}
if (rect.GetRight() > Width()) {
rect.Width = this->Width() - rect.X;
}
for (int y = rect.Y; y < rect.GetBottom(); ++y)
{
DWORD* point = (DWORD*)this->m_point + (rect.X + y * this->Width());//起始地址+坐标偏移
::memset(point, 0, rect.Width * 4);//抹除
}
}
HBITMAP Bitmap::GetHBITMAP()
{
return this->m_bmp;
}
HDC Bitmap::GetDC() {
if (!m_hdc) {
m_hdc = ::CreateCompatibleDC(NULL);
::SelectObject(m_hdc, m_bmp);
}
return m_hdc;
}
bool Bitmap::Save(const UIString& fileName)
{
size_t pos = fileName.rfind(".");
UIString ext;
if (pos != size_t(-1)) {
ext = fileName.substr(pos);
ext = ext.toLower();
}
bool ret = false;
Gdiplus::Bitmap* pbmSrc = NULL;
do
{
CLSID pngClsid;
int code = -1;
if (ext == ".png") {
code = GetEncoderClsid(L"image/png", &pngClsid);
}
else if (ext == ".jpg" || ext == ".jpeg") {
code = GetEncoderClsid(L"image/jpeg", &pngClsid);
}
else if (ext == ".tiff") {
code = GetEncoderClsid(L"image/tiff", &pngClsid);
}
else {
code = GetEncoderClsid(L"image/bmp", &pngClsid);
}
if (code == -1) {
break;
}
pbmSrc = new Gdiplus::Bitmap(Width(), Height(), Width() * 4, PixelFormat32bppARGB, (BYTE*)GetPixel());
if (pbmSrc && pbmSrc->Save(fileName.unicode().c_str(), &pngClsid) == Gdiplus::Status::Ok)
{
ret = true;
break;
}
} while (false);
if (pbmSrc) {
delete pbmSrc;
}
return ret;
}
Bitmap* Bitmap::Clone() const {
if (m_width <= 0 || m_height <= 0) {
return NULL;
}
// 创建新 Bitmap 对象(保留格式)
Bitmap* clone = new Bitmap(m_width, m_height);
//拷贝像素
memcpy(clone->m_point, m_point, m_width * m_height * 4);
return clone;
}
Bitmap::~Bitmap() {
if (m_hdc) {
::DeleteDC(m_hdc);
::DeleteObject((HGDIOBJ)(HBITMAP)(m_bmp));
}
}
};