C++ C++;Gdi+;将图像转换为灰度
尝试将32、24、16、8位图像转换为灰度显示。我读过关于使用BitBlt的文章,但可能存在一些轻松的内置机会 在GDI+中 代码:C++ C++;Gdi+;将图像转换为灰度,c++,gdi+,grayscale,C++,Gdi+,Grayscale,尝试将32、24、16、8位图像转换为灰度显示。我读过关于使用BitBlt的文章,但可能存在一些轻松的内置机会 在GDI+中 代码: #包括 ... 类gdiplus_init { ULONG_PTR令牌; 公众: gdiplus_init() { Gdiplus::GDIPlusStartupInputTMP; Gdiplus::Gdiplus启动(&token,&tmp,NULL); } ~gdiplus_init() { Gdiplus::GdiplusShutdown(令牌); } };
#包括
...
类gdiplus_init
{
ULONG_PTR令牌;
公众:
gdiplus_init()
{
Gdiplus::GDIPlusStartupInputTMP;
Gdiplus::Gdiplus启动(&token,&tmp,NULL);
}
~gdiplus_init()
{
Gdiplus::GdiplusShutdown(令牌);
}
};
bool getbits(const wchar_t*文件名,Gdiplus::PixelFormat PixelFormat,
std::vector&bitmapinfo,std::vector&bits,int&w,int&h)
{
gdiplus_init init;
单词bpp=0;
int用法=DIB_RGB_颜色;
int paletesize=0;
开关(像素格式)
{
已编制索引的案例像素:
bpp=8;
用法=DIB_PAL_颜色;
调色板大小=256*sizeof(RGBQUAD);
打破
案例PixelFormat16bppRGB555:bpp=16;中断;
案例PixelFormat16bppRGB565:bpp=16;中断;
案例像素格式24bpprgb:bpp=24;中断;
案例像素格式32bpprgb:bpp=32;中断;
默认:返回false;
}
auto src=Gdiplus::Bitmap::FromFile(文件名);
如果(src->GetLastStatus()!=Gdiplus::Status::Ok)
返回false;
自动dst=src->Clone(0,0,src->GetWidth(),src->GetHeight(),0,0),
像素格式);
w=src->GetWidth();
h=src->GetHeight();
HBITMAP HBITMAP;
Gdiplus::颜色;
dst->GetHBITMAP(颜色和hbitmap);
//为bitmapinfo分配足够的内存并初始化为零
//它是BITMAPINFO结构的大小+调色板的大小
调整大小(sizeof(bitmapinfo)+调色板大小,0);
//填写前6个参数
BITMAPINFO*ptr=(BITMAPINFO*)BITMAPINFO.data();
ptr->bmiHeader.biSize=sizeof(BitMapInfo头);//不要跳过
ptr->bmiHeader.biWidth=w;
ptr->bmiHeader.biHeight=h;
ptr->bmiHeader.biPlanes=1;
ptr->bmiHeader.biBitCount=bpp;
ptr->bmiHeader.biCompression=BI_RGB;
//计算尺寸的神奇公式:
//这大约是每像素w*h*bytes,是这样写的
//解释“位图填充”的步骤
双字尺寸=((w*bpp+31)/32)*4*h;
//为图像分配内存
调整大小(大小,0);
//最后调用GetDIBits来填充bits和bitmapinfo
HDC HDC=GetDC(0);
GetDIBits(hdc、hbitmap、0、h和位[0],(BITMAPINFO*)和BITMAPINFO[0],用法);
释放DC(0,hdc);
//清理
删除src;
删除dst;
返回true;
}
无效CMFCApplicationColorsView::OnDraw(CDC*pDC)
{
...
std::vector bi;//自动存储
std::向量位;
int w,h;
//24位测试
if(获取比特(L“c:\\test\\24bit.bmp”,像素格式24bpprgb,bi,比特,w,h))
拉伸阻力(dc,0,0,w,h,0,0,w,h,
bits.data(),(BITMAPINFO*)bi.data(),DIB_RGB_颜色,SRCCOPY);
//8位测试
if(获取位(L“c:\\test\\8bit.bmp”,像素格式8bppinged,bi,位,w,h))
拉伸阻力(dc,0,220,w,h,0,0,w,h,
bits.data(),(BITMAPINFO*)bi.data(),DIB_PAL_COLORS,SRCCOPY);
}
您可以通过各种转换直接绘制GDI+。使用Gdiplus::Graphics
绘制设备上下文
对于灰度转换,所有RGB值必须相同Gdiplus::ColorMatrix
可以变换颜色。绿色通常更重要,它会增加重量
void draw(CDC *pdc)
{
//this line should be in OnCreate or somewhere other than paint routine
Gdiplus::Bitmap source(L"file.jpg");
//gray scale conversion:
Gdiplus::ColorMatrix matrix =
{
.3f, .3f, .3f, 0, 0,
.6f, .6f, .6f, 0, 0,
.1f, .1f, .1f, 0, 0,
0, 0, 0, 1, 0,
0, 0, 0, 0, 1
};
Gdiplus::ImageAttributes attr;
attr.SetColorMatrix(&matrix,
Gdiplus::ColorMatrixFlagsDefault, Gdiplus::ColorAdjustTypeBitmap);
Gdiplus::Graphics gr(pdc->GetSafeHdc());
Gdiplus::REAL w = (Gdiplus::REAL)source.GetWidth();
Gdiplus::REAL h = (Gdiplus::REAL)source.GetHeight();
Gdiplus::RectF rect(0, 0, w, h);
gr.DrawImage(&source, rect, 0, 0, w, h, Gdiplus::UnitPixel, &attr);
}
注意,我对灰度矩阵使用了粗略值。有关更好的矩阵,请参阅
要转换文件,过程类似,除了使用Gdiplus::Graphics
创建内存dc并保存它
int GetEncoderClsid(const WCHAR* format, CLSID* clsid)
{
int result = -1;
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
Gdiplus::GetImageEncodersSize(&num, &size);
if(size)
{
Gdiplus::ImageCodecInfo* codec = (Gdiplus::ImageCodecInfo*)(malloc(size));
GetImageEncoders(num, size, codec);
for(UINT j = 0; j < num; ++j)
if(wcscmp(codec[j].MimeType, format) == 0)
{
*clsid = codec[j].Clsid;
result = j;
}
free(codec);
}
return result;
}
bool convert_grayscale(const wchar_t *file_in, const wchar_t *file_out)
{
CStringW extension = PathFindExtensionW(file_out);
extension.Remove(L'.');
extension.MakeLower();
if(extension == L"jpg") extension = L"jpeg";
extension = L"image/" + extension;
CLSID clsid;
if(GetEncoderClsid(extension, &clsid) == -1)
return false;
Gdiplus::Bitmap source(file_in);
if(source.GetLastStatus() != Gdiplus::Status::Ok)
return false;
Gdiplus::REAL w = (Gdiplus::REAL)source.GetWidth();
Gdiplus::REAL h = (Gdiplus::REAL)source.GetHeight();
Gdiplus::RectF rect(0, 0, w, h);
Gdiplus::Bitmap copy((INT)w, (INT)h, source.GetPixelFormat());
Gdiplus::ColorMatrix matrix =
{
.3f, .3f, .3f, 0, 0,
.6f, .6f, .6f, 0, 0,
.1f, .1f, .1f, 0, 0,
0, 0, 0, 1, 0,
0, 0, 0, 0, 1
};
Gdiplus::ImageAttributes attr;
attr.SetColorMatrix(&matrix,
Gdiplus::ColorMatrixFlagsDefault, Gdiplus::ColorAdjustTypeBitmap);
Gdiplus::Graphics gr(©);
gr.DrawImage(&source, rect, 0, 0, w, h, Gdiplus::UnitPixel, &attr);
auto st = copy.Save(file_out, &clsid);
return st == Gdiplus::Status::Ok;
}
...
convert_grayscale(L"source.jpg", L"destination.jpg");
int GetEncoderClsid(常量WCHAR*格式,CLSID*CLSID)
{
int结果=-1;
UINT num=0;//图像编码器的数量
UINT size=0;//图像编码器数组的大小(字节)
Gdiplus::GetImageEncodersSize(&num,&size);
如果(尺寸)
{
Gdiplus::ImageCodecInfo*编解码器=(Gdiplus::ImageCodecInfo*)(malloc(size));
GetImageEncoder(num、size、codec);
对于(UINT j=0;j
Edit:添加了extension.MakeLower()代码>以防文件扩展名为大写。
int GetEncoderClsid(const WCHAR* format, CLSID* clsid)
{
int result = -1;
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
Gdiplus::GetImageEncodersSize(&num, &size);
if(size)
{
Gdiplus::ImageCodecInfo* codec = (Gdiplus::ImageCodecInfo*)(malloc(size));
GetImageEncoders(num, size, codec);
for(UINT j = 0; j < num; ++j)
if(wcscmp(codec[j].MimeType, format) == 0)
{
*clsid = codec[j].Clsid;
result = j;
}
free(codec);
}
return result;
}
bool convert_grayscale(const wchar_t *file_in, const wchar_t *file_out)
{
CStringW extension = PathFindExtensionW(file_out);
extension.Remove(L'.');
extension.MakeLower();
if(extension == L"jpg") extension = L"jpeg";
extension = L"image/" + extension;
CLSID clsid;
if(GetEncoderClsid(extension, &clsid) == -1)
return false;
Gdiplus::Bitmap source(file_in);
if(source.GetLastStatus() != Gdiplus::Status::Ok)
return false;
Gdiplus::REAL w = (Gdiplus::REAL)source.GetWidth();
Gdiplus::REAL h = (Gdiplus::REAL)source.GetHeight();
Gdiplus::RectF rect(0, 0, w, h);
Gdiplus::Bitmap copy((INT)w, (INT)h, source.GetPixelFormat());
Gdiplus::ColorMatrix matrix =
{
.3f, .3f, .3f, 0, 0,
.6f, .6f, .6f, 0, 0,
.1f, .1f, .1f, 0, 0,
0, 0, 0, 1, 0,
0, 0, 0, 0, 1
};
Gdiplus::ImageAttributes attr;
attr.SetColorMatrix(&matrix,
Gdiplus::ColorMatrixFlagsDefault, Gdiplus::ColorAdjustTypeBitmap);
Gdiplus::Graphics gr(©);
gr.DrawImage(&source, rect, 0, 0, w, h, Gdiplus::UnitPixel, &attr);
auto st = copy.Save(file_out, &clsid);
return st == Gdiplus::Status::Ok;
}
...
convert_grayscale(L"source.jpg", L"destination.jpg");