/// <summary> /// Writes an image on the user-interface thread BLOCKING until the UI thread completed the work! /// </summary> /// <param name="image">The image to write</param> /// <param name="cancel">Thread signal to cancel the write</param> public void Write(Image8 image, AutoResetEvent cancel) { if (IsDisposed) { throw new ObjectDisposedException("EZImageSource"); } //if image sizes don't match re-initialize raw image, scaled image and UI image if (imageRaw.Width != image.Width || imageRaw.Height != image.Height) { if (imageRaw != null) { imageRaw.Dispose(); } imageRaw = new Image8(image.Width, image.Height); if (imageScaled != null) { imageScaled.Dispose(); } imageScaled = new Image8(image.Width, image.Height); _imageRect = new Int32Rect(0, 0, imageRaw.Width, imageRaw.Height); var done = new AutoResetEvent(false); DispatcherHelper.CheckBeginInvokeOnUI(() => { //this lock is only necessary because below after a cancel we don't wait on done - therefore upon asking the parent //thread to stop, the call to Write will return, the thread will stop and disposal continues potentially disposing //resources that are being used during the write (imageRaw, imageScaled, etc.). Hence an alternative would be to //wait on done after cancel has been signaled. lock (_disposeLock) { if (!IsDisposed) { ImageSource = new WriteableBitmap(imageRaw.Width, imageRaw.Height, 96, 96, PixelFormats.Gray8, null); } } done.Set(); }); //wait for our done event, indicating that the bitmap has been created (index 1) or //alternatively for cancel which tells us to finish if (WaitHandle.WaitAny(new[] { cancel, done }) == 0) { throw new OperationCanceledException(); } } //copy the new image into image-raw ip.ippiCopy_8u_C1R(image.Image, image.Stride, imageRaw.Image, imageRaw.Stride, image.Size); //scale image if necessary and write to screen if (cMax < 255) { UpdateImageScaled(cancel); } else { UpdateImage(cancel); } }
/// <summary> /// Create new image source /// </summary> public EZImageSource() { imageRaw = new Image8(100, 100); imageScaled = new Image8(imageRaw.Width, imageRaw.Height); _imageRect = new Int32Rect(0, 0, imageRaw.Width, imageRaw.Height); ///create the actual windows image source on the UI thread DispatcherHelper.UIDispatcher.Invoke(new Action(() => { ImageSource = new WriteableBitmap(imageRaw.Width, imageRaw.Height, 96, 96, PixelFormats.Gray8, null); })); //initialize CMax cMax = 255; }
public unsafe void WriteFrame(Image8 image) { int width = image.Width; int height = image.Height; int stride = image.Stride; if (firstFrame) { firstBmp = new Bitmap(width, height, stride, PixelFormat.Format8bppIndexed, (IntPtr)image.Image); var palette = firstBmp.Palette; int length = palette.Entries.Length; for (int i = 0; i < length; i++) { palette.Entries[i] = Color.FromArgb((int)(255 * (double)i / length), (int)(255 * (double)i / length), (int)(255 * (double)i / length)); } firstBmp.Palette = palette; var EncoderParams = new EncoderParameters(2); EncoderParams.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionNone); EncoderParams.Param[1] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.MultiFrame); firstBmp.Save(CurrentFileNameWithExtension, tiffCodecInfo, EncoderParams); firstFrame = false; } else { if (new FileInfo(CurrentFileNameWithExtension).Length > 512000000) // If we're above 1.9 GB, start a new file to avoid 2GB limitation in some tiff readers { fileIndex++; firstFrame = true; WriteFrame(image); return; } var bmp = new Bitmap(width, height, stride, PixelFormat.Format8bppIndexed, (IntPtr)image.Image); var palette = bmp.Palette; int length = palette.Entries.Length; for (int i = 0; i < length; i++) { palette.Entries[i] = Color.FromArgb((int)(255 * (double)i / length), (int)(255 * (double)i / length), (int)(255 * (double)i / length)); } bmp.Palette = palette; var EncoderParams = new EncoderParameters(2); EncoderParams.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionNone); EncoderParams.Param[1] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.FrameDimensionPage); firstBmp.SaveAdd(bmp, EncoderParams); bmp.Dispose(); } }
void Dispose(bool disposing) { if (!IsDisposed) { if (disposing) { lock (_disposeLock) { if (imageRaw != null) { imageRaw.Dispose(); imageRaw = null; } if (imageScaled != null) { imageScaled.Dispose(); imageScaled = null; } } } IsDisposed = true; } }