/// <summary> /// Provides the interface for merging two bitmaps together. /// </summary> /// <param name="bitmapA">The first bitmap for the merge</param> /// <param name="bitmapB">The second bitmap for the merge</param> /// <returns>The resulting bitmap</returns> public Bitmap Merge(Bitmap bitmapA, Bitmap bitmapB) { // Build the storage for the resulting bitmap PixelFormat pixelFormat = bitmapA.PixelFormat; Bitmap resultingBitmap = new Bitmap(bitmapA.Width, bitmapA.Height, pixelFormat); // Perform the merge for (int w = 0; w < bitmapA.Width; w++) { for (int h = 0; h < bitmapA.Height; h++) { Color pixelA = bitmapA.GetPixel(w, h); Color pixelB = bitmapB.GetPixel(w, h); if (!PixelUtils.ColorWithinThresholdOfWhite(pixelA, WhiteThreshold)) { // Set to the average of the two pixels if (PixelUtils.ColorsAreClose(pixelA, pixelB, LikenessThreshold)) { resultingBitmap.SetPixel(w, h, pixelA); } else { int brightnessA = PixelUtils.GetBrightness(pixelA); int brightnessB = PixelUtils.GetBrightness(pixelB); Color blendedPixel; // Determine which order to blend the pixels in if (brightnessA > brightnessB) { blendedPixel = BlendPixels(pixelB, pixelA, BlendAmount); } else { blendedPixel = BlendPixels(pixelA, pixelB, BlendAmount); } resultingBitmap.SetPixel(w, h, blendedPixel); } } else if (!PixelUtils.ColorWithinThresholdOfWhite(pixelA, WhiteThreshold)) { // PixelA has valid data, copy it resultingBitmap.SetPixel(w, h, pixelA); } else { // Just set this pixel to the value of pixelB resultingBitmap.SetPixel(w, h, pixelB); } } } return(resultingBitmap); }
/// <summary> /// Determines if a tile is complete. /// </summary> /// <returns>True if complete, else false</returns> public bool IsComplete() { Bitmap tileImage = GetBitmap(); int width = tileImage.Width; int height = tileImage.Height; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { Color currentPixel = tileImage.GetPixel(x, y); if (PixelUtils.ColorWithinThresholdOfWhite(currentPixel, 5)) return false; } } return true; }
/// <summary> /// Provides the interface for merging two bitmaps together. /// </summary> /// <param name="bitmapA">The first bitmap for the merge</param> /// <param name="bitmapB">The second bitmap for the merge</param> /// <returns>The resulting bitmap</returns> public Bitmap Merge(Bitmap bitmapA, Bitmap bitmapB) { //ApplicationController.Instance.Logger.Log("Using fast"); // Build the storage for the resulting bitmap PixelFormat pixelFormat = bitmapA.PixelFormat; Bitmap resultingBitmap = new Bitmap(bitmapA.Width, bitmapA.Height, pixelFormat); int width = bitmapA.Width; int height = bitmapA.Height; unsafe { BitmapData bitmapAData = bitmapA.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, pixelFormat); BitmapData bitmapBData = bitmapB.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, pixelFormat); BitmapData resultingBitmapData = resultingBitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, pixelFormat); int bytesPerPixel = Bitmap.GetPixelFormatSize(pixelFormat) / 8; int heightInPixels = bitmapAData.Height; int widthInBytes = bitmapAData.Width * bytesPerPixel; byte *firstPixelA = (byte *)bitmapAData.Scan0; byte *firstPixelB = (byte *)bitmapBData.Scan0; byte *firstPixelRes = (byte *)resultingBitmapData.Scan0; Parallel.For(0, heightInPixels, y => { byte *currentLineA = firstPixelA + (y * bitmapAData.Stride); byte *currentLineB = firstPixelB + (y * bitmapBData.Stride); byte *currentLineRes = firstPixelRes + (y * resultingBitmapData.Stride); for (int x = 0; x < widthInBytes; x = x + bytesPerPixel) { // Load the RGB values for the bitmaps int rA = currentLineA[x]; int rB = currentLineB[x]; int gA = currentLineA[x + 1]; int gB = currentLineB[x + 1]; int bA = currentLineA[x + 2]; int bB = currentLineB[x + 2]; // Translate to Microsoft classes // TODO: It would probably be faster to cut out the middle-man here... Color currentPixelA = Color.FromArgb(rA, gA, bA); Color currentPixelB = Color.FromArgb(rB, gB, bB); if (!PixelUtils.ColorWithinThresholdOfWhite(currentPixelA, WhiteThreshold)) { if (PixelUtils.ColorsAreClose(currentPixelA, currentPixelB, LikenessThreshold)) { // These colors are quite similar, just copy out the pixel from the first bitmap currentLineRes[x] = (byte)rA; currentLineRes[x + 1] = (byte)gA; currentLineRes[x + 2] = (byte)bA; } else { // Blend the pixels together int brightnessA = PixelUtils.GetBrightness(currentPixelA); int brightnessB = PixelUtils.GetBrightness(currentPixelB); Color blendedPixel; // Determine which order to blend the pixels in if (brightnessA > brightnessB) { blendedPixel = BlendPixels(currentPixelB, currentPixelA, BlendAmount); } else { blendedPixel = BlendPixels(currentPixelA, currentPixelB, BlendAmount); } currentLineRes[x] = blendedPixel.R; currentLineRes[x + 1] = blendedPixel.G; currentLineRes[x + 2] = blendedPixel.B; } } else if (!PixelUtils.ColorWithinThresholdOfWhite(currentPixelA, WhiteThreshold)) { // Just default to the pixel form bitmap a currentLineRes[x] = (byte)rA; currentLineRes[x + 1] = (byte)gA; currentLineRes[x + 2] = (byte)bA; } else { // Fall back to the pixel from bitmap b currentLineRes[x] = (byte)rB; currentLineRes[x + 1] = (byte)gB; currentLineRes[x + 2] = (byte)bB; } } }); } return(resultingBitmap); }