VariableWidthBitmapFont.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace FontBuilder
  6. {
  7. public class VariableWidthBitmapFont
  8. {
  9. private static System.Drawing.Color Magenta = System.Drawing.Color.FromArgb(255, 255, 0, 255);
  10. private static System.Drawing.Color Black = System.Drawing.Color.FromArgb(255, 0, 0, 0);
  11. private static System.Drawing.Color Transparent = System.Drawing.Color.FromArgb(0, 0, 0, 0);
  12. public static Dictionary<char, System.Drawing.Bitmap> DecodeVariableWidthBitmapFont(System.Drawing.Bitmap SourceBitmap)
  13. {
  14. var glyphs = new List<Rectangle>();
  15. var x = 0;
  16. var y = 0;
  17. while (y < SourceBitmap.Height)
  18. {
  19. int glyphHeight = 1;
  20. while (x < SourceBitmap.Width)
  21. {
  22. var pix = SourceBitmap.GetPixel(x, y);
  23. if (pix == Magenta)
  24. x += 1;
  25. else
  26. {
  27. var glyph = ExtractRect(SourceBitmap, x, y);
  28. glyphs.Add(glyph);
  29. x += glyph.Width;
  30. glyphHeight = glyph.Height;
  31. }
  32. }
  33. x = 0;
  34. y += glyphHeight;
  35. }
  36. var r = new Dictionary<char, System.Drawing.Bitmap>();
  37. var c = ' ';
  38. foreach (var glyph in glyphs)
  39. {
  40. if (!IsEmptyGlyph(SourceBitmap, glyph))
  41. r.Add(c, ExtractGlyph(SourceBitmap, glyph));
  42. c = (char)(c + 1);
  43. }
  44. return r;
  45. }
  46. /// <summary>
  47. /// Find the rectangle with origin at X, Y that is surrounded by magenta pixels
  48. /// </summary>
  49. /// <param name="Data"></param>
  50. /// <param name="X"></param>
  51. /// <param name="Y"></param>
  52. /// <returns></returns>
  53. private static Rectangle ExtractRect(System.Drawing.Bitmap Data, int X, int Y)
  54. {
  55. var endX = X;
  56. var endY = Y;
  57. while (endX < Data.Width && Data.GetPixel(endX, Y) != Magenta)
  58. endX += 1;
  59. while (endY < Data.Height && Data.GetPixel(X, endY) != Magenta)
  60. endY += 1;
  61. var rHeight = endY - Y;
  62. return new Rectangle(X, Y, endX - X, endY - Y);
  63. }
  64. /// <summary>
  65. /// Returns false if any pixel in the rectangle is not black.
  66. /// </summary>
  67. /// <param name="Data"></param>
  68. /// <param name="Rect"></param>
  69. /// <returns></returns>
  70. private static bool IsEmptyGlyph(System.Drawing.Bitmap Data, Rectangle Rect)
  71. {
  72. for (var x = Rect.X; x < Rect.X + Rect.Width && x < Data.Width; ++x)
  73. for (var y = Rect.Y; y < Rect.Y + Rect.Height && y < Data.Height; ++y)
  74. if (Data.GetPixel(x, y) != Black)
  75. return false;
  76. return true;
  77. }
  78. private static System.Drawing.Bitmap ExtractGlyph(System.Drawing.Bitmap Source, Rectangle Rect)
  79. {
  80. var r = new System.Drawing.Bitmap(Rect.Width, Rect.Height);
  81. for (var x = 0; x < Rect.Width && (x + Rect.X) < Source.Width; ++x)
  82. for (var y = 0; y < Rect.Height && (y + Rect.Y) < Source.Height; ++y)
  83. {
  84. var c = Source.GetPixel(x + Rect.X, y + Rect.Y);
  85. if (c == Black)
  86. r.SetPixel(x, y, Transparent);
  87. else
  88. r.SetPixel(x, y, c);
  89. }
  90. return r;
  91. }
  92. }
  93. }