Navigation:  I Want To... > Imaging >

Manipulate pixel data

Previous pageReturn to chapter overviewNext page

Use Case

You want to alter existing pixel data in some way for say, image processing.

Relevant Architecture

Image graphics

Relevant Types

ImageGraphic
GrayscaleImageGraphic
ColorImageGraphic
PixelData
GrayscalePixelData
ColorPixelData

Sample Code

using ClearCanvas.Common;

using ClearCanvas.Desktop.Actions;

using ClearCanvas.Desktop;

using ClearCanvas.ImageViewer;

using ClearCanvas.ImageViewer.BaseTools;

using ClearCanvas.ImageViewer.Graphics;

 

// ... (other using namespace statements here)

 

namespace MyPlugin.Imaging

{

   [ButtonAction("apply""global-toolbars/ToolbarStandard/ManipulatePixelDataTool""Apply")]

   [ButtonAction("apply""global-toolbars/ToolbarStandard/ResetManipulatePixelDataTool""Unapply")]

   [IconSet("apply", IconScheme.Colour, "Icons.MyToolSmall.png""Icons.MyToolMedium.png""Icons.MyToolLarge.png")]

   // ... (other action attributes here)

   [ExtensionOf(typeof (ImageViewerToolExtensionPoint))]

   public class ManipulatePixelDataTool : ImageViewerTool

   {

      public void Apply()

      {

         // Check for nulls before we using anything

         if (this.SelectedImageGraphicProvider == null)

            return;

 

         ImageGraphic image = this.SelectedImageGraphicProvider.ImageGraphic;

 

         if (image == null)

            return;

 

         // Make sure the image is grayscale

         if (!(image is GrayscaleImageGraphic))

            return;

 

         // Change the grayscale value of the pixel at (4,7) (8th row, 5th column)

         image.PixelData.SetPixel(47100);

 

         // Redraw the onscreen image

         image.Draw();

 

         // We've modified the original pixel data!

         // To reload it, we will need to call the other method.

      }

 

      public void Unapply()

      {

         // Check for nulls before we using anything

         if (this.SelectedImageSopProvider == null)

            return;

 

         this.SelectedImageSopProvider.Frame.UnloadPixelData();

 

         // Redraw the onscreen image

         this.SelectedPresentationImage.Draw();

      }

   }

}

Remarks

There are two ways to manipulate pixel data:

1.Easy, but not-as-fast.  If ease of implementation is key and performance is not terribly important to you, then use ImageGraphic.PixelData's GetPixel and SetPixel methods.  This might be the best approach if you're just prototyping an algorithm, when performance is not that important.
2.Fast, but not-as-easy.  If performance is key and you're willing to work with pointers, then get the raw byte array from ImageGraphic.PixelData.Raw and use unsafe code to do your processing.  Dealing with the raw byte array can be a bit tedious since you have to be aware of the image's size, bit depth and pixel format in your code (in the "easy, but not-as-fast" method, all of that is hidden from you).  However, if you've perfected your algorithm and are now ready to put it into production, this is definitely what you want to do.

It's important to remember that by default, ImageGraphic does not own its own pixel data.  Rather, it has a reference to the actual pixel data contained in a Frame (which belongs to an ImageSop).  Because it's possible for more than one ImageGraphic to reference the same pixel data, the pixel data is shared.  This is usually desirable for memory conservation, but may not be desirable when you're performing image processing operations on the data, since any changes to the data will be reflected by all ImageGraphics that reference it.  If you don't want that, you will need to create a copy of the raw data.  At some point, we will add a facility to the Framework that will handle this case automatically without the need for manual copying of pixel data.

If you need to undo the manipulations to the pixel data, you can force the pixel data to unload and, on the next attempt to draw the image, the pixel data will be reloaded from the original Frame.  Since the pixel data is tied to the Frame, the unload method is on the Frame and not on the graphic itself.  Please note that individual frames in a multi-frame image are treated and loaded separately.

Examples in Code Base

ClearCanvas.ImageViewer.Tools.ImageProcessing.Filter.SharpeningFilterTool