How to use ImageAttributes for BitmapImage

HoneyBee 186 Reputation points
2022-03-31T06:18:35.243+00:00

I'm working with WPF.

I need to work with ColorMatrix on my control's Background ImageSource.

The code below works fine.

But there is one problem.

Finally, at the moment of DrawImage to Graphics
It takes a long time.
It takes about 0.3 seconds.

I want to make this process faster.

look at my code
Convert ImageSource to Bitmap and
Create ImageAttributes and connect them to Graphics
Change this to ImageSorce again and use it.

This process is cumbersome and very slow.

Can't we make this simpler and faster?

ConvertBitmapToImageSource(NagativeBitmapFromSource(CurrentPageImage.ImageSource as BitmapImage));




  public ImageSource ConvertBitmapToImageSource(System.Drawing.Bitmap bitmap)
         {
             System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
             sw.Start();
             BitmapImage bitmapImage = new BitmapImage();
             using (MemoryStream memory = new MemoryStream())
             {
                 bitmap.Save(memory, ImageFormat.Png);
                 memory.Position = 0;
                 bitmapImage.BeginInit();
                 bitmapImage.StreamSource = memory;
                 bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                 bitmapImage.EndInit();
                 bitmapImage.Freeze();
             }
             sw.Stop();
             LogViewerAddItem("ConvertBitmapToImageSource : " + sw.Elapsed.ToString());
             return bitmapImage;
         }

         public System.Drawing.Bitmap NagativeBitmapFromSource(BitmapSource bitmapsource)
         {
             System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
             sw.Start();
             //convert image format
             var src = new System.Windows.Media.Imaging.FormatConvertedBitmap();
             src.BeginInit();
             src.Source = bitmapsource;
             src.DestinationFormat = System.Windows.Media.PixelFormats.Bgra32;
             src.EndInit();
             src.Freeze();
             LogViewerAddItem("FormatConvertedBitmap : " + sw.Elapsed.ToString());
             //copy to bitmap
             System.Drawing.Bitmap newBitmap = new System.Drawing.Bitmap(src.PixelWidth, src.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
             var data = newBitmap.LockBits(new System.Drawing.Rectangle(System.Drawing.Point.Empty, newBitmap.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
             src.CopyPixels(System.Windows.Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
             newBitmap.UnlockBits(data);

             LogViewerAddItem("copy to bitmap : " + sw.Elapsed.ToString());

             using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(newBitmap))
             {
                 ColorMatrix colorMatrix = new ColorMatrix(new float[][] {
                     new float[] {-0.30f, -0.30f, -0.30f,  0.00f,  0.00f},
                     new float[] {-0.59f, -0.59f, -0.59f,  0.00f,  0.00f},
                     new float[] {-0.11f, -0.11f, -0.11f,  0.00f,  0.00f},
                     new float[] { 0.00f,  0.00f,  0.00f,  1.00f,  0.00f},
                     new float[] { 1.00f,  1.00f,  1.00f,  0.00f,  1.00f }
                 });

                 using (ImageAttributes attributes = new ImageAttributes())
                 {
                     attributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
                     //attributes.SetGamma(gamma, ColorAdjustType.Bitmap);
                     LogViewerAddItem("SetColorMatrix : " + sw.Elapsed.ToString());

                     //g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

                     g.DrawImage(newBitmap, new System.Drawing.Rectangle(System.Drawing.Point.Empty, newBitmap.Size),
                        0, 0, newBitmap.Width, newBitmap.Height, System.Drawing.GraphicsUnit.Pixel, attributes);

                     attributes.Dispose();
                 }
                 g.Dispose();

                 LogViewerAddItem("Graphic DrawImage : " + sw.Elapsed.ToString());
             }

             sw.Stop();
             LogViewerAddItem(sw.Elapsed.ToString());
             return newBitmap;
         }
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,682 questions
0 comments No comments
{count} votes

Accepted answer
  1. Castorix31 81,836 Reputation points
    2022-03-31T09:30:51.84+00:00

    A test with a WriteableBitmap (with an image1 Image containing the Butterfly) =>

    188625-graynegative.gif

                var imgSource = image1.Source;  
    
                FormatConvertedBitmap newFormatedBitmapSource = new FormatConvertedBitmap();  
                newFormatedBitmapSource.BeginInit();  
                newFormatedBitmapSource.Source = (BitmapSource)imgSource;  
                newFormatedBitmapSource.DestinationFormat = PixelFormats.Bgra32;                  
                newFormatedBitmapSource.EndInit();  
    
                WriteableBitmap wb = new WriteableBitmap(newFormatedBitmapSource);  
                int nWidth = wb.PixelWidth;  
                int nHeight = wb.PixelHeight;  
                int[] pixelData = new int[nWidth * nHeight];  
                int nWidthBytes = nWidth * 4;  
                wb.CopyPixels(pixelData, nWidthBytes, 0);  
                for (int i = 0; i < pixelData.Length; ++i)  
                {  
                    pixelData[i] ^= 0x00FFFFFF;  
                    pixelData[i] = MakePixelGray(pixelData[i]);  
                }  
                wb.WritePixels(new Int32Rect(0, 0, nWidth, nHeight), pixelData, nWidthBytes, 0);  
    
                image1.Source = wb;  
    

    Utility function :

        private static int MakePixelGray(int pixel)  
        {  
            byte blue = (byte)pixel;  
            byte green = (byte)(pixel >> 8);  
            byte red = (byte)(pixel >> 16);  
            byte alpha = (byte)(pixel >> 24);  
    
            byte gray = (byte)(((red * 77) + (green * 150) + (blue * 29) + 128) / 256);  
            return (int)(alpha << 24 | gray << 16 | gray << 8 | gray);  
        }  
    
    1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. HoneyBee 186 Reputation points
    2022-03-31T08:29:27.997+00:00

    I think you can get better results by using writeablebitmap .

    But no matter how much you search
    in wpf
    using writeablebitmap
    I don't know how to achieve something like the above result.

    Obviously, it is expected to be faster than Graphics.

    Does anyone have any idea how to do this?

    0 comments No comments