如何从 C++ 中的 bmp 中删除绿屏?
How to remove green screen from bmp in c++?
所以我是 Direct2D 和图像处理领域的新手,现在有点不知所措。我有这张绿色背景的图片,我需要加载它。但是在将其显示到屏幕之前必须删除绿色背景(使用 C++ 色度键)。
到目前为止,我已经成功地将 jpg/bmp 文件中的 d2d 位图加载到屏幕上。抱歉,如果这是一个愚蠢的问题,但我在其他地方找不到太多信息。这是我正在尝试处理的图像。
所以我用来加载位图的步骤是,创建 WIC 工厂,创建能够将文件读入 WIC 的解码器,为 WIC 创建转换器并配置它。
最后一步是创建位图。
然后我用 RendetTarget->DrawBitmap()
方法传递适当的参数在屏幕上绘制它。
我现在唯一想不通的是如何去除下图中的绿屏。如果我的问题缺少一些必要的信息,请告诉我。任何帮助将不胜感激。
这是在屏幕上绘制位图的代码
gfx->GetRenderTarget()->DrawBitmap(
bmp, //Bitmap we built from WIC
D2D1::RectF(0, 0,
bmp->GetSize().width, bmp->GetSize().height),
0.8f, // opacity
D2D1_BITMAP_INTERPOLATION_MODE::D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
D2D1::RectF(0, 0, bmp->GetSize().width, bmp->GetSize().height) //Source Rect
);
这是我的可执行文件 (window) 的屏幕截图以及目前为止的内容。
Main Window
这是加载位图的代码
this->gfx = gfx;
bmp = NULL;
HRESULT hr;
IWICImagingFactory *wicFactory = NULL;
hr = CoCreateInstance(
CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(LPVOID*)&wicFactory); // pointer to the WICFactory
// decoder
IWICBitmapDecoder *wicDecoder = NULL;
hr = wicFactory->CreateDecoderFromFilename(
filename, // filename passed as parameter
NULL,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
&wicDecoder); // pointer to the Decoder
IWICBitmapFrameDecode* wicFrame = NULL;
hr = wicDecoder->GetFrame(0, &wicFrame);
// create wic converter
IWICFormatConverter *wicConverter = NULL;
hr = wicFactory->CreateFormatConverter(&wicConverter);
hr = wicConverter->Initialize(
wicFrame,
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
NULL,
0.0,
WICBitmapPaletteTypeCustom
);
// create bitmap
gfx->GetRenderTarget()->CreateBitmapFromWicBitmap(
wicConverter,
NULL,
&bmp // destination bmp defined in header
);
此代码将在其上绘制一个背景和具有透明度的精灵。您所要做的就是加载一个透明的 png 文件。使用图像编辑器将位图转换为 png。这需要 Visual Studio Atl COM 类 CComPtr
,但没有它你也可以做到。
#include <Windows.h>
#include <atlbase.h>
#include <d2d1.h>
#include <Wincodec.h>
HRESULT load_image(ID2D1HwndRenderTarget *target,
const wchar_t *filename, ID2D1Bitmap** bitmap)
{
HRESULT hr = S_FALSE;
CComPtr<IWICImagingFactory> factory;
CComPtr<IWICBitmapDecoder> decoder;
CComPtr<IWICBitmapFrameDecode> frame;
CComPtr<IWICFormatConverter> converter;
hr = CoCreateInstance(CLSID_WICImagingFactory,
NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (void**)&factory);
if (FAILED(hr)) return hr;
hr = factory->CreateDecoderFromFilename(filename, NULL,
GENERIC_READ, WICDecodeMetadataCacheOnLoad, &decoder);
if(FAILED(hr)) return hr;
hr = decoder->GetFrame(0, &frame);
if(FAILED(hr)) return hr;
hr = factory->CreateFormatConverter(&converter);
if(FAILED(hr)) return hr;
hr = converter->Initialize(frame, GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut);
if(FAILED(hr)) return hr;
hr = target->CreateBitmapFromWicBitmap(converter, 0, bitmap);
return hr;
}
void on_render(ID2D1HwndRenderTarget *render)
{
render->BeginDraw();
render->Clear(D2D1::ColorF(D2D1::ColorF::White));
CComPtr<ID2D1Bitmap> background;
if SUCCEEDED(load_image(render, L"c:\background.jpg", &background))
{
D2D1_SIZE_F size = background->GetSize();
render->DrawBitmap(background, D2D1::RectF(0, 0, size.width, size.height));
}
CComPtr<ID2D1Bitmap> sprite;
if SUCCEEDED(load_image(render, L"c:\transparent.png", &sprite))
{
D2D1_SIZE_F size = sprite->GetSize();
render->DrawBitmap(sprite, D2D1::RectF(0, 0, size.width, size.height));
}
render->EndDraw();
}
TransparentBlt
是一个 GDI 函数,只能处理单一透明度。如果您打算使用 GDI 函数,那么也许您不需要 Direct2D 的复杂性!或者你可以使用 GDI+
if(msg == WM_PAINT)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
auto hbitmap = LoadImage(NULL, L"test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
auto memdc = CreateCompatibleDC(hdc);
auto oldbmp = SelectObject(memdc, hbitmap);
BITMAP bm;
GetObject(hbitmap, sizeof(bm), &bm);
int w = bm.bmWidth;
int h = bm.bmHeight;
TransparentBlt(hdc, 0, 0, w, h, memdc, 0, 0, w, h, RGB(0, 255, 0));
SelectObject(memdc, oldbmp);
DeleteDC(memdc);
DeleteObject(hbitmap);//<- edit
EndPaint(hwnd, &ps);
return 0;
}
所以我是 Direct2D 和图像处理领域的新手,现在有点不知所措。我有这张绿色背景的图片,我需要加载它。但是在将其显示到屏幕之前必须删除绿色背景(使用 C++ 色度键)。
到目前为止,我已经成功地将 jpg/bmp 文件中的 d2d 位图加载到屏幕上。抱歉,如果这是一个愚蠢的问题,但我在其他地方找不到太多信息。这是我正在尝试处理的图像。
所以我用来加载位图的步骤是,创建 WIC 工厂,创建能够将文件读入 WIC 的解码器,为 WIC 创建转换器并配置它。
最后一步是创建位图。
然后我用 RendetTarget->DrawBitmap()
方法传递适当的参数在屏幕上绘制它。
我现在唯一想不通的是如何去除下图中的绿屏。如果我的问题缺少一些必要的信息,请告诉我。任何帮助将不胜感激。
这是在屏幕上绘制位图的代码
gfx->GetRenderTarget()->DrawBitmap(
bmp, //Bitmap we built from WIC
D2D1::RectF(0, 0,
bmp->GetSize().width, bmp->GetSize().height),
0.8f, // opacity
D2D1_BITMAP_INTERPOLATION_MODE::D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
D2D1::RectF(0, 0, bmp->GetSize().width, bmp->GetSize().height) //Source Rect
);
这是我的可执行文件 (window) 的屏幕截图以及目前为止的内容。 Main Window
这是加载位图的代码
this->gfx = gfx;
bmp = NULL;
HRESULT hr;
IWICImagingFactory *wicFactory = NULL;
hr = CoCreateInstance(
CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(LPVOID*)&wicFactory); // pointer to the WICFactory
// decoder
IWICBitmapDecoder *wicDecoder = NULL;
hr = wicFactory->CreateDecoderFromFilename(
filename, // filename passed as parameter
NULL,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
&wicDecoder); // pointer to the Decoder
IWICBitmapFrameDecode* wicFrame = NULL;
hr = wicDecoder->GetFrame(0, &wicFrame);
// create wic converter
IWICFormatConverter *wicConverter = NULL;
hr = wicFactory->CreateFormatConverter(&wicConverter);
hr = wicConverter->Initialize(
wicFrame,
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
NULL,
0.0,
WICBitmapPaletteTypeCustom
);
// create bitmap
gfx->GetRenderTarget()->CreateBitmapFromWicBitmap(
wicConverter,
NULL,
&bmp // destination bmp defined in header
);
此代码将在其上绘制一个背景和具有透明度的精灵。您所要做的就是加载一个透明的 png 文件。使用图像编辑器将位图转换为 png。这需要 Visual Studio Atl COM 类 CComPtr
,但没有它你也可以做到。
#include <Windows.h>
#include <atlbase.h>
#include <d2d1.h>
#include <Wincodec.h>
HRESULT load_image(ID2D1HwndRenderTarget *target,
const wchar_t *filename, ID2D1Bitmap** bitmap)
{
HRESULT hr = S_FALSE;
CComPtr<IWICImagingFactory> factory;
CComPtr<IWICBitmapDecoder> decoder;
CComPtr<IWICBitmapFrameDecode> frame;
CComPtr<IWICFormatConverter> converter;
hr = CoCreateInstance(CLSID_WICImagingFactory,
NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (void**)&factory);
if (FAILED(hr)) return hr;
hr = factory->CreateDecoderFromFilename(filename, NULL,
GENERIC_READ, WICDecodeMetadataCacheOnLoad, &decoder);
if(FAILED(hr)) return hr;
hr = decoder->GetFrame(0, &frame);
if(FAILED(hr)) return hr;
hr = factory->CreateFormatConverter(&converter);
if(FAILED(hr)) return hr;
hr = converter->Initialize(frame, GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeMedianCut);
if(FAILED(hr)) return hr;
hr = target->CreateBitmapFromWicBitmap(converter, 0, bitmap);
return hr;
}
void on_render(ID2D1HwndRenderTarget *render)
{
render->BeginDraw();
render->Clear(D2D1::ColorF(D2D1::ColorF::White));
CComPtr<ID2D1Bitmap> background;
if SUCCEEDED(load_image(render, L"c:\background.jpg", &background))
{
D2D1_SIZE_F size = background->GetSize();
render->DrawBitmap(background, D2D1::RectF(0, 0, size.width, size.height));
}
CComPtr<ID2D1Bitmap> sprite;
if SUCCEEDED(load_image(render, L"c:\transparent.png", &sprite))
{
D2D1_SIZE_F size = sprite->GetSize();
render->DrawBitmap(sprite, D2D1::RectF(0, 0, size.width, size.height));
}
render->EndDraw();
}
TransparentBlt
是一个 GDI 函数,只能处理单一透明度。如果您打算使用 GDI 函数,那么也许您不需要 Direct2D 的复杂性!或者你可以使用 GDI+
if(msg == WM_PAINT)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
auto hbitmap = LoadImage(NULL, L"test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
auto memdc = CreateCompatibleDC(hdc);
auto oldbmp = SelectObject(memdc, hbitmap);
BITMAP bm;
GetObject(hbitmap, sizeof(bm), &bm);
int w = bm.bmWidth;
int h = bm.bmHeight;
TransparentBlt(hdc, 0, 0, w, h, memdc, 0, 0, w, h, RGB(0, 255, 0));
SelectObject(memdc, oldbmp);
DeleteDC(memdc);
DeleteObject(hbitmap);//<- edit
EndPaint(hwnd, &ps);
return 0;
}