首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何将RGBA图像复制到Windows剪贴板

如何将RGBA图像复制到Windows剪贴板
EN

Stack Overflow用户
提问于 2022-05-17 20:05:04
回答 1查看 172关注 0票数 2

如何将32位(每像素) RGBA图像复制到Windows的剪贴板上?经过大量的尝试,我已经开始使用这个功能了,但是我的图像数据“粘贴”一点也没有。它也不会出现在剪贴板的历史记录中。

稍微编辑一下它来使用CF_DIBBITMAPINFOHEADER头已经在历史上产生了一个“拷贝”条目,并在粘贴时产生了一个大小正确的图像,尽管在CF_DIB背面粘贴一个png会导致程序以令人难以置信的有趣和非良性的方式出现故障。

我的目标是将带有alpha通道的图像复制到剪贴板上,并且在切换过程中不要将颜色与alpha相加。我做错什么了..?

代码语言:javascript
运行
复制
bool copyBitmapIntoClipboard(Window & window, const Bitmap & in) {
    //  this section is my code for creating a png file
    StreamWrite stream = StreamWrite::asBufferCreate();
    in.savePng(stream);
    uint64 bufSize = 0;
    char * buf = stream._takeBuffer(bufSize, false);
    // "buf"      <-- contains the PNG payload
    // "bufSize"  <-- is the size of this payload

    // beyond this point, it's just standard windows' stuff that doesn't rely on my code
    BITMAPV5HEADER header;
    header.bV5Size          = sizeof(BITMAPV5HEADER);
    header.bV5Width         = in.getX(); // <-- size of the bitmap in pixels, width and height
    header.bV5Height        = in.getY();
    header.bV5Planes        = 1;
    header.bV5BitCount      = 0;
    header.bV5Compression   = BI_PNG;
    header.bV5SizeImage     = bufSize;
    header.bV5XPelsPerMeter = 0;
    header.bV5YPelsPerMeter = 0;
    header.bV5ClrUsed       = 0;
    header.bV5ClrImportant  = 0;
    header.bV5RedMask       = 0xFF000000;
    header.bV5GreenMask     = 0x00FF0000;
    header.bV5BlueMask      = 0x0000FF00;
    header.bV5AlphaMask     = 0x000000FF;
    header.bV5CSType        = LCS_sRGB;
    header.bV5Endpoints;    // ignored
    header.bV5GammaRed      = 0;
    header.bV5GammaGreen    = 0;
    header.bV5GammaBlue     = 0;
    header.bV5Intent        = 0;
    header.bV5ProfileData   = 0;
    header.bV5ProfileSize   = 0;
    header.bV5Reserved      = 0;

    HGLOBAL gift = GlobalAlloc(GMEM_MOVEABLE, sizeof(BITMAPV5HEADER) + bufSize);
    if (gift == NULL) 
        return false;

    HWND win = window.getWindowHandle();
    if (!OpenClipboard(win)) {
        GlobalFree(gift);
        return false;
    }
    EmptyClipboard();

    void * giftLocked = GlobalLock(gift);
    if (giftLocked) {
        memcpy(giftLocked, &header, sizeof(BITMAPV5HEADER));
        memcpy((char*)giftLocked + sizeof(BITMAPV5HEADER), buf, bufSize);
    }
    GlobalUnlock(gift);

    SetClipboardData(CF_DIBV5, gift);

    CloseClipboard();
    return true;
}
EN

Stack Overflow用户

回答已采纳

发布于 2022-05-18 01:01:07

至少在我的经验中,尝试用BITMAPV5HEADER传输png数据几乎是一个完全的损失,除非您基本上计划将其作为内部格式严格使用。

至少对相当数量的应用程序有效的一种策略是注册PNG剪贴板格式,并将PNG文件的内容放入剪贴板(没有其他标题)。代码如下所示:

代码语言:javascript
运行
复制
bool copyBitmapIntoClipboard(Window & window, const Bitmap & in) {
    //  this section is my code for creating a png file
    StreamWrite stream = StreamWrite::asBufferCreate();
    in.savePng(stream);
    uint64 bufSize = 0;
    char * buf = stream._takeBuffer(bufSize, false);
    // "buf"      <-- contains the PNG payload
    // "bufSize"  <-- is the size of this payload

    HGLOBAL gift = GlobalAlloc(GMEM_MOVEABLE, bufSize);
    if (gift == NULL) 
        return false;

    HWND win = window.getWindowHandle();
    if (!OpenClipboard(win)) {
        GlobalFree(gift);
        return false;
    }
    EmptyClipboard();

    auto fmt = RegisterClipboardFormat("PNG"); // or `L"PNG", as applicable

    void * giftLocked = GlobalLock(gift);
    if (giftLocked) {
        memcpy((char*)giftLocked, buf, bufSize);
    }
    GlobalUnlock(gift);

    SetClipboardData(fmt, gift);

    CloseClipboard();
    return true;
}

我使用过这样的代码,并成功地将内容粘贴到至少LibreOffice with和Calc、MS和Paint.Net的最新版本中。

这也是Chrome (举个例子)的格式,如果您告诉它复制位图,它将产生第一个(首选)格式。

另一方面,FireFox产生了大量的格式,而不是这个格式。它会产生一个CF_DIBV5,但至少如果内存正常的话,它会预先乘以alpha (或者它可能会完全失去α)--我不太清楚。不会像你想要的那样保存它)。

Gimp将接受32位RGB格式的DIB,其中alpha位于左字节,并使用该alpha。不管是好是坏,据我所知,这是唯一能将某些东西粘贴到Gimp中的东西,并保留它的alpha (而不是预成倍的)。

备注

随着版本的更新,

  • 所支持的格式可能会发生很大变化,因此即使(例如) PNG上次尝试使用Gimp,它现在也可能会发生变化。

  • 您可以将相同的数据以不同的格式添加到剪贴板中。您希望从“最佳”格式(最忠实地保存数据的格式)开始,然后以最糟糕的方式工作。因此,当您执行一个副本时,您可能需要执行PNG,然后是带有alpha通道的RGB,然后是CF_BITMAP (这将预乘alpha,但可能仍然比没有好)。
票数 3
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72280052

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档