【问题标题】:How to paste a transparent image from the clipboard in a C# winforms app?如何将剪贴板中的透明图像粘贴到 C# winforms 应用程序中?
【发布时间】:2012-07-01 16:28:40
【问题描述】:

注意:这个问题是关于从剪贴板粘贴,而不是复制到剪贴板。有几篇关于复制到剪贴板的帖子,但找不到解决这个问题的帖子。

如何将具有透明度的图像for example this one 粘贴到 Winforms 应用程序并保持透明度?

我尝试过使用System.Windows.Forms.GetImage(),但这会产生一个黑色背景的位图。

我从谷歌浏览器复制这张图片,它支持多种剪贴板格式,包括DeviceIndependentBitmapFormat17

【问题讨论】:

    标签: winforms image clipboard transparent paste


    【解决方案1】:

    Chrome 以 24bpp 格式将图像复制到剪贴板。这会将透明度变成黑色。您可以从剪贴板中获取 32bpp 格式,但这需要处理 DIB 格式。 System.Drawing 中没有对此的内置支持,您需要一个小辅助函数来进行转换:

        private Image GetImageFromClipboard() {
            if (Clipboard.GetDataObject() == null) return null;
            if (Clipboard.GetDataObject().GetDataPresent(DataFormats.Dib)) {
                var dib = ((System.IO.MemoryStream)Clipboard.GetData(DataFormats.Dib)).ToArray();
                var width = BitConverter.ToInt32(dib, 4);
                var height = BitConverter.ToInt32(dib, 8);
                var bpp = BitConverter.ToInt16(dib, 14);
                if (bpp == 32) {
                    var gch = GCHandle.Alloc(dib, GCHandleType.Pinned);
                    Bitmap bmp = null;
                    try {
                        var ptr = new IntPtr((long)gch.AddrOfPinnedObject() + 40);
                        bmp = new Bitmap(width, height, width * 4, System.Drawing.Imaging.PixelFormat.Format32bppArgb, ptr);
                        return new Bitmap(bmp);
                    }
                    finally {
                        gch.Free();
                        if (bmp != null) bmp.Dispose();
                    }
                }
            }
            return Clipboard.ContainsImage() ? Clipboard.GetImage() : null;
        }
    

    示例用法:

        protected override void OnPaint(PaintEventArgs e) {
            using (var bmp = GetImageFromClipboard()) {
                if (bmp != null) e.Graphics.DrawImage(bmp, 0, 0);
            }
        }
    

    生成此屏幕截图,并将表单的 BackgroundImage 属性设置为库存位图:

    【讨论】:

    • 太棒了。非常感谢。
    • 刚刚注意到 - 图像旋转了 180 度!上面的图像也是从原始图像旋转而来的。知道为什么吗?
    • 我可以使用 image.RotateFlip(SD.RotateFlipType.Rotate180FlipX) 来解决这个问题。不过不知道为什么上面的代码会导致旋转和翻转。
    • 啊,对,位图中的扫描线是倒置存储的。您的解决方法没问题。
    • 具有 40 字节标头的 DIB 的 32 位格式在技术上是没有 alpha 的 RGB。似乎这被滥用为 ARGB 很多,但问题是无法确定每个像素数据的第 4 个字节是 alpha 还是只是垃圾字节。
    【解决方案2】:

    (我无法评论答案)

    Hans Passant 的回答很好,但不正确。

    Screenshot saved with this code.

    你需要替换var ptr = new IntPtr((long)gch.AddrOfPinnedObject() + 40); var ptr = new IntPtr((long)gch.AddrOfPinnedObject() + 52);

    Screenshot saved with correct code.

    你还需要垂直翻转图像

    【讨论】:

    • 看起来 40 的偏移量可能取决于 dib 格式的变化。我建议改写这个。而不是“Hans Passant 的答案很好但不正确”,我会说:“使用 40 的偏移量(来自@Hans Passant 的答案)导致我的图像出现奇怪的边框,52 的偏移量修复了它。”
    猜你喜欢
    • 2013-12-06
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-08
    相关资源
    最近更新 更多