首頁 > 後端開發 > C++ > 如何在不同的應用程式中可靠地複製和貼上透明圖像?

如何在不同的應用程式中可靠地複製和貼上透明圖像?

Linda Hamilton
發布: 2025-01-12 14:34:43
原創
219 人瀏覽過

How Can I Reliably Copy and Paste Images with Transparency in Different Applications?

在不同應用程式中可靠地複製貼上透明圖像

您可能遇到這樣的問題:在複製貼上影像時,透明度無法在不同程式之間保持一致。儘管Chrome可以保留透明度,但使用系統剪貼簿物件設定影像時,透明度可能會遺失。

剪貼簿限制

Windows剪貼簿本身並非原生支援影像透明度。然而,您可以利用多種資料類型來提高跨應用程式的相容性。

PNG流:最佳相容性選擇

PNG串流是保持剪貼簿影像透明度最可靠的方法。將PNG映像貼到GIMP或較新的MS Office程式中,透明度將被保留。

多種格式,更廣相容性

為了確保與更多應用程式相容,建議在剪貼簿上包含多種支援的影像格式,例如PNG、裝置無關點陣圖(DIB)和標準點陣圖。

範例程式碼

<code class="language-c#">public static void SetClipboardImage(Bitmap image, Bitmap imageNoTr, DataObject data)
{
    Clipboard.Clear();
    if (data == null) data = new DataObject();
    if (imageNoTr == null) imageNoTr = image;

    using (MemoryStream pngMemStream = new MemoryStream())
    using (MemoryStream dibMemStream = new MemoryStream())
    {
        data.SetData(DataFormats.Bitmap, true, imageNoTr); // 设置标准位图(无透明度)
        image.Save(pngMemStream, ImageFormat.Png);
        data.SetData("PNG", false, pngMemStream); // 设置PNG流(GIMP和较新MS Office兼容)
        Byte[] dibData = ConvertToDib(image);
        dibMemStream.Write(dibData, 0, dibData.Length);
        data.SetData(DataFormats.Dib, false, dibMemStream); // 设置DIB格式(处理错误解释透明度的应用)
        Clipboard.SetDataObject(data, true);
    }
}

public static Byte[] ConvertToDib(Image image)
{
    using (Bitmap bm32b = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb))
    {
        using (Graphics gr = Graphics.FromImage(bm32b))
            gr.DrawImage(image, new Rectangle(0, 0, bm32b.Width, bm32b.Height));
        bm32b.RotateFlip(RotateFlipType.Rotate180FlipX);
        Int32 stride;
        Byte[] bm32bData = ImageUtils.GetImageData(bm32b, out stride);
        Int32 hdrSize = 0x28;
        Byte[] fullImage = new Byte[hdrSize + 12 + bm32bData.Length];
        ArrayUtils.WriteIntToByteArray(fullImage, 0x00, 4, true, (UInt32)hdrSize);
        ArrayUtils.WriteIntToByteArray(fullImage, 0x04, 4, true, (UInt32)image.Width);
        ArrayUtils.WriteIntToByteArray(fullImage, 0x08, 4, true, (UInt32)image.Height);
        ArrayUtils.WriteIntToByteArray(fullImage, 0x0C, 2, true, 1);
        ArrayUtils.WriteIntToByteArray(fullImage, 0x0E, 2, true, 32);
        ArrayUtils.WriteIntToByteArray(fullImage, 0x10, 4, true, 3);
        ArrayUtils.WriteIntToByteArray(fullImage, 0x14, 4, true, (UInt32)bm32bData.Length);
        ArrayUtils.WriteIntToByteArray(fullImage, hdrSize + 0, 4, true, 0x00FF0000);
        ArrayUtils.WriteIntToByteArray(fullImage, hdrSize + 4, 4, true, 0x0000FF00);
        ArrayUtils.WriteIntToByteArray(fullImage, hdrSize + 8, 4, true, 0x000000FF);
        Array.Copy(bm32bData, 0, fullImage, hdrSize + 12, bm32bData.Length);
        return fullImage;
    }
}</code>
登入後複製

從剪貼簿擷取影像

要從剪貼簿提取影像,需要檢查各種支援的格式,優先使用PNG以確保最大可靠性:

<code class="language-c#">public static Bitmap GetClipboardImage(DataObject retrievedData)
{
    if (retrievedData.GetDataPresent("PNG", false))
    {
        MemoryStream png_stream = retrievedData.GetData("PNG", false) as MemoryStream;
        if (png_stream != null)
            using (Bitmap bm = new Bitmap(png_stream))
                return ImageUtils.CloneImage(bm);
    }
    else if (retrievedData.GetDataPresent(DataFormats.Dib, false))
    {
        MemoryStream dib = retrievedData.GetData(DataFormats.Dib, false) as MemoryStream;
        if (dib != null)
            return ImageFromClipboardDib(dib.ToArray());
    }
    else if (retrievedData.GetDataPresent(DataFormats.Bitmap))
        return new Bitmap(retrievedData.GetData(DataFormats.Bitmap) as Image);
    else if (retrievedData.GetDataPresent(typeof(Image)))
        return new Bitmap(retrievedData.GetData(typeof(Image)) as Image);
    return null;
}

public static Bitmap ImageFromClipboardDib(Byte[] dibBytes)
{
    if (dibBytes == null || dibBytes.Length < 4 || dibBytes.Length < (Int32)ArrayUtils.ReadIntFromByteArray(dibBytes, 0, 4, true))
        return null;
    Int32 width = (Int32)ArrayUtils.ReadIntFromByteArray(dibBytes, 0x04, 4, true);
    Int32 height = (Int32)ArrayUtils.ReadIntFromByteArray(dibBytes, 0x08, 4, true);
    Int16 planes = (Int16)ArrayUtils.ReadIntFromByteArray(dibBytes, 0x0C, 2, true);
    Int16 bitCount = (Int16)ArrayUtils.ReadIntFromByteArray(dibBytes, 0x0E, 2, true);
    Int32 compression = (Int32)ArrayUtils.ReadIntFromByteArray(dibBytes, 0x10, 4, true);
    if (planes != 1 || (compression != 0 && compression != 3))
        return null;
    PixelFormat fmt;
    switch (bitCount)
    {
        case 32: fmt = PixelFormat.Format32bppRgb; break;
        case 24: fmt = PixelFormat.Format24bppRgb; break;
        case 16: fmt = PixelFormat.Format16bppRgb555; break;
        default: return null;
    }
    Int32 stride = (((((bitCount * width) + 7) / 8) + 3) / 4) * 4;
    Int32 imageIndex = 40 + (compression == 3 ? 12 : 0);
    if (dibBytes.Length < imageIndex) return null;
    Byte[] image = new Byte[dibBytes.Length - imageIndex];
    Array.Copy(dibBytes, imageIndex, image, 0, image.Length);
    Bitmap bitmap = ImageUtils.BuildImage(image, width, height, stride, fmt, null, null);

    // ... (ImageFromClipboardDib function continues,  requires ImageUtils.BuildImage implementation) ...
}</code>
登入後複製

(注意:上述程式碼片段中ImageUtils.GetImageDataImageUtils.CloneImageImageUtils.BuildImage 需要根據實際情況自行實現。) 這些函數負責影像資料的處理和點陣圖的建立。 這部分實現取決於你使用的影像處理庫和具體的平台環境。

以上是如何在不同的應用程式中可靠地複製和貼上透明圖像?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板