public static void CreateBitmapPerGlyph(FontGlyph[] sourceGlyphs, HelperBitmap[] sourceBitmaps, out FontGlyph[] destGlyphs, out HelperBitmap[] destBitmaps) { destBitmaps = new HelperBitmap[sourceGlyphs.Length]; destGlyphs = new FontGlyph[sourceGlyphs.Length]; for (int i = 0; i < sourceGlyphs.Length; i++) { var sg = sourceGlyphs[i]; destGlyphs[i] = new FontGlyph(i, new Rectangle(0, 0, sg.rect.Width, sg.rect.Height), sg.yOffset, sg.character); destBitmaps[i] = new HelperBitmap(new Bitmap(sg.rect.Width, sg.rect.Height, PixelFormat.Format32bppArgb)); HelperBitmap.Blit(sourceBitmaps[sg.page].bitmapData, destBitmaps[i].bitmapData, sg.rect, 0, 0); } }
public TexturePage(string filePath) { var bitmap = new HelperBitmap(filePath); CreateTexture(bitmap.bitmapData); bitmap.Free(); }
public void DownScale32(int newWidth, int newHeight) { HelperBitmap newBitmap = new HelperBitmap(new Bitmap(newWidth, newHeight, bitmap.PixelFormat)); if (bitmap.PixelFormat != PixelFormat.Format32bppArgb) throw new Exception("DownsScale32 only works on 32 bit images"); float xscale = (float)bitmapData.Width / newWidth; float yscale = (float)bitmapData.Height / newHeight; byte r = 0, g = 0, b = 0, a = 0; float summedR = 0f; float summedG = 0f; float summedB = 0f; float summedA = 0f; int left, right, top, bottom; //the area of old pixels covered by the new bitmap float targetStartX, targetEndX; float targetStartY, targetEndY; float leftF, rightF, topF, bottomF; //edges of new pixel in old pixel coords float weight; float weightScale = xscale * yscale; float totalColourWeight = 0f; for (int m = 0; m < newHeight; m++) { for (int n = 0; n < newWidth; n++) { leftF = n * xscale; rightF = (n + 1) * xscale; topF = m * yscale; bottomF = (m + 1) * yscale; left = (int)leftF; right = (int)rightF; top = (int)topF; bottom = (int)bottomF; if (left < 0) left = 0; if (top < 0) top = 0; if (right >= bitmapData.Width) right = bitmapData.Width - 1; if (bottom >= bitmapData.Height) bottom = bitmapData.Height - 1; summedR = 0f; summedG = 0f; summedB = 0f; summedA = 0f; totalColourWeight = 0f; for (int j = top; j <= bottom; j++) { for (int i = left; i <= right; i++) { targetStartX = Math.Max(leftF, i); targetEndX = Math.Min(rightF, i + 1); targetStartY = Math.Max(topF, j); targetEndY = Math.Min(bottomF, j + 1); weight = (targetEndX - targetStartX) * (targetEndY - targetStartY); GetPixel32(i, j, ref r, ref g, ref b, ref a); summedA += weight * a; if (a != 0) { summedR += weight * r; summedG += weight * g; summedB += weight * b; totalColourWeight += weight; } } } summedR /= totalColourWeight; summedG /= totalColourWeight; summedB /= totalColourWeight; summedA /= weightScale; if (summedR < 0) summedR = 0f; if (summedG < 0) summedG = 0f; if (summedB < 0) summedB = 0f; if (summedA < 0) summedA = 0f; if (summedR >= 256) summedR = 255; if (summedG >= 256) summedG = 255; if (summedB >= 256) summedB = 255; if (summedA >= 256) summedA = 255; newBitmap.PutPixel32(n, m, (byte)summedR, (byte)summedG, (byte)summedB, (byte)summedA); } } this.Free(); this.bitmap = newBitmap.bitmap; this.bitmapData = newBitmap.bitmapData; }
private static List<HelperBitmap> GenerateBitmapSheetsAndRepack(FontGlyph[] sourceGlyphs, BitmapData[] sourceBitmaps, int destSheetWidth, int destSheetHeight, out FontGlyph[] destGlyphs, int destMargin, bool usePowerOfTwo) { var pages = new List<HelperBitmap>(); destGlyphs = new FontGlyph[sourceGlyphs.Length]; HelperBitmap currentPage = null; int maxY = 0; foreach (var glph in sourceGlyphs) maxY = Math.Max(glph.rect.Height, maxY); int finalPageIndex = 0; int finalPageRequiredWidth = 0; int finalPageRequiredHeight = 0; for (int k = 0; k < 2; k++) { bool pre = k == 0; //first iteration is simply to determine the required size of the final page, so that we can crop it in advance int xPos = 0; int yPos = 0; int maxYInRow = 0; int totalTries = 0; for (int i = 0; i < sourceGlyphs.Length; i++) { if (!pre && currentPage == null) { if (finalPageIndex == pages.Count) { int width = Math.Min(destSheetWidth, usePowerOfTwo ? PowerOfTwo(finalPageRequiredWidth) : finalPageRequiredWidth); int height = Math.Min(destSheetHeight, usePowerOfTwo ? PowerOfTwo(finalPageRequiredHeight) : finalPageRequiredHeight); currentPage = new HelperBitmap(new Bitmap(width, height, PixelFormat.Format32bppArgb)); currentPage.Clear32(255, 255, 255, 0); //clear to white, but totally transparent } else { currentPage = new HelperBitmap(new Bitmap(destSheetWidth, destSheetHeight, PixelFormat.Format32bppArgb)); currentPage.Clear32(255, 255, 255, 0); //clear to white, but totally transparent } pages.Add(currentPage); } totalTries++; if (totalTries > 10 * sourceGlyphs.Length) throw new Exception("Failed to fit font into texture pages"); var rect = sourceGlyphs[i].rect; if (xPos + rect.Width + 2 * destMargin <= destSheetWidth && yPos + rect.Height + 2 * destMargin <= destSheetHeight) { if (!pre) { //add to page if (sourceBitmaps[sourceGlyphs[i].page].PixelFormat == PixelFormat.Format32bppArgb) HelperBitmap.Blit(sourceBitmaps[sourceGlyphs[i].page], currentPage.bitmapData, rect.X, rect.Y, rect.Width, rect.Height, xPos + destMargin, yPos + destMargin); else HelperBitmap.BlitMask(sourceBitmaps[sourceGlyphs[i].page], currentPage.bitmapData, rect.X, rect.Y, rect.Width, rect.Height, xPos + destMargin, yPos + destMargin); destGlyphs[i] = new FontGlyph(pages.Count - 1, new Rectangle(xPos + destMargin, yPos + destMargin, rect.Width, rect.Height), sourceGlyphs[i].yOffset, sourceGlyphs[i].character); } else { finalPageRequiredWidth = Math.Max(finalPageRequiredWidth, xPos + rect.Width + 2 * destMargin); finalPageRequiredHeight = Math.Max(finalPageRequiredHeight, yPos + rect.Height + 2 * destMargin); } xPos += rect.Width + 2 * destMargin; maxYInRow = Math.Max(maxYInRow, rect.Height); continue; } if (xPos + rect.Width + 2 * destMargin > destSheetWidth) { i--; yPos += maxYInRow + 2 * destMargin; xPos = 0; if (yPos + maxY + 2 * destMargin > destSheetHeight) { yPos = 0; if (!pre) { currentPage = null; } else { finalPageRequiredWidth = 0; finalPageRequiredHeight = 0; finalPageIndex++; } } continue; } } } return pages; }
/* public void Blur(int radius, int passes) { QBitmap tmp = new QBitmap(new Bitmap(this.bitmap.Width, this.bitmap.Height, bitmap.PixelFormat)); byte r=0,g=0,b=0,a=0; int summedR, summedG, summedB, summedA; int weight = 0; int xpos, ypos, x, y, kx, ky; for (int pass = 0; pass < passes; pass++) { //horizontal pass for (y = 0; y < bitmap.Height; y++) { for (x = 0; x < bitmap.Width; x++) { summedR = summedG = summedB = summedA = weight = 0; for (kx = -radius; kx <= radius; kx++) { xpos = x + kx; if (xpos >= 0 && xpos < bitmap.Width) { GetPixel32(xpos, y, ref r, ref g, ref b, ref a); summedR += r; summedG += g; summedB += b; summedA += a; weight++; } } summedR /= weight; summedG /= weight; summedB /= weight; summedA /= weight; tmp.PutPixel32(x, y, (byte)summedR, (byte)summedG, (byte)summedB, (byte)summedA); } } //vertical pass for (x = 0; x < bitmap.Width; ++x) { for (y = 0; y < bitmap.Height; ++y) { summedR = summedG = summedB = summedA = weight = 0; for (ky = -radius; ky <= radius; ky++) { ypos = y + ky; if (ypos >= 0 && ypos < bitmap.Height) { tmp.GetPixel32(x, ypos, ref r, ref g, ref b, ref a); summedR += r; summedG += g; summedB += b; summedA += a; weight++; } } summedR /= weight; summedG /= weight; summedB /= weight; summedA /= weight; PutPixel32(x, y, (byte)summedR, (byte)summedG, (byte)summedB, (byte)summedA); } } } tmp.Free(); }*/ public void BlurAlpha(int radius, int passes) { HelperBitmap tmp = new HelperBitmap(new Bitmap(this.bitmap.Width, this.bitmap.Height, bitmap.PixelFormat)); byte a = 0; int summedA; int weight = 0; int xpos, ypos, x, y, kx, ky; int width = bitmap.Width; int height = bitmap.Height; for (int pass = 0; pass < passes; pass++) { //horizontal pass for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { summedA = weight = 0; for (kx = -radius; kx <= radius; kx++) { xpos = x + kx; if (xpos >= 0 && xpos < width) { GetAlpha32(xpos, y, ref a); summedA += a; weight++; } } summedA /= weight; tmp.PutAlpha32(x, y, (byte)summedA); } } //vertical pass for (x = 0; x < width; ++x) { for (y = 0; y < height; ++y) { summedA = weight = 0; for (ky = -radius; ky <= radius; ky++) { ypos = y + ky; if (ypos >= 0 && ypos < height) { tmp.GetAlpha32(x, ypos, ref a); summedA += a; weight++; } } summedA /= weight; PutAlpha32(x, y, (byte)summedA); } } } tmp.Free(); }