【问题标题】:Remove transparency in images with C#使用 C# 删除图像中的透明度
【发布时间】:2010-10-11 17:18:49
【问题描述】:

有谁知道一种平滑/快速去除透明度的方法,例如pngs/tiffs 等并将其替换为白色背景?

基本上我需要这个是我需要创建 PDF/A 兼容的图像,根据规范,这些图像可能没有透明度(因此固定的白色背景很好)。

有什么想法/建议吗?

干杯,谢谢, -约尔格

【问题讨论】:

    标签: c# .net image transparency


    【解决方案1】:

    您可以创建一个与 png 大小相同的位图,绘制一个白色矩形,然后在其上绘制图像。

    void RemTransp(string file) {
        Bitmap src = new Bitmap(file);
        Bitmap target = new Bitmap(src.Size.Width,src.Size.Height);
        Graphics g = Graphics.FromImage(target);
        g.DrawRectangle(new Pen(new SolidBrush(Color.White)), 0, 0, target.Width, target.Height);
        g.DrawImage(src, 0, 0);
        target.Save("Your target path");
    }
    

    【讨论】:

    • 绘制矩形的时候,你可以调用 g.Clear(Color.White);
    • 太棒了 - 感谢您的快速回复!出于某种原因,我也必须指定 g.DrawImage 的宽度和高度......否则放置的图片由于某种原因小于它们的原始 .width/.height)
    • Guffa 的评论是必经之路。
    • 图像中的透明度是 Alpha 通道。此解决方案不会删除此通道,因此它仍然是没有透明区域的透明图像。要移除透明度,您必须移除 Alpha 通道。
    【解决方案2】:

    您必须删除 Alpha 通道。否则你仍然会有一个透明的图像 - 只是没有透明区域。

    class Program
    {
        static void Main(string[] args)
        {
            //this also works for different file formats
            ReplaceTransparency(@"C:\Y\transparent.png", System.Drawing.Color.White).Save(@"C:\Y\no_transparency.png");
            ReplaceTransparency(@"C:\Y\transparent.gif", System.Drawing.Color.White).Save(@"C:\Y\no_transparency.gif");
        }
    
        public static System.Drawing.Bitmap ReplaceTransparency(string file, System.Drawing.Color background)
        {
            return ReplaceTransparency(System.Drawing.Image.FromFile(file), background);
        }
    
        public static System.Drawing.Bitmap ReplaceTransparency(System.Drawing.Image image, System.Drawing.Color background)
        {
            return ReplaceTransparency((System.Drawing.Bitmap)image, background);
        }
    
        public static System.Drawing.Bitmap ReplaceTransparency(System.Drawing.Bitmap bitmap, System.Drawing.Color background)
        {
            /* Important: you have to set the PixelFormat to remove the alpha channel.
             * Otherwise you'll still have a transparent image - just without transparent areas */
            var result = new System.Drawing.Bitmap(bitmap.Size.Width, bitmap.Size.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            var g = System.Drawing.Graphics.FromImage(result);
    
            g.Clear(background);
            g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
            g.DrawImage(bitmap, 0, 0);
    
            return result;
        }
    }
    

    【讨论】:

      【解决方案3】:

      添加到 Stormenet 的答案;记得用 "using" 语句包装所有 Bitmap 和 Graphics 对象以释放非托管资源。

      【讨论】:

        【解决方案4】:

        1) 创建一个具有白色背景且与图像大小相同的位图
        2) 加载图像并将其绘制在“白色”位图上
        3) 保存新创建的图片

        【讨论】:

          【解决方案5】:

          PNG 具有 Alpha 通道,因此无法简单地重新着色。创建相同大小的白色图像,并在其上创建合成图像覆盖您的图像。

          【讨论】:

            【解决方案6】:

            命名空间:

            using Microsoft.Win32;
            using System.Windows.Media;
            using System.Windows.Media.Imaging;
            using PdfSharp;
            using PdfSharp.Pdf;
            using PdfSharp.Drawing;
            

            从文件创建 PNG 或 TIFF BitmapSource:

            BitmapSource BitmapSource;
            private void OpenFile(Object sender, RoutedEventArgs e)
                {
                    OpenFileDialog OpenFileDialog = new OpenFileDialog();
                    OpenFileDialog.Filter = "PNG files (*.png)|*.png|TIFF files (*.tif)|*.tif";            
            
                    if (OpenFileDialog.ShowDialog() == true)
                    {
                        try
                        {
                            if (OpenFileDialog.OpenFile() != null)
                            {
                                String InitialPath = OpenFileDialog.FileName;                       
                                FileStream InitialFileStream = new FileStream(InitialPath, FileMode.Open, FileAccess.Read, FileShare.Read);
            
                                switch (OpenFileDialog.FilterIndex)
                                {
                                    case 1:
                                        PngBitmapDecoder PngBitmapDecoder = new PngBitmapDecoder(InitialFileStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
                                        BitmapSource = PngBitmapDecoder.Frames[0];
                                        InitialFileStream.Close();
                                        break;
                                    case 2:
                                        TiffBitmapDecoder TiffBitmapDecoder = new TiffBitmapDecoder(InitialFileStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
                                        BitmapSource = TiffBitmapDecoder.Frames[0];
                                        InitialFileStream.Close();
                                        break;
                                }  
                            }
                        }
                        catch (Exception Exception)
                        {
                            MessageBox.Show("Error: Could not read file from disk. Original error: ", Exception.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            

            按钮点击功能:

            private void ButtonClick(Object sender, RoutedEventArgs e)
                {
                    PixelFormat PixelFormat = BitmapSource.Format;
                    if (PixelFormat == PixelFormats.Bgra32)
                    {
                        try
                        {
                            BitmapSource = Bgra32ToBgra24(BitmapSource);
                            //BitmapSource = Bgra32ToGray8(BitmapSource);
                        }
            
                        catch (Exception Exception)
                        {
                            MessageBox.Show("Error: Could not convert BitmapSource. Original error: ", Exception.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            

            功能:

            public static BitmapSource Bgra32ToBgr24(BitmapSource BitmapSource)
                {
                    Int32 PixelWidth = BitmapSource.PixelWidth;
                    Int32 PixelHeight = BitmapSource.PixelHeight;
                    Double DpiX = BitmapSource.DpiX;
                    Double DpiY = BitmapSource.DpiY;
            
                    PixelFormat InputPixelFormat = BitmapSource.Format;
                    BitmapPalette InputPalette = BitmapSource.Palette;
                    Int32 InputBitsPerPixel = BitmapSource.Format.BitsPerPixel;
                    Int32 InputStride = PixelWidth * InputBitsPerPixel / 8;
                    Byte[] InputPixelsArray = new Byte[InputStride * PixelHeight];
                    BitmapSource.CopyPixels(InputPixelsArray, InputStride, 0);
            
                    PixelFormat PixelFormat = PixelFormats.Bgr24;
                    BitmapPalette Palette = null;
                    Int32 BitsPerPixel = 24;
                    Int32 Stride = PixelWidth * BitsPerPixel / 8;
                    Byte[] PixelsArray = new Byte[InputStride * PixelHeight / 4 * 3]; 
            
                    Int32 i = 0; Int32 j = 0; Int32 k = 0;
                    while (i < InputPixelsArray.Length / 4)
                    {
                        PixelsArray[k] = InputPixelsArray[j];
                        PixelsArray[k + 1] = InputPixelsArray[j + 1];
                        PixelsArray[k + 2] = InputPixelsArray[j + 2];
            
                        i = i + 1;
                        j = j + 4;
                        k = k + 3;
                    }
            
                    BitmapSource = BitmapSource.Create(PixelWidth, PixelHeight, DpiX, DpiY, PixelFormat, Palette, PixelsArray, Stride);
                    return BitmapSource;
                }
            

            将通道转换为 Gray8 BitmapSource

            public static BitmapSource Bgra32ToGray8(BitmapSource BitmapSource)
                {
                    Int32 PixelWidth = BitmapSource.PixelWidth;
                    Int32 PixelHeight = BitmapSource.PixelHeight;
                    Double DpiX = BitmapSource.DpiX;
                    Double DpiY = BitmapSource.DpiY;
            
                    PixelFormat InputPixelFormat = BitmapSource.Format;
                    BitmapPalette InputPalette = BitmapSource.Palette;
                    Int32 InputBitsPerPixel = BitmapSource.Format.BitsPerPixel;
                    Int32 InputStride = PixelWidth * InputBitsPerPixel / 8;
                    Byte[] InputPixelsArray = new Byte[InputStride * PixelHeight];
                    BitmapSource.CopyPixels(InputPixelsArray, InputStride, 0);
            
                    PixelFormat PixelFormat = PixelFormats.Gray8;
                    BitmapPalette Palette = null;
                    Int32 BitsPerPixel = 8;
                    Int32 Stride = PixelWidth * BitsPerPixel / 8;
                    Byte[] A_PixelsArray = new Byte[InputStride * PixelHeight / 4];
            
                    Int32 i = 0; Int32 j = 3;
                    while (i < InputPixelsArray.Length / 4)
                    {
                        A_PixelsArray[i] = InputPixelsArray[j];
            
                        i = i + 1;
                        j = j + 4;
                    }
            
                    BitmapSource = BitmapSource.Create(PixelWidth, PixelHeight, DpiX, DpiY, PixelFormat, Palette, A_PixelsArray, Stride);
                    return BitmapSource;
                }
            

            将 BitmapSource 保存为 PDF:

            private void SaveFileAs(Object sender, RoutedEventArgs e)
                {
                    SaveFileDialog SaveFileDialog = new SaveFileDialog();
                    SaveFileDialog.Filter = "PDF files (*.pdf)|*.pdf";
                    if (SaveFileDialog.ShowDialog() == true)
                    {
                        try
                        {
                            if (SaveFileDialog.FileName != null)
                            {
                                String DestinationPath = SaveFileDialog.FileName;
                                FileStream DestinationFileStream = new FileStream(DestinationPath, FileMode.Create, FileAccess.Write, FileShare.Write);
            
                                switch (SaveFileDialog.FilterIndex)
                                {   
                                    case 1:
                                        PdfDocument PdfDocument = new PdfDocument();
                                        PdfPage PdfPage = new PdfPage();
                                        PdfDocument.Pages.Add(PdfPage);
                                        XImage Image = XImage.FromBitmapSource(BitmapSource);
                                        XGraphics XGraphic = XGraphics.FromPdfPage(PdfDocument.Pages[0]);
            
                                        Double VerticalMargin = 20;
                                        Double HorizontalMargin = 20;
                                        Double Ratio = BitmapSource.Height / BitmapSource.Width;
                                        Double ImageWidth = PdfPage.Width - 2 * VerticalMargin;
                                        Double ImageHeight = Ratio * (PdfPage.Width - 2 * HorizontalMargin);
            
                                        XGraphic.DrawImage(Image, VerticalMargin, HorizontalMargin, ImageWidth, ImageHeight);
                                        PdfDocument.Save(DestinationFileStream);
                                        PdfDocument.Close();
                                        DestinationFileStream.Close();
                                        break;
                                }
                            }
                        }
                        catch (Exception Exception)
                        {
                            MessageBox.Show("Error: Could not write file to disk. Original error: ", Exception.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            

            【讨论】:

            • 你的代码很有启发性。由于我正在处理类似的问题,只是在上下文中有所不同,因为我的输入是 CMYK + A 中的 TIFF,所以我仍然会尝试使用 copypixels 并随后修改字节缓冲区数组。有时间请看我的问题stackoverflow.com/questions/65266182/…
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-02-14
            • 2022-01-20
            • 2011-04-02
            • 2023-04-02
            • 1970-01-01
            相关资源
            最近更新 更多