I'm having a DICOM image data, which holds 16bit gray values. To visualize the data I need to apply a windowing method that cuts out pieces of the 16bits values. Therefore I have two properties, like WindowCenter and WindowWidth.
Since I want to use the WPF mechanisms I decided to create a DicomImage class which derives from BitmapSource. Since BitmapSource has no direct access to the internal pixeldata, I created a private WriteableBitmap (InternalImage) member where I can manipulate the data whenever WindowCenter and WindowWidth is changed.
To see the results I attach to Image.Source = DicomImage and the image is shown. But when I change the WindowCenter/WindowWidth the image is not updated. When I attach the WriteableBitmap directly (Image.Source = InternalImage) everything works as it should.
What I'm I doing wrong?
Thanks
Marti
Related
I want to display an image (.tif, gray value 16 bit) which is editable for the user via sliders. The displayed image should directly react to the changes, so the user knows what he's doing to the image.
Currently I only seem to be creating new files with every change and displaying the latest one, which is a terrible solution.
My idea would be to load the original pixeldata, put it in some sort of temporary file which isn't and won't be saved, then saving the parameters of the sliders and when hitting save applying the parameters to the original image (since in the end the filter is used on an intire set of images).
An Image is not a File. If might be that you display the Image that is in a file, but once you've loaded the file into an Image object don't ever use the file again, until the edited image needs to be saved in a file.
You say you want to display an image. As you are using winforms, I assume you are using a PictureBox control. If not, you have a class that you order to display an Image.
Image imageToDisplay = GetImageToDisplay();
this.PictureBox1.Image = imageToDisplay;
GetImageTodisplay will read the file and return it as an Image
System.Drawing.Image GetImageToDisplay()
{
FileStream imageStream = new FileStream(this.GetImageFileName(), FileMode.Open);
System.Drawing.Image image = new Image(imageStream);
return image;
}
Apparently you also have sliders. You don't mention the class of your sliders, but apparently it is an object that notifies your form about a new slider value.
void OnSliderValueChanged(object sender, int sliderValue)
{
Image displayedImage = this.PictureBox1.Image;
this.ProcessSliderChanged(image, sliderValue);
}
Until now I don't see the creation of a new file. So this should be in ProcessSliderChange. Luckily that is a function you created yourself. All you have to do is change the image according to your new slider value. Don't do anything with file handling and you won't get a new file
void ProcessSliderChange(System.Drawing.Image image, int sliderValue)
{ // what do you want to do with the image?
// make it darker? move it? change contrast?
}
Unfortunately the Image class doesn't have a lot of functions to edit images, I assume you have a library with functions that act on System.Drawing.Image objects. Just use those functions to change your Image.
I have an BitmapImage which is generated by application itself and have no sourceFile or URI. Now i have to convert this image to WritableBitmapImage in order to save it, according to this. But all the methods require sourceFile or URI.
There is no good way to extract the pixels from a BitmapImage after the fact.
As you note, if you have the source image then you can create a WriteableBitmap from that.
Since WritableBitmap and BitmapImage are both ImageSources they can be used the same way in most cases, so if you know you'll need access to the pixels when you create the BitmapImage then you can usually create a WriteableBitmap instead.
Once the BitmapImage is created and the original source is no longer available the closest you can get is to use RenderTargetBitmap to render the displayed Image control into a new bitmap from which you can extract the pixels with GetPixelData.
This will be a second generation image though and for large images will likely have lost data to resizing interpolation between the original and the rendering.
I'd recommend using a WriteableBitmap instead of a BitmapImage to begin with when generating the original image.
I'm currently working on a tile based map editor, focusing to get scrolling working exactly how I want. That's where I experience some troubles. While scrolling, images get generated to display the new content as you scroll around. This works fine till about 200 images (System.Windows.Controls.Image) being generated at a new side (simple maps, not complicated).
Whenever about 1000 images (or a lot more if you scroll faster..) get generated on the side, the application will hang for some time, depending on how rapid you scroll etc.
The cause of this temporarily hangup is always caused by this line. Removing this line eliminates the "lag" fully (but obviously does not give the wanted result):
img.Source = it.GetFullSpriteSource(0);
That method generates an ImageSource, or returns the ImageSource stored in a variable if already generated. The problem lies not in this method, since the following scenario gives the same problem.
public static ImageSource yellowimg;
[...]
System.Drawing.Bitmap derp = new System.Drawing.Bitmap(32, 32);
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(derp))
g.FillRectangle(System.Drawing.Brushes.Yellow, 0, 0, 32, 32);
yellowimg = Utilities.ToImgSource(derp);
[...]
img.Source = yellowimg;
So the problem probably lies in the fact I assign the ImageSource.
I am generating an ImageSource out of a Bitmap like this, might be relevant:
public static ImageSource ToImgSource(Bitmap bitmap)
{
return Imaging.CreateBitmapSourceFromHBitmap(
bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
I have also tried generation in a seperate Thread (background generation), but this results in the following error, trying to read the ImageSource from another thread.
The calling thread cannot access the object because different thread owns it
What are things I could try?
Keep in mind I'm not advanced with WPF (Recently started) and I have barely any knowledge about ImageSource.
Thanks,
~ Tgys
Instead of creating an ImageSource from a System.Drawing.Bitmap you should use WriteableBitmap. If you have to draw complicated drawing into the bitmap, you would have to draw into the DrawingContext of a DrawingVisual and render that DrawingVisual into a RenderTargetBitmap,
When you create ImageSource objects in a separate thread, you have to call their Freeze method before using them in the UI.
I am trying to let a user capture an image and add it onto the screen using an Image. However, I also need to resize this image down to about half size due to memory restrictions (12x 5MP images is never good on a phone...)
I am launching the camera task fine and it calls the Completed event. However, when I try and use DecodeJpeg I get a "The parameter is incorrect." exception.
Here is my code for resizing, where mx and my are int for dimensions. I have verified that there is something in the e.ChosenPhoto with a length of about ~5500:
WriteableBitmap bitmap = PictureDecoder.DecodeJpeg(e.ChosenPhoto, mx, my);
Image img = new Image();
img.Source = bitmap;
The first line is where the app crashes. Any ideas?
EDIT:
This also occurs with the result from the PhotoChooserTask....
Try using the System.Windows.Media.Imaging - Extensions.LoadJpeg method instead of PictureDecoder.DecodeJpeg. Also make sure that the stream is positioned at the beginning of the stream. If you have already used the stream you will need to reset it using:
MyImageStream.Seek(0, System.IO.SeekOrigin.Begin)
I had a lot of problems trying to get access to the original image, especially since BitmapImage automatically resizes images over 2000x2000. If you want an image larger than 2000x2000 you have to have access to the original stream and load it into a WriteableBitmap object
If you want to see some more complex image handling code including detecting resolution from image stream using ExifLib and rotating stream using the WriteableBitmap Extensions check out the BarcodeCaptureResult class for the Silverlight ZXing Library.
UPDATE: Since all you want is to resize an image given the e.ChosenPhoto result I pulled the code from The Silverlight ZXing library. This should work:
WriteableBitmap wbBarcodeImage = new WriteableBitmap(mx, my);
Extensions.LoadJpeg(wbBarcodeImage, e.ChosenPhoto);//Load JPEG from stream into our re-sized writeable bitmap
Note that you will need to use the correct height/width ratio, otherwise you will have a black bar at the bottom or side of the image. You can use ExifLib to detect the original image size and use that to scale (see GetWriteableBitmap method in BarcodeCaptureResult linked above)
the problem is as follows:
I have got a rendered bitmap in a byte array (together with the bitmap header). Now I want to manipulate the content of a bitmap. For that purpose I need to wrap this array with some high-level class, say BitmapImage . I want to avoid copying the array, or its data part etc. I want just to force .NET to interpret my byte array as the BitmapImage .
I want to change the content by rendering some stuff to RenderTargetBitmap , and then interpret its data bits as the bits of my image. For rendering I am to use standard DrawingContext, DrawingVisual pair. Thus, it would be great if I could WORK on the data part of my byte array and render my final image to this subarray. Then I did not need to perform any copying and the performance would be great.
How to speedup the calculation and get breathtaking results? :-)
Thank you in advance for the replies!
Cheers
I would use Writeablebitmap , manipulate it in the code and then show it in the Image. Depending on the context some caching could do a great job.