private void AddLayers(DrawArgs args) { IAssociatedTissues volume = args.SceneGraph.ParentPresentationImage as IAssociatedTissues; if (volume == null) return; GraphicCollection layers = volume.TissueLayers; vtkPropCollection props = _vtkRenderer.GetViewProps(); foreach (VolumeGraphic volumeGraphic in layers) { if (props.IsItemPresent(volumeGraphic.VtkProp) == 0) _vtkRenderer.AddViewProp(volumeGraphic.VtkProp); //if (volumeLayer.OldVtkProp != null) //{ // if (props.IsItemPresent(volumeLayer.OldVtkProp) != 0) // { // props.RemoveItem(volumeLayer.OldVtkProp); // volumeLayer.OldVtkProp = null; // } //} } }
private void RenderImage(DrawArgs args) { if (args.DrawMode == DrawMode.Refresh) { RefreshImage(args); return; } if (_firstRender) { // the first time we try to render a freshly cloned image, we need to draw it twice // this is to make sure the client rectangle is updated when we try to compute the correct point of interest _firstRender = false; RenderImage(args); } try { var sourceTransform = (ImageSpatialTransform)((ISpatialTransformProvider)SelectedPresentationImage).SpatialTransform; var transform = (ImageSpatialTransform)((ISpatialTransformProvider)_magnificationImage).SpatialTransform; float scale = sourceTransform.Scale * ToolSettings.DefaultInstance.MagnificationFactor; transform.ScaleToFit = false; transform.Scale = scale; transform.TranslationX = 0; transform.TranslationY = 0; var midPoint = new PointF(args.RenderingSurface.ClientRectangle.Width / 2f, args.RenderingSurface.ClientRectangle.Height / 2f); var sourcePointOfInterest = sourceTransform.ConvertToSource(_tileLocation); // compute translation required to move the point of interest on the magnified image to the centre of the client area var translation = transform.ConvertToSource(midPoint) - new SizeF(sourcePointOfInterest); transform.TranslationX = translation.X; transform.TranslationY = translation.Y; _magnificationImage.Draw(args); // clear the rendering exception message _lastRenderExceptionMessage = null; } catch (Exception ex) { Platform.Log(LogLevel.Error, ex, "An error has occured while rendering the magnified contents of the tile."); // a rendering exception was encountered, so set the message field _lastRenderExceptionMessage = ex is RenderingException ? ((RenderingException)ex).UserMessage : ex.Message; // we cannot simply pass the existing Graphics because we haven't released its hDC yet // if we do, we'll get a "Object is currently in use elsewhere" exception DrawErrorMessage(_lastRenderExceptionMessage, args.RenderingSurface.ContextID, args.RenderingSurface.ClientRectangle); } }
private void AddLayers(DrawArgs args) { IAssociatedTissues volume = args.SceneGraph.ParentPresentationImage as IAssociatedTissues; if (volume == null) return; GraphicCollection layers = volume.TissueLayers; vtkPropCollection props = _vtkRenderer.GetViewProps(); foreach (var graphic in layers) { var volumeGraphic = (VolumeGraphic) graphic; if (props.IsItemPresent(volumeGraphic.VtkProp) == 0) _vtkRenderer.AddViewProp(volumeGraphic.VtkProp); } }
/// <summary> /// Initializes a <see cref="RenderingException"/>. /// </summary> /// <param name="innerException">The actual exception that was thrown in the rendering pipeline.</param> /// <param name="drawArgs">The <see cref="DrawArgs"/> of the failed rendering operation.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="innerException"/> is null.</exception> public RenderingException(Exception innerException, DrawArgs drawArgs) : base("An exception was thrown in the rendering pipeline.", innerException) { if (innerException == null) throw new ArgumentNullException("innerException", "An inner exception must be provided."); // record as much information as possible about the rendering operation for debugging purposes if (drawArgs != null) { DrawMode = drawArgs.DrawMode; if (drawArgs.RenderingSurface != null) { WindowId = drawArgs.RenderingSurface.WindowID; ContextId = drawArgs.RenderingSurface.ContextID; ClientRectangle = drawArgs.RenderingSurface.ClientRectangle; ClipRectangle = drawArgs.RenderingSurface.ClipRectangle; } } }
protected override void OnPaint(PaintEventArgs e) { if (_surface != null) { _surface.ContextID = e.Graphics.GetHdc(); try { var args = new DrawArgs(_surface, new WinFormsScreenProxy(Screen.FromControl(this)), DrawMode.Refresh); _render(args); } finally { e.Graphics.ReleaseHdc(_surface.ContextID); } } //base.OnPaint(e); }
private void RenderImage() { if (_surface == null) return; using (var graphics = base.CreateGraphics()) { _surface.ContextID = graphics.GetHdc(); try { var args = new DrawArgs(_surface, new WinFormsScreenProxy(Screen.FromControl(this)), DrawMode.Render); _render(args); args = new DrawArgs(_surface, new WinFormsScreenProxy(Screen.FromControl(this)), DrawMode.Refresh); _render(args); } finally { graphics.ReleaseHdc(_surface.ContextID); } } }
/// <summary> /// Renders the <see cref="PresentationImage"/> without firing any events. /// </summary> /// <exception cref="RenderingException">Thrown if any <see cref="Exception"/> is encountered while rendering the image.</exception> protected void DrawNoEvents(DrawArgs drawArgs) { drawArgs.SceneGraph = this.SceneGraph; Rectangle oldRectangle = _clientRectangle; _clientRectangle = drawArgs.RenderingSurface.ClientRectangle; try { this.ImageRenderer.Draw(drawArgs); } finally { _clientRectangle = oldRectangle; } }
public override void Draw(DrawArgs drawArgs) { if (_delayedEventPublisher == null && SynchronizationContext.Current != null) _delayedEventPublisher = new DelayedEventPublisher(OnDelayedProgressChanged, 1000, DelayedEventPublisherTriggerMode.Periodic); var asyncFrame = Frame; using (asyncFrame.AcquireLock()) { if (!asyncFrame.IsAsyncLoaded) { if (!Visible) // if this is an off-screen draw, wait for data to be loaded { lock (_waitPixelData) { if (!asyncFrame.IsAsyncLoaded) { var completionHandler = new EventHandler((s, e) => { lock (_waitPixelData) { Monitor.Pulse(_waitPixelData); } }); var onFrameAsyncLoaded = new AsyncPixelDataEventHandler(completionHandler); var onFrameAsyncFaulted = new AsyncPixelDataFaultEventHandler(completionHandler); asyncFrame.AsyncLoaded += onFrameAsyncLoaded; asyncFrame.AsyncFaulted += onFrameAsyncFaulted; asyncFrame.GetNormalizedPixelData(); // check the flag again, in case the event actually fired before we hooked up the handler if (!asyncFrame.IsAsyncLoaded) Monitor.Wait(_waitPixelData); asyncFrame.AsyncLoaded -= onFrameAsyncLoaded; asyncFrame.AsyncFaulted -= onFrameAsyncFaulted; } } } else if (!ApplicationGraphics.OfType<ProgressGraphic>().Any()) { ProgressGraphic.Show(this, ApplicationGraphics, true, ProgressBarGraphicStyle.Continuous, false); } } base.Draw(drawArgs); } }
/// <summary> /// Forces a render of the specified image and setting the image's client rectangle property at the same time. /// </summary> public static Bitmap RenderImage(this IPresentationImage image, Rectangle clientRectangle) { // we can't just call image.DrawToBitmap because we also want to force the client rectangle of the image // which wouldn't be set correctly because the image has possibly never been drawn in a Tile before var presentationImage = image as PresentationImage; if (presentationImage != null) { var bmp = new Bitmap(clientRectangle.Width, clientRectangle.Height, PixelFormat.Format32bppArgb); var graphics = System.Drawing.Graphics.FromImage(bmp); var contextId = graphics.GetHdc(); try { using (var surface = presentationImage.ImageRenderer.CreateRenderingSurface(IntPtr.Zero, clientRectangle.Width, clientRectangle.Height, RenderingSurfaceType.Offscreen)) { surface.ContextID = contextId; surface.ClipRectangle = new Rectangle(0, 0, clientRectangle.Width, clientRectangle.Height); var drawArgs = new DrawArgs(surface, null, DrawMode.Render); presentationImage.Draw(drawArgs); drawArgs = new DrawArgs(surface, null, DrawMode.Refresh); presentationImage.Draw(drawArgs); } } finally { graphics.ReleaseHdc(contextId); graphics.Dispose(); } return bmp; } else { throw new NotSupportedException("Image type is not supported"); } }
/// <summary> /// Initializes the member variables before calling <see cref="Render"/> or <see cref="Refresh"/>. /// </summary> protected virtual void Initialize(DrawArgs drawArgs) { _drawMode = drawArgs.DrawMode; _sceneGraph = drawArgs.SceneGraph; _surface = drawArgs.RenderingSurface; Dpi = drawArgs.Dpi; }
protected override void OnPaint(PaintEventArgs e) { //Assume anything Vista or later has the same issues. if (IsVistaOrLater()) { //Windows Vista is opportunistic when it comes to wait conditions (e.g. locks, Mutexes, etc) //in that it will actually process WM_PAINT messages on the current thread, even though //it is supposed to be blocking in a WaitSleepJoin state. This behaviour can actually //break rendering for a couple of reasons: // 1. We do custom double-buffering, and it's possible that we could process a paint message // for an image that hasn't actually been rendered to the back buffer yet. // 2. The renderer itself accesses the pixel data of the ImageSops, which is a synchronized operation. // In the case where 2 threads try to load the pixel data of an image simultaneously, the renderer can end up // blocking execution on the main UI thread in the middle of a rendering operation. If we // allow another tile to paint in this situation, it actually causes some GDI errors because // the previous rendering operation has not yet completed. if (_isDrawing || _painting) { e.Graphics.Clear(Color.Black); //Queue this tile up for deferred painting and return. if (!_tilesToRepaint.Contains(this)) _tilesToRepaint.Add(this); return; } //We're about to paint this tile, so remove it from the queue. _tilesToRepaint.Remove(this); } if (_tile.PresentationImage == null) DisposeSurface(); if (this.Surface == null) { // Make sure tile gets blacked out if there's // no presentation image in it e.Graphics.Clear(Color.Black); } else { this.Surface.WindowID = this.Handle; this.Surface.ContextID = e.Graphics.GetHdc(); this.Surface.ClientRectangle = this.ClientRectangle; this.Surface.ClipRectangle = e.ClipRectangle; DrawArgs args = new DrawArgs(this.Surface, new WinFormsScreenProxy(Screen.FromControl(this)), DrawMode.Refresh); _painting = true; try { _tile.Draw(args); // if an exception was encountered the last time we rendered the buffer, refresh the error text now if (!string.IsNullOrEmpty(_lastRenderExceptionMessage)) { // we cannot simply pass the Graphics because we haven't released its hDC yet // if we do, we'll get a "Object is currently in use elsewhere" exception DrawErrorMessage(_lastRenderExceptionMessage, Surface.ContextID, ClientRectangle); } } catch (Exception ex) { Platform.Log(LogLevel.Error, ex, "An error has occured while refreshing the contents of a tile."); var exceptionMessage = ex is RenderingException ? ((RenderingException) ex).UserMessage : ex.Message; // we cannot simply pass the existing Graphics because we haven't released its hDC yet // if we do, we'll get a "Object is currently in use elsewhere" exception DrawErrorMessage(exceptionMessage, Surface.ContextID, ClientRectangle); } finally { e.Graphics.ReleaseHdc(this.Surface.ContextID); _painting = false; } } // Now that we've finished painting this tile, we can process the deferred paint jobs. // The code below is self-fulfilling, in that we remove one tile from the queue and // invalidate it, causing it to paint. When it's done painting, it will remove and // invalidate the next one, and so on. if (IsVistaOrLater() && _tilesToRepaint.Count > 0) { TileControl tileToRepaint = _tilesToRepaint[0]; _tilesToRepaint.RemoveAt(0); tileToRepaint.Invalidate(); tileToRepaint.Update(); } //base.OnPaint(e); }
private void DoDraw() { EventsHelper.Fire(_drawing, this, EventArgs.Empty); CodeClock clock = new CodeClock(); clock.Start(); if (this.Surface != null) { System.Drawing.Graphics graphics = this.CreateGraphics(); this.Surface.WindowID = this.Handle; this.Surface.ContextID = graphics.GetHdc(); this.Surface.ClientRectangle = this.ClientRectangle; this.Surface.ClipRectangle = this.ClientRectangle; DrawArgs args = new DrawArgs(this.Surface, new WinFormsScreenProxy(Screen.FromControl(this)), DrawMode.Render); _isDrawing = true; try { _tile.Draw(args); _lastRenderExceptionMessage = null; } catch (Exception ex) { Platform.Log(LogLevel.Error, ex, "An error has occured while rendering the contents of a tile."); _lastRenderExceptionMessage = ex is RenderingException ? ((RenderingException) ex).UserMessage : ex.Message; // we cannot simply pass the existing Graphics because we haven't released its hDC yet // if we do, we'll get a "Object is currently in use elsewhere" exception DrawErrorMessage(_lastRenderExceptionMessage, Surface.ContextID, ClientRectangle); } finally { graphics.ReleaseHdc(this.Surface.ContextID); graphics.Dispose(); _isDrawing = false; } } //Cause the tile to paint/refresh. Invalidate(); Update(); clock.Stop(); string str = String.Format("TileControl.Draw: {0}, {1}\n", clock.ToString(), this.Size.ToString()); Trace.Write(str); }
public void Draw(DrawArgs args) { CreateRenderer(); AddLayers(args); _surface.Draw(); }
/// <summary> /// Initializes the member variables before calling <see cref="RendererBase.Render"/> or <see cref="RendererBase.Refresh"/>. /// </summary> protected override void Initialize(DrawArgs drawArgs) { base.Initialize(drawArgs); }
private void RefreshImage(DrawArgs args) { try { // if there was an exception the last time we rendered the buffer, don't refresh from the buffer and instead redraw the error message if (string.IsNullOrEmpty(_lastRenderExceptionMessage)) { _magnificationImage.Draw(args); } else { // we cannot simply pass the existing Graphics because we haven't released its hDC yet // if we do, we'll get a "Object is currently in use elsewhere" exception DrawErrorMessage(_lastRenderExceptionMessage, args.RenderingSurface.ContextID, args.RenderingSurface.ClientRectangle); } } catch (Exception ex) { Platform.Log(LogLevel.Error, ex, "An error has occured while refreshing the magnified contents of the tile."); var exceptionMessage = ex is RenderingException ? ((RenderingException)ex).UserMessage : ex.Message; // we cannot simply pass the Graphics because we haven't released its hDC yet // if we do, we'll get a "Object is currently in use elsewhere" exception DrawErrorMessage(exceptionMessage, args.RenderingSurface.ContextID, args.RenderingSurface.ClientRectangle); } }
public void Draw(DrawArgs drawArgs) { Wrapper.Item.Draw(drawArgs); }
/// <summary> /// Raises the <see cref="EventBroker.ImageDrawing"/> event and /// renders the <see cref="PresentationImage"/>. /// </summary> /// <param name="drawArgs"></param> /// <remarks> /// For internal Framework use only. /// </remarks> /// <exception cref="RenderingException">Thrown if any <see cref="Exception"/> is encountered while rendering the image.</exception> public virtual void Draw(DrawArgs drawArgs) { drawArgs.SceneGraph = this.SceneGraph; _clientRectangle = drawArgs.RenderingSurface.ClientRectangle; // Let others know that we're about to draw ImageDrawingEventArgs args = new ImageDrawingEventArgs(this); if (this.ImageViewer != null && this.ImageViewer.EventBroker != null) this.ImageViewer.EventBroker.OnImageDrawing(args); OnDrawing(); this.ImageRenderer.Draw(drawArgs); }
/// <summary> /// Renders the specified scene graph to the graphics surface. /// </summary> /// <remarks> /// Calling code should take care to handle any exceptions in a manner suitable to the context of /// the rendering operation. For example, the view control for an /// <see cref="ITile"/> may wish to display the error message in the tile's client area <i>without /// crashing the control</i>, whereas an image export routine may wish to notify the user via an error /// dialog and have the export output <i>fail to be created</i>. Automated routines (such as unit /// tests) may even wish that the exception bubble all the way to the top for debugging purposes. /// </remarks> /// <param name="drawArgs">A <see cref="DrawArgs"/> object that specifies the graphics surface and the scene graph to be rendered.</param> /// <exception cref="RenderingException">Thrown if any <see cref="Exception"/> is encountered in the rendering pipeline.</exception> public virtual void Draw(DrawArgs drawArgs) { try { Initialize(drawArgs); if (drawArgs.RenderingSurface.ClientRectangle.Width == 0 || drawArgs.RenderingSurface.ClientRectangle.Height == 0) return; if (DrawMode == DrawMode.Render) Render(); else Refresh(); } catch (Exception e) { throw new RenderingException(e, drawArgs); } finally { _sceneGraph = null; _surface = null; } }
/// <summary> /// Renders the <see cref="PresentationImage"/> to a provided offscreen <see cref="Bitmap"/>. /// </summary> /// <param name="bmp">The offscreen bitmap to render to.</param> /// <returns></returns> /// <remarks> /// This method can be used anywhere an offscreen bitmap is required, such as /// paper/DICOM printing, thumbnail generation, creation of new DICOM images, etc. /// </remarks> /// <exception cref="ArgumentNullException">Thrown if <paramref name="bmp"/> is null.</exception> /// <exception cref="ArgumentException">Thrown if <paramref name="bmp"/> has invalid dimensions.</exception> /// <exception cref="RenderingException">Thrown if any <see cref="Exception"/> is encountered while rendering the image.</exception> public virtual void DrawToBitmap(Bitmap bmp) { Platform.CheckForNullReference(bmp, "bmp"); Platform.CheckPositive(bmp.Width, "bmp.Width"); Platform.CheckPositive(bmp.Height, "bmp.Height"); var graphics = System.Drawing.Graphics.FromImage(bmp); var contextId = graphics.GetHdc(); try { using (var surface = ImageRenderer.GetRenderingSurface(IntPtr.Zero, bmp.Width, bmp.Height)) { surface.ContextID = contextId; surface.ClipRectangle = new Rectangle(0, 0, bmp.Width, bmp.Height); var drawArgs = new DrawArgs(surface, null, DrawMode.Render); DrawNoEvents(drawArgs); drawArgs = new DrawArgs(surface, null, DrawMode.Refresh); DrawNoEvents(drawArgs); } } finally { graphics.ReleaseHdc(contextId); graphics.Dispose(); } }
private static Bitmap ImageDrawToBitmap(IPresentationImage presentationImage, int width, int height, float dpi) { if (!(presentationImage is PresentationImage)) return presentationImage.DrawToBitmap(width, height); var image = (PresentationImage) presentationImage; var bmp = new Bitmap(width, height); var graphics = System.Drawing.Graphics.FromImage(bmp); var contextId = graphics.GetHdc(); try { using (var surface = image.ImageRenderer.CreateRenderingSurface(IntPtr.Zero, bmp.Width, bmp.Height, RenderingSurfaceType.Offscreen)) { surface.ContextID = contextId; surface.ClipRectangle = new Rectangle(0, 0, bmp.Width, bmp.Height); var drawArgs = new DrawArgs(surface, null, DrawMode.Render) {Dpi = dpi, Tag = bmp}; image.Draw(drawArgs); drawArgs = new DrawArgs(surface, null, DrawMode.Refresh) { Dpi = dpi, Tag = bmp}; image.Draw(drawArgs); } } finally { graphics.ReleaseHdc(contextId); graphics.Dispose(); } return bmp; }