Win32剪贴板和Alpha通道图像

前端之家收集整理的这篇文章主要介绍了Win32剪贴板和Alpha通道图像前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我的应用程序应该能够将32位图像(RGB alpha通道)复制到剪贴板,并从剪贴板中粘贴这些图像.为此,我打算使用CF_DIBV5,因为BITMAPV5HEADER结构具有字段bV5AlphaMask.

问题是对于剪贴板中应该如何存储图像数据似乎没有一致意见.在进行一些测试时,我发现应用程序之间有一些差异,使得它不可能得到一般的解决方案.

这是我的观察:

>当我将alpha通道图像从Word 2010或XnView复制到剪贴板时,它将被存储而不会产生不同的像素数据.
>然而,当我使用Firefox或Chrome复制图像时,像素数据似乎被alpha通道预先使用.
> Firefox将bV5AlphaMask设置为0xff000000,而大多数其他应用程序根本不设置它,但保持为0.这是奇怪的,因为这些应用程序将DIB放在实际包含最高8位的alpha通道的剪贴板上,但仍然将bV5AlphaMask设置为0所以人们必须假设如果位深度为32,即使bV5AlphaMask为0,也有一个alpha通道.

为了缩短长篇小说,我的基本问题是:有关Alpha通道数据应如何存储在剪贴板上的官方信息?我特别感兴趣的是找出数据是否必须预付.如上所述,Word 2010和XnView不会超前,而Firefox和Chrome.但是,知道颜色通道是否应该预乘,这一点至关重要.

非常感谢您的光临!

更新2
粘贴到Paint.NET工作正常.这是由于我的代码中的一个错误,如果Alpha通道为0,则没有将颜色通道设置为0,即在这种情况下,预处理未正确完成,这似乎使Paint.NET变得混乱.

仍然未解决的是Internet Explorer 10的问题.当将Alpha通道的PNG复制到剪贴板时,IE 10只是在剪贴板上放置一个24位CF_DIBV5,但是Paint.NET可以使用Alpha通道粘贴此位图,因此必须有另一种格式IE 10暴露于剪贴板.也许它暴露了一个PNG使用CFSTR_FILECONTENTS和CFSTR_FILEDESCRIPTOR.

UPDATE
我现在已经按照下面的arx描述的方式实现了它,它的工作原理很好.但是,仍然有两件让我困惑的事情:

1)将Alpha应用程序中的Alpha通道图像粘贴到Paint.NET中不会保留Alpha通道.图像在Paint.NET中显示为不透明.然而,从Firefox和Chrome粘贴到Paint.NET中,Alpha通道保留完好!我已经倾销了完整的DIBV5,它与我的应用程序是一样的,但仍然可以与FF和Chrome一起使用,但不适用于我的应用程序,所以还必须有其他的东西! Firefox和Chrome必须做一些我的应用程序不做的事情!

2)Internet Explorer 10也是如此.将IE 10的Alpha通道图像粘贴到我的应用程序上根本不起作用…我正在获得一个深度为24的DIB,即没有alpha通道所有.然而,从IE 10粘贴到Paint.NET时,Alpha通道就在那里!所以在这里还要有更多的东西…

我确定有一个正确的方法来存储CF_DIBV5中的alpha,但它并不重要.应用程序已经处理它不一致,所以如果你希望你的应用程序与他人很好地玩,你不能使用CF_DIBV5.

我曾经研究过复制和粘贴透明位图.我的目标是将透明位图成功粘贴到Office和GIMP的两个版本中.我看了几种可能的格式:

CF_BITMAP

透明度总是被忽略.

CF_DIB

以通常的0xAARRGGBB格式使用32bpp BI_RGB. GIMP支持这一点,但没有其他的.

CF_DIBV5

GIMP不支持这一点.

“PNG”

支持的粘贴:GIMP,Word 2000,Excel 2000,Excel 2007和PowerPoint 2007.
粘贴不受支持:Word 2007和OneNote 2007.

如果您复制位图,所有这些应用程序成功导出“PNG”.

但是,Word和OneNote 2007将粘贴从Explorer复制的PNG文件.所以我想出了以下几点:

复制解决方

将您的透明位图转换为PNG格式.

广告以下剪贴板格式:

