public static Bitmap GetMergedBitmap(AddTexImageInfo[] images, OptimizedImgParams[] xLimits, int mergedImgWidth, int mergedImgHeight) { var heightOfEachImage = images[0].ImageBitmap.Height; if (images.Any(image => image.ImageBitmap.Height != heightOfEachImage)) { throw new Exception("GetMergedBitmap: All images should be of the same height"); } var mergedBitmap = new Bitmap(mergedImgWidth, mergedImgHeight); var g = Graphics.FromImage(mergedBitmap); g.Clear(Color.FromArgb(200, 200, 200)); g.InterpolationMode = InterpolationMode.HighQualityBilinear; g.Dispose(); var previousImgWidths = 0; for (var index = 0; index < images.Length; index++) { for (var y = 0; y < heightOfEachImage; y++) { var image = images[index]; //in the merged image, the original bitmaps are stacked one next to the other //the widths of the stacked images are cropped to their optimizedWidth //move forward by the previous image width var mergedImageXPos = previousImgWidths; if (xLimits[index].XLimitsAtYIndices[y].Min >= xLimits[index].OptimizedImgMin) { //move forward by the cropped min mergedImageXPos += xLimits[index].XLimitsAtYIndices[y].Min - xLimits[index].OptimizedImgMin; //Copy the pixel data from the image for (int x = xLimits[index].XLimitsAtYIndices[y].Min, noOfPixels = 1; noOfPixels <= xLimits[index].XLimitsAtYIndices[y].Width; noOfPixels++, x++) { var pixel = image.ImageBitmap.GetPixel(x, y); mergedBitmap.SetPixel(mergedImageXPos, y, pixel); mergedImageXPos++; } } } previousImgWidths += xLimits[index].OptimizedImgWidth; } //fill up blank spaces by extending edges TexImageOptimizer.ExtendTextureToAllSidesOfImage(mergedBitmap, 0); return(mergedBitmap); }
public static ImgIndexRange GetNextIndexRangeFromLeft(int beyondThisIndex, Bitmap img, int y, bool validInvalidFlag) { var startIndex = -1; for (var ctr = beyondThisIndex + 1; ctr >= 0 && ctr < img.Width; ctr++) { var valid = TexImageOptimizer.IsValidPixel(ctr, y, img); if (valid == validInvalidFlag) { startIndex = ctr; break; } } if (startIndex < 0) { return(null); } var endIndex = startIndex; for (var ctr = startIndex + 1; ctr >= 0 && ctr < img.Width; ctr++) { var valid = TexImageOptimizer.IsValidPixel(ctr, y, img); if (valid == validInvalidFlag) { endIndex = ctr; } else { break; //looking for continuous stream of pixels of same type (valid or invalid) } } return(new ImgIndexRange { MinIndex = startIndex, MaxIndex = endIndex }); }
internal static void ExtendRightTextureAtYValue(Bitmap img, int y, int consecutiveValidSidePixelsToOverlay) { var nextRange = IndexRangeProcessor.GetNextIndexRangeFromRight(img.Width, img, y, validInvalidFlag: false); while (nextRange != null) { if (consecutiveValidSidePixelsToOverlay > 0) { var validRange = IndexRangeProcessor.GetNextIndexRangeFromRight(nextRange.MinIndex, img, y, validInvalidFlag: true); if (validRange != null && (validRange.MaxIndex + 1 - validRange.MinIndex) > consecutiveValidSidePixelsToOverlay) { nextRange.MinIndex = nextRange.MinIndex - consecutiveValidSidePixelsToOverlay; } } var indexOfPixelToOverlay = nextRange.MinIndex - 1; if (0 <= indexOfPixelToOverlay && indexOfPixelToOverlay < img.Width) { var colorForOverlay = img.GetPixel(indexOfPixelToOverlay, y); TexImageOptimizer.ColorPixels(nextRange.MinIndex, nextRange.MaxIndex, colorForOverlay, img, y); } nextRange = IndexRangeProcessor.GetNextIndexRangeFromRight(nextRange.MinIndex, img, y, validInvalidFlag: false); } }