【问题标题】:Rotating a CImage and preserving its alpha/transparency channel旋转 CImage 并保留其 alpha/透明度通道
【发布时间】:2015-07-29 11:04:00
【问题描述】:

我有一些现有代码使用具有 alpha 通道的 CImage,我需要旋转它。

我发现以下建议将 CImage 转换为 GDI+ 位图然后旋转它,旋转后的结果最终回到 CImage。

Bitmap* gdiPlusBitmap=Bitmap::FromHBITMAP(atlBitmap.Detach());
gdiPlusBitmap->RotateFlip(Rotate90FlipNone);
HBITMAP hbmp;
gdiPlusBitmap->GetHBITMAP(Color::White, &hbmp);
atlBitmap.Attach(hbmp);

显然它不需要实际复制位图字节就可以工作,这很好,但问题是如果你从 HBITMAP 创建一个 Bitmap 对象,它会丢弃 alpha 通道。

显然要保留 alpha 通道,您必须改为使用构造函数创建位图

Bitmap(
  [in]  INT width,
  [in]  INT height,
  [in]  INT stride,
  [in]  PixelFormat format,
  [in]  BYTE *scan0
);

所以我正在尝试调整上面的内容以使用这个构造函数,但是 CImage 和 Bitmap 之间的交互有点令人困惑。我想我需要像这样创建位图

Bitmap* gdiPlusBitmap = new Bitmap(
            pCImage->GetWidth(),
            pCImage->GetHeight(),
            pCImage->GetPitch(),
            PixelFormat32bppARGB,
            (BYTE *)pCImage->GetBits());
nGDIStatus = gdiPlusBitmap->RotateFlip(Rotate90FlipNone);

但我不确定如何让 CImage 获取更改(这样我最终会旋转原始 CImage),或者在哪里删除 Bitmap 对象。

有谁知道这样做的正确方法,保留 alpha 通道?

理想情况下,我希望避免复制位图数据,但这不是强制性的。

【问题讨论】:

    标签: c++ image bitmap mfc gdi+


    【解决方案1】:

    您可以使用Gdiplus::GraphicsCImage 上绘制位图。

    注意,如果图像不支持 Alpha 通道,硬编码 PixelFormat32bppARGB 可能会导致问题。我添加了一些基本的错误检查。

    CImage image;
    if (S_OK != image.Load(L"c:\\test\\test.png"))
    {
        AfxMessageBox(L"can't open");
        return 0;
    }
    
    int bpp = image.GetBPP();
    
    //get pixel format:
    HBITMAP hbmp = image.Detach();
    Gdiplus::Bitmap* bmpTemp = Gdiplus::Bitmap::FromHBITMAP(hbmp, 0);
    Gdiplus::PixelFormat pixel_format = bmpTemp->GetPixelFormat();
    if (bpp == 32)
        pixel_format = PixelFormat32bppARGB;
    image.Attach(hbmp);
    
    //rotate:   
    Gdiplus::Bitmap bmp(image.GetWidth(), image.GetHeight(), image.GetPitch(), pixel_format, static_cast<BYTE*>(image.GetBits()));
    bmp.RotateFlip(Gdiplus::Rotate90FlipNone);
    
    //convert back to image:
    image.Destroy();
    if (image.Create(bmp.GetWidth(), bmp.GetHeight(), 32, CImage::createAlphaChannel))
    {
        Gdiplus::Bitmap dst(image.GetWidth(), image.GetHeight(), image.GetPitch(), PixelFormat32bppARGB, static_cast<BYTE*>(image.GetBits()));
        Gdiplus::Graphics graphics(&dst);
        graphics.DrawImage(&bmp, 0, 0);
    }
    

    【讨论】:

    • 效果很好。谢谢。我尝试了其他几种方法,但它丢失了 alpha,或者部分透明的像素变得不透明,导致锯齿状边缘。看起来 Graphics 对象是唯一的方法。
    猜你喜欢
    • 2014-12-29
    • 1970-01-01
    • 2011-06-05
    • 2012-01-02
    • 1970-01-01
    • 2019-03-18
    • 2010-12-30
    • 2012-02-20
    • 2013-11-13
    相关资源
    最近更新 更多