“PNG” – 原始的PNG数据.
CF_DIB – 用于不处理透明度的应用程序(如paint).
CFSTR_FILEDESCRIPTOR – 使PNG看起来像一个文件.文件描述符应该有一个发明的文件名,带有“.png”扩展名.
CFSTR_FILECONTENTS – 内容必须作为IStream公开;只是使用HGLOBAL似乎不起作用.数据与“PNG”数据相同.

完成此操作后,我可以将透明位图成功粘贴到GIMP,Office 2000和Office 2007中.也可以将PNG直接粘贴到资源管理器文件夹中.

更新

我意识到我只回答了一半的问题.这是非常好的复制,但如果您想从仅复制CF_DIBV5(如Firefox)的应用程序粘贴,则无法使用.

我建议您使用“PNG”,如果可用,否则回到CF_DIBV5,将其视为预购.这将正确处理Word 2010(导出“PNG”),Firefox和Chrome. XnView只导出不相乘的CF_DIBV5,所以这将无法正常工作.我不确定你能做得更好.

lscf – 用于探索剪贴板格式的工具

这是显示可用剪贴板格式列表的工具的来源.它也可以写一个文件.我叫它lscf.在Visual Studio中创建一个win32控制台应用程序,并通过主函数粘贴此源代码.它有一个非常小的错误:如果您输入格式名称时,它不会显示“未知格式”错误.

#include <Windows.h>

#include <stdio.h>
#include <tchar.h>

#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))

LPCTSTR cfNames[] = {
    _T("CF_TEXT"),_T("CF_BITMAP"),_T("CF_MetaFILEPICT"),_T("CF_SYLK"),_T("CF_DIF"),_T("CF_TIFF"),_T("CF_OEMTEXT"),_T("CF_DIB"),_T("CF_PALETTE"),_T("CF_PENDATA"),_T("CF_RIFF"),_T("CF_WAVE"),_T("CF_UNICODETEXT"),_T("CF_ENHMetaFILE"),_T("CF_HDROP"),_T("CF_LOCALE"),_T("CF_DIBV5")
};

int LookupFormat(LPCTSTR name)
{
    for (int i = 0; i != ARRAY_SIZE(cfNames); ++i)
    {
        if (_tcscmp(cfNames[i],name) == 0)
            return i + 1;
    }

    return RegisterClipboardFormat(name);
}

void PrintFormatName(int format)
{
    if (!format)
        return;

    if ((format > 0) && (format <= ARRAY_SIZE(cfNames)))
    {
        _tprintf(_T("%s\n"),cfNames[format - 1]);
    }
    else
    {
        TCHAR buffer[100];

        if (GetClipboardFormatName(format,buffer,ARRAY_SIZE(buffer)))
            _tprintf(_T("%s\n"),buffer);
        else
            _tprintf(_T("#%i\n"),format);
    }
}

void WriteFormats()
{
    int count = 0;
    int format = 0;
    do
    {
        format = EnumClipboardFormats(format);
        if (format)
        {
            ++count;
            PrintFormatName(format);
        }
    }
    while (format != 0);

    if (!count)
        _tprintf(_T("Clipboard is empty!\n"));
}

void SaveFormat(int format,LPCTSTR filename)
{
    HGLOBAL hData = (HGLOBAL)GetClipboardData(format);

    LPVOID data = GlobalLock(hData);

    HANDLE hFile = CreateFile(filename,GENERIC_WRITE,CREATE_ALWAYS,0);
    if (hFile != INVALID_HANDLE_VALUE)
    {
        DWORD bytesWritten;
        WriteFile(hFile,data,GlobalSize(hData),&bytesWritten,0);
        CloseHandle(hFile);
    }

    GlobalUnlock(hData);
}

int _tmain(int argc,_TCHAR* argv[])
{
    if (!OpenClipboard(0))
    {
        _tprintf(_T("Cannot open clipboard\n"));
        return 1;
    }

    if (argc == 1)
    {
        WriteFormats();
    }
    else if (argc == 3)
    {
        int format = LookupFormat(argv[1]);
        if (format == 0)
        {
            _tprintf(_T("Unknown format\n"));
            return 1;
        }

        SaveFormat(format,argv[2]);
    }
    else
    {
        _tprintf(_T("lscf\n"));
        _tprintf(_T("List available clipboard formats\n\n"));
        _tprintf(_T("lscf CF_NAME filename\n"));
        _tprintf(_T("Write format CF_NAME to file filename\n\n"));
    }

    CloseClipboard();

    return 0;
}

猜你在找的Windows相关文章