Search code examples
image-processingdicomfo-dicom

Invert grayscale using fo-dicom


I'm currently using fo-dicon to build a simple dicom viewer in C#. I am currently increasing or decreasing the brightness and contrast by adjusting window width & center values.

How do I invert the grayscale using the InvertLut class?

    public WriteableBitmap DisplayedImage {get;set;}


    //...
    private void ExecuteLoadImageCommand()
    {
        _dicomFile = DicomFile.Open(GetImageFileName());
        _dicomImage = new DicomImage(_dicomFile.Dataset);
        WindowLevel = _dicomImage.WindowCenter;
        WindowWidth = _dicomImage.WindowWidth;
        var grayScaleOptions = GrayscaleRenderOptions.FromBitRange(_dicomFile.Dataset);
        Depth = grayScaleOptions.BitDepth.BitsAllocated;

        DisplayedImage = _dicomImage.RenderImage().As<WriteableBitmap>();
    }

   
       
    

Solution

  • With the solution provided in below fo-dicom issue, i was able to invert the image. I did not use InvertLUT class.

    https://github.com/fo-dicom/fo-dicom/issues/784

    I had to convert from WritableBitmap to Bitmap, then again to WritableBitmap.

    Solution:

    public static class BitmapHelper
    {
        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
        public static extern void CopyMemory(IntPtr dest, IntPtr source, int Length);
    
        public static void ConvertToWritableBitmap(Bitmap bitmap, ref WriteableBitmap writeableBitmap)
        {
            BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    
            try
            {
                writeableBitmap.Lock();
                CopyMemory(writeableBitmap.BackBuffer, data.Scan0,
                    (writeableBitmap.BackBufferStride * bitmap.Height));
                writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, bitmap.Width, bitmap.Height));
                writeableBitmap.Unlock();
            }
            finally
            {
                bitmap.UnlockBits(data);
                bitmap.Dispose();
            }
        }
    
        /// <summary>
        ///
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        public static Bitmap InvertBitmapPixels(WriteableBitmap writeableBitmap)
        {
            var image = BitmapFromWriteableBitmap(writeableBitmap);
            // create the negative color matrix
            ColorMatrix color_matrix = 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}
                }
            );
    
            // create some image attributes
            ImageAttributes attributes = new ImageAttributes();
            attributes.SetColorMatrix(color_matrix);
    
            var bmp = new Bitmap(image);
            {
                using (var g = Graphics.FromImage(bmp))
                {
                    g.DrawImage(
                        image,
                        new Rectangle(0, 0, image.Width, image.Height),
                        0, 0, bmp.Width, bmp.Height,
                        GraphicsUnit.Pixel,
                        attributes
                    );
                }
    
                return bmp;
            }
        }
    
        public static Bitmap BitmapFromWriteableBitmap(WriteableBitmap writeBmp)
        {
            System.Drawing.Bitmap bmp;
            using (MemoryStream outStream = new MemoryStream())
            {
                BitmapEncoder enc = new BmpBitmapEncoder();
                enc.Frames.Add(BitmapFrame.Create((BitmapSource)writeBmp));
                enc.Save(outStream);
                bmp = new System.Drawing.Bitmap(outStream);
            }
            return bmp;
        }
    }
    

    To invert:

    var image = BitmapHelper.InvertBitmapPixels(_writableBitmapImage);
            BitmapHelper.ConvertToWritableBitmap(image, ref _writableBitmapImage);