将位图 (bmp) 转换为具有透明度的 png (Windows c++)
Converting a bitmap (bmp) to png with transparency (Windows c++)
我需要将 bmp 文件转换为 png 文件,同时将 bmp 中的一种颜色视为透明。我的应用程序使用 MFC,但我不受限于在解决方案中使用 MFC。我在从 gdi 移植到 Direct2D 时这样做,所以我确实可以访问 Direct2D(尽管我是 Direct2D 的真正新手)。我想避免使用 gdi+ 和外部源代码(例如 libpng),但我会重新考虑它是否提供了一个易于实施的解决方案。性能不是问题。
如此处所示,MFC 使从 bmp 文件创建 png 文件变得容易,但我不知道如何将 bmp 中的 "transparent color" 转换为 png 中的 alpha 蒙版。 (不太理想,但我可以创建 png 文件,然后读取它,将图像的 "transparent color" 更改为透明度,然后写入它。)
// Convert bmp to png.
CImage image;
if(image.Load(bmpFilename) == S_OK)
{
image.Save(pngFilename, Gdiplus::ImageFormatPNG) == S_OK);
}
我看到 this thread 提出了一个非常相似的问题,但它的答案是高层次的(例如,"use libpng"、"use gdi+"、"use BITMAPINFOHEADER::biCompression == BI_PNG" 等) .我正在寻找细节和(相对)易于实施。
谢谢!
应该这样做:
void CImageCopy(CImage& dest, CImage& src)
{
// rescale user image
dest.Destroy();
dest.Create(src.GetWidth(), src.GetHeight(), 32, CImage::createAlphaChannel);
HDC hdc = dest.GetDC();
src.AlphaBlend(hdc, 0,0,src.GetWidth(), src.GetHeight(), 0,0,src.GetWidth(),src.GetHeight());
dest.ReleaseDC();
}
void Fix24BitTransparency(CImage& img)
{
if(img.GetBPP()<32 )
{
// alpha bits
CImage imgout;
imgout.Create(img.GetWidth(), img.GetHeight(), 32, CImage::createAlphaChannel);
for(int x=0; x<img.GetWidth(); ++x)
for(int y=0; y<img.GetHeight(); ++y)
{
COLORREF c1;
c1 = img.GetPixel(x,y); // user image
imgout.SetPixel(x,y,c1);
if( c1 == RGB(255,0,128) ) // or whatever you decide transparent...
{
imgout.SetPixel(x,y, RGB(255,255,255) );
BYTE* pAlpha = (BYTE*)imgout.GetPixelAddress(x, y)+3;
*pAlpha = 0;
}
else
{
BYTE* pAlpha = (BYTE*)imgout.GetPixelAddress(x, y)+3;
*pAlpha = 255;
}
}
CImageCopy(img, imgout);
}
}
我需要将 bmp 文件转换为 png 文件,同时将 bmp 中的一种颜色视为透明。我的应用程序使用 MFC,但我不受限于在解决方案中使用 MFC。我在从 gdi 移植到 Direct2D 时这样做,所以我确实可以访问 Direct2D(尽管我是 Direct2D 的真正新手)。我想避免使用 gdi+ 和外部源代码(例如 libpng),但我会重新考虑它是否提供了一个易于实施的解决方案。性能不是问题。
如此处所示,MFC 使从 bmp 文件创建 png 文件变得容易,但我不知道如何将 bmp 中的 "transparent color" 转换为 png 中的 alpha 蒙版。 (不太理想,但我可以创建 png 文件,然后读取它,将图像的 "transparent color" 更改为透明度,然后写入它。)
// Convert bmp to png.
CImage image;
if(image.Load(bmpFilename) == S_OK)
{
image.Save(pngFilename, Gdiplus::ImageFormatPNG) == S_OK);
}
我看到 this thread 提出了一个非常相似的问题,但它的答案是高层次的(例如,"use libpng"、"use gdi+"、"use BITMAPINFOHEADER::biCompression == BI_PNG" 等) .我正在寻找细节和(相对)易于实施。
谢谢!
应该这样做:
void CImageCopy(CImage& dest, CImage& src)
{
// rescale user image
dest.Destroy();
dest.Create(src.GetWidth(), src.GetHeight(), 32, CImage::createAlphaChannel);
HDC hdc = dest.GetDC();
src.AlphaBlend(hdc, 0,0,src.GetWidth(), src.GetHeight(), 0,0,src.GetWidth(),src.GetHeight());
dest.ReleaseDC();
}
void Fix24BitTransparency(CImage& img)
{
if(img.GetBPP()<32 )
{
// alpha bits
CImage imgout;
imgout.Create(img.GetWidth(), img.GetHeight(), 32, CImage::createAlphaChannel);
for(int x=0; x<img.GetWidth(); ++x)
for(int y=0; y<img.GetHeight(); ++y)
{
COLORREF c1;
c1 = img.GetPixel(x,y); // user image
imgout.SetPixel(x,y,c1);
if( c1 == RGB(255,0,128) ) // or whatever you decide transparent...
{
imgout.SetPixel(x,y, RGB(255,255,255) );
BYTE* pAlpha = (BYTE*)imgout.GetPixelAddress(x, y)+3;
*pAlpha = 0;
}
else
{
BYTE* pAlpha = (BYTE*)imgout.GetPixelAddress(x, y)+3;
*pAlpha = 255;
}
}
CImageCopy(img, imgout);
}
}