1
0
mirror of https://github.com/ncblakely/GiantsTools synced 2024-07-03 20:11:45 +02:00
GiantsTools/Sdk/External/DirectXTK/MakeSpriteFont/BitmapImporter.cs
2021-01-23 15:40:09 -08:00

122 lines
4.4 KiB
C#

// DirectXTK MakeSpriteFont tool
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// http://go.microsoft.com/fwlink/?LinkId=248929
using System;
using System.Linq;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
namespace MakeSpriteFont
{
// Extracts font glyphs from a specially marked 2D bitmap. Characters should be
// arranged in a grid ordered from top left to bottom right. Monochrome characters
// should use white for solid areas and black for transparent areas. To include
// multicolored characters, add an alpha channel to the bitmap and use that to
// control which parts of the character are solid. The spaces between characters
// and around the edges of the grid should be filled with bright pink (red=255,
// green=0, blue=255). It doesn't matter if your grid includes lots of wasted space,
// because the converter will rearrange characters, packing as tightly as possible.
public class BitmapImporter : IFontImporter
{
// Properties hold the imported font data.
public IEnumerable<Glyph> Glyphs { get; private set; }
public float LineSpacing { get; private set; }
public void Import(CommandLineOptions options)
{
// Load the source bitmap.
Bitmap bitmap;
try
{
bitmap = new Bitmap(options.SourceFont);
}
catch
{
throw new Exception(string.Format("Unable to load '{0}'.", options.SourceFont));
}
// Convert to our desired pixel format.
bitmap = BitmapUtils.ChangePixelFormat(bitmap, PixelFormat.Format32bppArgb);
// What characters are included in this font?
var characters = CharacterRegion.Flatten(options.CharacterRegions).ToArray();
int characterIndex = 0;
char currentCharacter = '\0';
// Split the source image into a list of individual glyphs.
var glyphList = new List<Glyph>();
Glyphs = glyphList;
LineSpacing = 0;
foreach (Rectangle rectangle in FindGlyphs(bitmap))
{
if (characterIndex < characters.Length)
currentCharacter = characters[characterIndex++];
else
currentCharacter++;
glyphList.Add(new Glyph(currentCharacter, bitmap, rectangle));
LineSpacing = Math.Max(LineSpacing, rectangle.Height);
}
// If the bitmap doesn't already have an alpha channel, create one now.
if (BitmapUtils.IsAlphaEntirely(255, bitmap))
{
BitmapUtils.ConvertGreyToAlpha(bitmap);
}
}
// Searches a 2D bitmap for characters that are surrounded by a marker pink color.
static IEnumerable<Rectangle> FindGlyphs(Bitmap bitmap)
{
using (var bitmapData = new BitmapUtils.PixelAccessor(bitmap, ImageLockMode.ReadOnly))
{
for (int y = 1; y < bitmap.Height; y++)
{
for (int x = 1; x < bitmap.Width; x++)
{
// Look for the top left corner of a character (a pixel that is not pink, but was pink immediately to the left and above it)
if (!IsMarkerColor(bitmapData[x, y]) &&
IsMarkerColor(bitmapData[x - 1, y]) &&
IsMarkerColor(bitmapData[x, y - 1]))
{
// Measure the size of this character.
int w = 1, h = 1;
while ((x + w < bitmap.Width) && !IsMarkerColor(bitmapData[x + w, y]))
{
w++;
}
while ((y + h < bitmap.Height) && !IsMarkerColor(bitmapData[x, y + h]))
{
h++;
}
yield return new Rectangle(x, y, w, h);
}
}
}
}
}
// Checks whether a color is the magic magenta marker value.
static bool IsMarkerColor(Color color)
{
return color.ToArgb() == Color.Magenta.ToArgb();
}
}
}