question

HoneyBee-2519 avatar image
0 Votes"
HoneyBee-2519 asked HoneyBee-2519 answered

How to use ColorMatrix to highlight a specific color in WPF

I have an image file with text and pictures.

This is a typical document image form.

Converted colors using ColorMatrix.

The ColorMatrix structure is shown below.

   // create the negative color matrix
             colorMatrix = new ColorMatrix(new float[][]
             {
                 new float[] {-1, 0, 0, 0, 0},
                 new float[] {0, -1, 0, 0, 0},
                 new float[] {0, 0, -1, 0, 0},
                 new float[] {0, 0, 0, 1, 0},
                 new float[] {1, 1, 1, 0, 1}
             });
    
             imageAttributes.SetColorMatrix(colorMatrix);

Register and use ColorMatrix with ImageAttributes.

After conversion, the characters are not clear.

After the black is converted to white, the thickness comes out thin.

Is there any way to make only white color thicker?

I want to make the text much clearer and bolder when I change the color.

dotnet-csharpwindows-wpf
· 5
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi,@ HoneyBee-2519. Could you provide your complete code? And please show me your image file to be converted.

0 Votes 0 ·

@HuiLiu-MSFT
Thank you for your interest.
Below is the main code related to the control that utilizes that code.

         public System.Drawing.Bitmap Transform(System.Drawing.Bitmap source)
         {
             System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(source);
    
             ColorMatrix colorMatrix = new ColorMatrix(new float[][]
             {
                 new float[] {-1, 0, 0, 0, 0},
                 new float[] {0, -1, 0, 0, 0},
                 new float[] {0, 0, -1, 0, 0},
                 new float[] {0, 0, 0, 1, 0},
                 new float[] {1, 1, 1, 0, 1}
             });
    
             imageAttributes.SetColorMatrix(colorMatrix);
    
             g.DrawImage(source, new System.Drawing.Rectangle(0, 0, source.Width, source.Height),
                         0, 0, source.Width, source.Height, System.Drawing.GraphicsUnit.Pixel, imageAttributes);
    
             g.Dispose();
    
             return source;
         }
0 Votes 0 ·
 ![124103-000008.jpg][1]
     private Uri _textBookUri;
             public Uri TextBookUri
             {
                 get => _textBookUri;
                 set
                 {
                     Dispatcher.Invoke(new Action(() =>
                     {
                         if (SetProperty(ref _textBookUri, value))
                         {
                             CurrentTextBook = new System.Drawing.Bitmap(_textBookUri.AbsolutePath);
        
                             inkCanvasImage.ImageSource = _isNagative ? ConvertBitmapToImageSource(Transform(CurrentTextBook)) : ConvertBitmapToImageSource(CurrentTextBook);
                         }
                     }));
                 }
             }


[1]: /answers/storage/attachments/124103-000008.jpg

0 Votes 0 ·
000008.jpg (1.5 MiB)

Hi,@ HoneyBee-2519. I don't quite understand the code inkCanvasImage.ImageSource = _isNagative? ConvertBitmapToImageSource(Transform(CurrentTextBook)): ConvertBitmapToImageSource(CurrentTextBook);. What is the definition of CurrentTextBook? Could you show me the code of Transform(CurrentTextBook)? What is the definition of inkCanvasImage? Could you show me the code of the class that contains the _textBookUri property?

0 Votes 0 ·
Show more comments
HuiLiu-MSFT avatar image
0 Votes"
HuiLiu-MSFT answered HuiLiu-MSFT commented

For making the colors bolder and the font clearer, you could try the following code.
The code of xaml:

 float contrast = 1f;
   float gamma = 8.5f;
    private Bitmap MakeGrayscaleWithColorMatrix(Bitmap original)
         { 
             Bitmap newBitmap = new Bitmap(original.Width, original.Height); 
             Graphics g = Graphics.FromImage(newBitmap); 
             ColorMatrix colorMatrix = new ColorMatrix( 
             new float[][]
             {
                  new float[] { contrast, 0, 0, 0, 0},
                  new float[] {0, contrast, 0, 0, 0},
                  new float[] { 0, 0f, contrast, 0, 0},
                  new float[] {0, 0, 0, 1, 0},
                  new float[] {0, 0, 0, 0, 1}
             }) ;
       
             ImageAttributes attributes = new ImageAttributes();
              
             attributes.SetColorMatrix(colorMatrix,ColorMatrixFlag.Default,ColorAdjustType.Bitmap);
             attributes.SetGamma(gamma,ColorAdjustType.Bitmap);
               
             g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
                0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes); 
             g.Dispose();
             return newBitmap;
         }

The picture of result:
126527-color.png

You can also refer to the links(https://stackoverflow.com/questions/55849048/resize-bitmap-image-and-make-bolder-lines and https://stackoverflow.com/questions/34116706/how-to-repair-dimmed-image-of-book-page/34121073#34121073 ) for more.


If the response is helpful, please click "Accept Answer" and upvote it. 
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread. 


color.png (230.6 KiB)
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@HuiLiu-MSFT

Thank you very much.
It gives great results.

But here the result is different from what I want.

Below I am attaching a comparison image of the results I want.

Left is the original
The right side is the converted image.

I want to sharpen only the text in the converted image.

What value should I adjust in ColorMatrix ?

127436-image.png


0 Votes 0 ·
image.png (986.4 KiB)

Hi,@ HoneyBee-2519. Could you try the above settings on the converted image? It uses a ColorMatrix to enhance an image via contrast and gamma. If you want to sharpen the picture, you may use Convolution filter.

0 Votes 0 ·
HoneyBee-2519 avatar image
0 Votes"
HoneyBee-2519 answered

@HuiLiu-MSFT
Hi.
Long time no see.

Thanks to you, I solved the above problem well.

But since then I have a few questions
I ran the test.

I have to get the ImageSource (or BitmapImage) of the control to do this.

So convert BitmapImage to Bitmap and
I applied SetColormatrix here.

So far there aren't many speed issues.
It's just cumbersome.

The problem occurred when I DrawImage on the Graphics object.

A lot of time is wasted here.

Is there any way to make this 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;
         }
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

HoneyBee-2519 avatar image
0 Votes"
HoneyBee-2519 answered

@HuiLiu-MSFT

@HuiLiu-MSFT

It's been a while since I've written an answer.
Your ideas have been of great help to me.

But still I haven't solved the speed problem.

And I got a way to improve the speed even faster.

It is to use WriteableBitmap .

Below is my code.

It works very fast.

But I can't work to make it much sharper via Gamma settings like in your answer.

Any ideas on how to quickly set the Gamma value in my source code?

 public static WriteableBitmap ConvertNagativePage(BitmapImage source)
         {
             FormatConvertedBitmap newFormatedBitmapSource = new FormatConvertedBitmap();
             newFormatedBitmapSource.BeginInit();
             newFormatedBitmapSource.Source = source;
             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);
    
             return wb;
         }
    
         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);
         }
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.