Вопрос по image, transparent, winforms, clipboard, paste – Как вставить прозрачное изображение из буфера обмена в приложении C # winforms?

8

Примечание. Этот вопрос касается вставки из буфера обмена, а не копирования в буфер обмена. Существует несколько сообщений о копировании в буфер обмена, но не удалось найти ни одного, который бы отвечал на этот вопрос.

Как я могу вставить изображение с прозрачностью,например этотв приложение winforms и сохранить прозрачность?

Я пытался использоватьSystem.Windows.Forms.GetImage(), но это создает растровое изображение с черным фоном.

Я копирую это изображение из Google Chrome, который поддерживает несколько форматов буфера обмена, в том числеDeviceIndependentBitmap а такжеFormat17.

Ваш Ответ

1   ответ
12

Chrome копирует изображение в буфер обмена в формате 24bpp. Что превращает прозрачность в черный. Вы можете получить 32-битный формат из буфера обмена, но это требует обработки формата 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 формы, установленным в растровое растровое изображение:

enter image description here

32-битный формат DIB с 40-байтовым заголовком технически является RGB без альфа. Кажется, это часто используется как ARGB, но проблема в том, что нет никакого способа убедиться, является ли 4-й байт данных каждого пикселя альфа или просто ненужными байтами.
Просто заметил - изображения повернуты на 180 градусов! Изображение выше также повернуто от оригинала. Есть идеи почему? bright
Brilliant. Большое спасибо. bright
Ах, да, строки сканирования в растровом изображении хранятся вверх ногами. Ваш обходной путь в порядке.
Я смог обойти это с image.RotateFlip (SD.RotateFlipType.Rotate180FlipX). Не знаю, почему приведенный выше код вызывает поворот и переворачивание. bright

Похожие вопросы