/// <summary> /// Overlays the specified layer's image with the input image. /// Returns true on success. /// </summary> /// <param name="layerId">the id of the layer to apply the image to</param> /// <param name="image">The image to apply</param> /// <param name="updateRegion">The region that needs to be redrawn.</param> /// <param name="mode">The blendmode used to apply the image.</param> public bool applyImageOnLayer(int layerId, Bitmap image, Rectangle updateRegion, BlendMode mode) { Layer layer = m_layers[layerId]; // check if theres an image to apply to if (layer.hasFragment() == false) { return(false); } // create region relative to the image to update Rectangle imageRegion = layer.getLayerRegion(); // return if there's nothing to update if (!updateRegion.IntersectsWith(imageRegion)) { return(false); } // reduce the size of the redraw zone to only include area the layer's image covers Rectangle redrawRegion = Rectangle.Intersect(updateRegion, imageRegion); // area to redraw relative to the layer image // intersect to reduce area to redraw Point redrawLocalPosition = redrawRegion.Location; // offset by layer image position redrawLocalPosition.X -= imageRegion.X; redrawLocalPosition.Y -= imageRegion.Y; // get the layer's image Bitmap layerImage = layer.getImage(); // image that will be a cropped section of drawbuffer Bitmap bufferCrop = new Bitmap( redrawRegion.Width, redrawRegion.Height, PixelFormat.Format32bppArgb); // copy the section of the drawbuffer that will be redarwn into the cropbuffer image using (Graphics m = Graphics.FromImage(bufferCrop)) { m.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; m.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; m.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; m.DrawImage(image, new Rectangle(0, 0, redrawRegion.Width, redrawRegion.Height), redrawRegion, GraphicsUnit.Pixel); } //// apply the cropped image to the current layer image Bitmap bmp = RasterBlend.mergeImages( layerImage, bufferCrop, redrawLocalPosition, redrawRegion.Size, mode); bufferCrop.Dispose(); // set the new image as the layer image layer.setImage(bmp); bmp.Dispose(); return(true); }
/// <summary> /// Flattens drawbuffer to current layer and applies the changes to cached image. Runs Dispose() on cachedImage. /// Returns null on fail /// </summary> /// <param name="displaySize">The size of the display region in the application</param> /// <param name="updateRegion">The region within the final image that will be changed</param> /// <param name="cachedImage">The previous final image - gets Bitmap.Dispose()</param> /// <returns></returns> public Bitmap flattenImage(Size displaySize, Rectangle updateRegion, int startPos, int endPos, Bitmap cachedImage) { diagnostics.restartTimer(); if (updateRegion.Width <= 0 || updateRegion.Height <= 0) { return(null); } if (startPos >= endPos) { return(null); } if (startPos < 0) { startPos = 0; } if (endPos > m_layerCount) { endPos = m_layerCount; } // copy previous image into the result to reduce work needed Bitmap result = cachedImage; // the image to stack layers into and apply to the reswult image after stacking Bitmap redrawnSection = new Bitmap(updateRegion.Width, updateRegion.Height); // remove all data that will be overwritten from flattening // this must happen before redrawnSection is written to using (Graphics gr = Graphics.FromImage(result)) { gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; gr.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy; gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; gr.DrawImage(redrawnSection, updateRegion, new Rectangle(new Point(0, 0), redrawnSection.Size), GraphicsUnit.Pixel); } diagnostics.printTimeElapsedAndRestart("PREPARE RESULT IMAGE TIME "); // move pixels from drawBuffer to display_canvas // flatten all layers for (int l = startPos; l < endPos; l++) //for (int l = m_layerCount - 1; l >= 0; l--) { // get a handle on the layer Layer layer = m_layers[l]; // Console.Write("\nLayer " + l + " isVisible = " + layer.getIsVisible()); // skip layer if is not visible or has not been set if (layer.getId() == int.MinValue) { continue; } if (layer.getIsVisible() == false) { continue; } if (layer.hasFragment() == false) { continue; } // create region relative to the image to update Rectangle imageRegion = layer.getLayerRegion(); // get a handle on the layers image Bitmap layerImage = layer.getImage(); if (layerImage == null) { continue; } // reduce the size of the redraw zone to only include area the layer's image covers Rectangle redrawRegion = Rectangle.Intersect(updateRegion, imageRegion); // area to redraw relative to the layer image // intersect to reduce area to redraw Point redrawLocalPosition = redrawRegion.Location; // offset by layer image position redrawLocalPosition.X -= imageRegion.X; redrawLocalPosition.Y -= imageRegion.Y; // go to next layer if there's nothing to update if (!updateRegion.IntersectsWith(imageRegion)) { continue; } // create new image the size of redraw region Bitmap layerCrop = new Bitmap( redrawRegion.Width, redrawRegion.Height, PixelFormat.Format32bppArgb); // cut section out of layer that will be applied to the image using (Graphics gr = Graphics.FromImage(layerCrop)) { gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; gr.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; gr.DrawImage(layerImage, new Rectangle(0, 0, redrawRegion.Width, redrawRegion.Height), new Rectangle(redrawLocalPosition, redrawRegion.Size), GraphicsUnit.Pixel); } // apply cutout to the result image Bitmap stack = RasterBlend.mergeImages( redrawnSection, layerCrop, new Point(redrawRegion.X -= updateRegion.X, redrawRegion.Y -= updateRegion.Y),//redrawLocalPosition, redrawRegion.Size, BlendMode.Add); layerCrop.Dispose(); if (redrawnSection != null) { redrawnSection.Dispose(); } redrawnSection = stack; diagnostics.printTimeElapsedAndRestart("FLATTEN LAYER " + l + " TIME"); } // END l // create final image Bitmap final = RasterBlend.mergeImages( result, redrawnSection, updateRegion.Location, updateRegion.Size, BlendMode.Add); // this is now the final version of Bitmap stack redrawnSection.Dispose(); if (result != null) { result.Dispose(); } // set new image as the result result = final; diagnostics.printTimeElapsedAndRestart("SET RESULT AND DISPOSE TIME "); return(result); }