/// <summary> /// Merges two images taking into consideration their alpha values. /// </summary> /// <param name="bmpBg">The background Image</param> /// <param name="bmpTop">The image that goes on top of the background</param> /// <param name="xBg">Left corner position of background</param> /// <param name="yBg">Top corner position of the background</param> /// <param name="xTop">Left corner position of the top image</param> /// <param name="yTop">Top corner position of the top image</param> /// <returns>Returns an interface to the image</returns> IImageAdapterUnmanaged IImageAdapterUnmanaged.Merge(IImageAdapterUnmanaged bmpBg, IImageAdapterUnmanaged bmpTop, int xBg, int yBg, int xTop, int yTop) { System.Diagnostics.Debug.WriteLine("Merge() started"); #if DEBUG ImageUtility.ToImageFile(bmpBg, System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Before_Merge_Bg.png")); ImageUtility.ToImageFile(bmpTop, System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Before_Merge_Top.png")); #endif // debug #if DEBUG ImageUtility.ToImageFile((IImageAdapter)bmpBg, System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Merge_BgImage.bmp")); ImageUtility.ToImageFile((IImageAdapter)bmpTop, System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Merge_TopImage.bmp")); #endif // DEBUG Rectangle rBg = new Rectangle(xBg, yBg, bmpBg.Width, bmpBg.Height); Rectangle rTop = new Rectangle(xTop, yTop, bmpTop.Width, bmpTop.Height); System.Diagnostics.Debug.WriteLine("Merge() \n\nrBg " + rBg.ToString() + "\nrTop " + rTop.ToString()); if (Rectangle.Intersect(rBg, rTop) != rTop) { throw new ArgumentOutOfRangeException("Top BMP must be inside Bg one"); } int maxAlpha = 0; float bgAlpha = 0; float topAlpha = 0; // Copy Color from background image into this (same as cloning bg image into 'this') ImageAdapter temp = new ImageAdapter((IImageAdapter)bmpBg); System.Diagnostics.Debug.WriteLine("Merge1() : Before the loop"); for (int x = rBg.Left; x < rBg.Right; x++) { for (int y = rBg.Top; y < rBg.Bottom; y++) { if (rTop.Contains(x, y)) { IColor colorBg = bmpBg[x - rBg.Left, y - rBg.Top]; IColor colorTop = bmpTop[x - rTop.Left, y - rTop.Top]; maxAlpha = Math.Max(colorBg.A, colorTop.A); topAlpha = (float)colorTop.Alpha; bgAlpha = (float)((1f - colorTop.Alpha) * colorBg.Alpha); IColor color = new ColorByte((byte)maxAlpha, (byte)(bgAlpha * colorBg.R + topAlpha * colorTop.R), (byte)(bgAlpha * colorBg.G + topAlpha * colorTop.G), (byte)(bgAlpha * colorBg.B + topAlpha * colorTop.B)); temp[x - rBg.Left, y - rBg.Top] = color; } } } #if DEBUG ImageUtility.ToImageFile(temp, System.IO.Path.Combine(System.IO.Path.GetTempPath(), "After_Merge_This.png")); #endif return((IImageAdapterUnmanaged)temp); }
private void InternalConstructor(Bitmap bmp) { if (bmp == null) { throw new ArgumentNullException("Bitmap passed in is null"); } _colors = new IColor[bmp.Width, bmp.Height]; _metadataInfo = new MetadataInfo(bmp.PropertyItems); //Verify that metadata correctly set the DPI //In the case where no dpi meta is stored with the image it defaults to the screen resolution //we fix that here in the metadata info Point metaDpi = MetadataInfoHelper.GetDpi(_metadataInfo); Point bmpDpi = new Point((int)Math.Round(bmp.HorizontalResolution), (int)Math.Round(bmp.VerticalResolution)); if (!metaDpi.Equals(bmpDpi)) { MetadataInfoHelper.SetDpi(_metadataInfo, bmpDpi); } ImageUtility image = null; try { image = new ImageUtility(bmp); // Conversion to 32 bits done internally. image.GetSetPixelUnsafeBegin(); byte[] BGRAStream = image.GetStreamBufferBGRA(); image.GetSetPixelUnsafeRollBack(); int size = BGRAStream.Length; for (int index = 0, x = 0, y = 0; index < size; index += 4, x++) // flat array to remove the cost of the computation (x + y *x) { if (x >= Width) { x = 0; y++; } _colors[x, y] = new ColorByte(BGRAStream[index + 3], BGRAStream[index + 2], BGRAStream[index + 1], BGRAStream[index]); if (_colors[x, y].ARGB == 0) { _colors[x, y].IsEmpty = true; } } BGRAStream = null; } finally { if (image != null) { image.Dispose(); image = null; } GC.Collect(GC.MaxGeneration); } }