private static Dictionary <GlyphKey, string> ParseGlyphMap(Bitmap glyphMap, out int cw, out int ch, out GlyphKey cursorGlyph) { Dictionary <GlyphKey, string> glyphDictionary = new Dictionary <GlyphKey, string>(); BitmapData data = glyphMap.LockBits(new Rectangle(Point.Empty, glyphMap.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); int glyphMapStride = data.Stride / 4; int[] glyphMapData = new int[glyphMapStride * data.Height]; Marshal.Copy(data.Scan0, glyphMapData, 0, glyphMapData.Length); glyphMap.UnlockBits(data); int redARGB = Color.Red.ToArgb(); bool isUnicodeMap = glyphMapData[0] == redARGB || glyphMapData[0] == Color.Blue.ToArgb() || glyphMapData[0] == Color.Yellow.ToArgb(); int ww = isUnicodeMap ? 256 : 32, hh = isUnicodeMap ? 256 : 8; cw = glyphMap.Width / ww; ch = glyphMap.Height / hh; cursorGlyph = new GlyphKey(glyphMapData, glyphMapStride, 0, cw, ch); for (int y = 0; y < hh; y++) { for (int x = 0; x < ww; x++) { if ((x == 0 && y == 0) || (!isUnicodeMap && x == 31 && y == 7) || (isUnicodeMap && glyphMapData[x * cw + glyphMapStride * y * ch] == redARGB)) { continue; } GlyphKey charGlyph = new GlyphKey(glyphMapData, glyphMapStride, x * cw + glyphMapStride * y * ch, cw, ch); if (!glyphDictionary.ContainsKey(charGlyph)) { char chr = isUnicodeMap ? (char)(x + 256 * y) : charMap[x + 32 * y]; glyphDictionary.Add(charGlyph, (charGlyph.Background == cursorGlyph.Background ? "N" : "R") + chr); } } } return(glyphDictionary); }
public GlyphKey(GlyphKey glyph, GlyphKey cursor) { Background = glyph.Background; Foreground = glyph.Foreground; data = new bool[glyph.data.Length]; hashCode = 1; for (int i = 0; i < data.Length; i++) { data[i] = glyph.data[i] ^ cursor.data[i]; hashCode = unchecked (hashCode * 31 + (data[i] ? 1231 : 1237)); } }
private int ParseHex(Dictionary <GlyphKey, char> hexDigits, int[] rawData, int stride, int offset, int cw, int ch) { char[] chars = new char[4]; for (int i = 0; i < chars.Length; i++) { GlyphKey glyph = new GlyphKey(rawData, stride, offset + i * cw, cw, ch); if (!hexDigits.ContainsKey(glyph)) { return(-1); } chars[i] = hexDigits[glyph]; } return(int.Parse(new string(chars), System.Globalization.NumberStyles.HexNumber)); }
public override bool Equals(object obj) { GlyphKey other = obj as GlyphKey; if (other == null || other.data.Length != data.Length) { return(false); } for (int i = 0; i < data.Length; i++) { if (data[i] != other.data[i]) { return(false); } } return(true); }
private int ParseHex(Dictionary<GlyphKey, char> hexDigits, int[] rawData, int stride, int offset, int cw, int ch) { char[] chars = new char[4]; for (int i = 0; i < chars.Length; i++) { GlyphKey glyph = new GlyphKey(rawData, stride, offset + i * cw, cw, ch); if (!hexDigits.ContainsKey(glyph)) return -1; chars[i] = hexDigits[glyph]; } return int.Parse(new string(chars), System.Globalization.NumberStyles.HexNumber); }
private bool ParseUnicodePattern(Bitmap bmp, int[] rawData, int stride, int cw, int ch) { int cols = bmp.Width / cw, rows = bmp.Height / ch; int bgColor = rawData[0], fgColor = 42; // validate whole pattern again -- first two rows and first 32 chars of last row must be identical for (int i = 0; i < 3; i++) { int baseY = (i == 2 ? rows - 1 : i) * stride * ch; for (int j = 0; j < (i == 2 ? 32 : cols); j++) { for (int y = 0; y < ch; y++) { int cmpPos = y * stride; int basePos = baseY + j * cw + cmpPos; for (int x = 0; x < cw; x++) { if (basePos == cmpPos) { if (rawData[basePos + x] != bgColor && fgColor == 42) fgColor = rawData[basePos + x]; if (rawData[basePos + x] != fgColor && rawData[basePos + x] != bgColor) { Status = "Failed to validate calibration pattern - too many colors detected"; return false; } } if (rawData[basePos + x] != rawData[cmpPos + x]) { Status = "Failed to validate calibration pattern - marker character missing or incorrect"; return false; } } } } } for (int y = ch * 2; y < bmp.Height; y++) { int baseY = stride * y; for (int x = 0; x < bmp.Width; x++) { if (rawData[baseY + x] == bgColor) continue; else if (rawData[baseY + x] != fgColor) { Status = "Failed to validate calibration pattern - too many colors detected"; } int row = y / ch; if (x > cw * 74 || row == 2 || row == 4 || (row >= 23 && row < rows - 1) || (row == 3 && x > cw * 23) || (row >= 22 && row <= 24 && x > cw) ) { Status = "Failed to validate Unicode calibration pattern - characters outside allowed range"; return false; } } } // validate line syntax GlyphKey plus = new GlyphKey(rawData, stride, 0, cw, ch); GlyphKey space = new GlyphKey(rawData, stride, 2 * ch * stride, cw, ch); foreach (int x in new[] { 0, 17, 22 }) { GlyphKey check = new GlyphKey(rawData, stride, x * cw + 3 * ch * stride, cw, ch); if (!check.FullEquals(plus)) { Status = "Failed to validate Unicode calibration pattern - invalid digits line"; return false; } } foreach (int x in new[] { 4, 9 }) { for (int y = 5; y < 21; y++) { GlyphKey check = new GlyphKey(rawData, stride, x * cw + y * ch * stride, cw, ch); if (!check.FullEquals(space)) { Status = "Failed to validate Unicode calibration pattern - invalid data line"; return false; } } } // parse header line Dictionary<GlyphKey, char> hexDigits = new Dictionary<GlyphKey, char>(); for (int x = 0; x < 16; x++) { hexDigits.Add(new GlyphKey(rawData, stride, (x + 1) * cw + 3 * ch * stride, cw, ch), "0123456789ABCDEF"[x]); } int last = ParseHex(hexDigits, rawData, stride, 18 * cw + 3 * ch * stride, cw, ch); if (last == -1) { Status = "Failed to parse Unicode calibration pattern - invalid hex digits in header line"; return false; } if (last != lastUnicode) { if (last == lastLastUnicode) { WasSame = true; return false; } Status = "Failed to parse Unicode calibration pattern - incorrect page order"; return false; } lastLastUnicode = lastUnicode; // parse data lines bool moreScreens = new GlyphKey(rawData, stride, 21 * ch * stride, cw, ch).FullEquals(plus); for (int y = 5; y < 21; y++) { if (!moreScreens && new GlyphKey(rawData, stride, cw + y * ch * stride, cw, ch).FullEquals(space)) { StoreUnicodeGlyph(0, fgColor, bgColor, rawData, stride, y * ch * stride, cw, ch); break; } int from = ParseHex(hexDigits, rawData, stride, y * ch * stride, cw, ch); int to = ParseHex(hexDigits, rawData, stride, 5 * cw + y * ch * stride, cw, ch); if (from == -1 || to == -1 || to < from || to >= from + 64) { Status = "Failed to parse Unicode calibration pattern - invalid hex digits in data line"; return false; } for (int x = 0; x < to - from + 1; x++) { StoreUnicodeGlyph(from + x, fgColor, bgColor, rawData, stride, (x + 10) * cw + y * ch * stride, cw, ch); } lastUnicode = to; } if (moreScreens) { Status = "Calibrated unicode pattern page for " + cols + "x" + rows + " - more pages pending"; IsFinished = false; } else if (unicodePattern != null) { unicodePattern.Save(@"glyphmaps\unicode-calibrated-" + DateTime.Now.Ticks + "." + cols + "x" + rows + "." + bmp.Width + "x" + bmp.Height + ".glyphmap", ImageFormat.Png); Status = "Successfully calibrated Unicode pattern: " + cols + "x" + rows; IsFinished = true; } return true; }
private bool ParseUnicodePattern(Bitmap bmp, int[] rawData, int stride, int cw, int ch) { int cols = bmp.Width / cw, rows = bmp.Height / ch; int bgColor = rawData[0], fgColor = 42; // validate whole pattern again -- first two rows and first 32 chars of last row must be identical for (int i = 0; i < 3; i++) { int baseY = (i == 2 ? rows - 1 : i) * stride * ch; for (int j = 0; j < (i == 2 ? 32 : cols); j++) { for (int y = 0; y < ch; y++) { int cmpPos = y * stride; int basePos = baseY + j * cw + cmpPos; for (int x = 0; x < cw; x++) { if (basePos == cmpPos) { if (rawData[basePos + x] != bgColor && fgColor == 42) { fgColor = rawData[basePos + x]; } if (rawData[basePos + x] != fgColor && rawData[basePos + x] != bgColor) { Status = "Failed to validate calibration pattern - too many colors detected"; return(false); } } if (rawData[basePos + x] != rawData[cmpPos + x]) { Status = "Failed to validate calibration pattern - marker character missing or incorrect"; return(false); } } } } } for (int y = ch * 2; y < bmp.Height; y++) { int baseY = stride * y; for (int x = 0; x < bmp.Width; x++) { if (rawData[baseY + x] == bgColor) { continue; } else if (rawData[baseY + x] != fgColor) { Status = "Failed to validate calibration pattern - too many colors detected"; } int row = y / ch; if (x > cw * 74 || row == 2 || row == 4 || (row >= 23 && row < rows - 1) || (row == 3 && x > cw * 23) || (row >= 22 && row <= 24 && x > cw) ) { Status = "Failed to validate Unicode calibration pattern - characters outside allowed range"; return(false); } } } // validate line syntax GlyphKey plus = new GlyphKey(rawData, stride, 0, cw, ch); GlyphKey space = new GlyphKey(rawData, stride, 2 * ch * stride, cw, ch); foreach (int x in new[] { 0, 17, 22 }) { GlyphKey check = new GlyphKey(rawData, stride, x * cw + 3 * ch * stride, cw, ch); if (!check.FullEquals(plus)) { Status = "Failed to validate Unicode calibration pattern - invalid digits line"; return(false); } } foreach (int x in new[] { 4, 9 }) { for (int y = 5; y < 21; y++) { GlyphKey check = new GlyphKey(rawData, stride, x * cw + y * ch * stride, cw, ch); if (!check.FullEquals(space)) { Status = "Failed to validate Unicode calibration pattern - invalid data line"; return(false); } } } // parse header line Dictionary <GlyphKey, char> hexDigits = new Dictionary <GlyphKey, char>(); for (int x = 0; x < 16; x++) { hexDigits.Add(new GlyphKey(rawData, stride, (x + 1) * cw + 3 * ch * stride, cw, ch), "0123456789ABCDEF"[x]); } int last = ParseHex(hexDigits, rawData, stride, 18 * cw + 3 * ch * stride, cw, ch); if (last == -1) { Status = "Failed to parse Unicode calibration pattern - invalid hex digits in header line"; return(false); } if (last != lastUnicode) { if (last == lastLastUnicode) { WasSame = true; return(false); } Status = "Failed to parse Unicode calibration pattern - incorrect page order"; return(false); } lastLastUnicode = lastUnicode; // parse data lines bool moreScreens = new GlyphKey(rawData, stride, 21 * ch * stride, cw, ch).FullEquals(plus); for (int y = 5; y < 21; y++) { if (!moreScreens && new GlyphKey(rawData, stride, cw + y * ch * stride, cw, ch).FullEquals(space)) { StoreUnicodeGlyph(0, fgColor, bgColor, rawData, stride, y * ch * stride, cw, ch); break; } int from = ParseHex(hexDigits, rawData, stride, y * ch * stride, cw, ch); int to = ParseHex(hexDigits, rawData, stride, 5 * cw + y * ch * stride, cw, ch); if (from == -1 || to == -1 || to < from || to >= from + 64) { Status = "Failed to parse Unicode calibration pattern - invalid hex digits in data line"; return(false); } for (int x = 0; x < to - from + 1; x++) { StoreUnicodeGlyph(from + x, fgColor, bgColor, rawData, stride, (x + 10) * cw + y * ch * stride, cw, ch); } lastUnicode = to; } if (moreScreens) { Status = "Calibrated unicode pattern page for " + cols + "x" + rows + " - more pages pending"; IsFinished = false; } else if (unicodePattern != null) { unicodePattern.Save(@"glyphmaps\unicode-calibrated-" + DateTime.Now.Ticks + "." + cols + "x" + rows + "." + bmp.Width + "x" + bmp.Height + ".glyphmap", ImageFormat.Png); Status = "Successfully calibrated Unicode pattern: " + cols + "x" + rows; IsFinished = true; } return(true); }
private static string Parse(Bitmap bmp, int[] bmpData, int bmpStride, Bitmap glyphMap, out int parseErrors, int[] screenSize, Color[] fgColors, Color[] bgColors, out int cursorX, out int cursorY) { int cw, ch; GlyphKey cursorGlyph; Dictionary <GlyphKey, string> glyphDictionary = ParseGlyphMap(glyphMap, out cw, out ch, out cursorGlyph); int width = bmp.Width / cw; int height = bmp.Height / ch; screenSize[0] = width; screenSize[1] = height; cursorX = -1; cursorY = -1; int fg = 0, bg = 0; StringBuilder result = new StringBuilder(); parseErrors = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { bool found = false; for (int i = 0; !found && i < (cursorX == -1 ? 2 : 1); i++) { GlyphKey glyph = new GlyphKey(bmpData, bmpStride, x * cw + bmpStride * y * ch, cw, ch); if (glyph.Foreground == 42) { continue; } if (i == 1) { glyph = new GlyphKey(glyph, cursorGlyph); } string value; if (glyphDictionary.TryGetValue(glyph, out value)) { if (i == 1) { cursorX = x; cursorY = y; } found = true; result.Append(value[1]); if (value[0] == 'N') { fg = glyph.Foreground; bg = glyph.Background; } else { fg = glyph.Background; bg = glyph.Foreground; } } } if (!found) { result.Append("\uFFFD"); fg = Color.Red.ToArgb(); bg = Color.White.ToArgb(); parseErrors++; } if (fgColors != null) { fgColors[x + width * y] = Color.FromArgb(fg); } if (bgColors != null) { bgColors[x + width * y] = Color.FromArgb(bg); } } result.Append("\n"); } return(result.ToString()); }
public bool FullEquals(GlyphKey other) { return(Foreground == other.Foreground && Background == other.Background && Equals(other)); }
private static string Parse(Bitmap bmp, int[] bmpData, int bmpStride, Bitmap glyphMap, out int parseErrors, int[] screenSize, Color[] fgColors, Color[] bgColors, out int cursorX, out int cursorY) { int cw, ch; GlyphKey cursorGlyph; Dictionary<GlyphKey, string> glyphDictionary = ParseGlyphMap(glyphMap, out cw, out ch, out cursorGlyph); int width = bmp.Width / cw; int height = bmp.Height / ch; screenSize[0] = width; screenSize[1] = height; cursorX = -1; cursorY = -1; int fg = 0, bg = 0; StringBuilder result = new StringBuilder(); parseErrors = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { bool found = false; for (int i = 0; !found && i < (cursorX == -1 ? 2 : 1); i++) { GlyphKey glyph = new GlyphKey(bmpData, bmpStride, x * cw + bmpStride * y * ch, cw, ch); if (glyph.Foreground == 42) continue; if (i == 1) { glyph = new GlyphKey(glyph, cursorGlyph); } string value; if (glyphDictionary.TryGetValue(glyph, out value)) { if (i == 1) { cursorX = x; cursorY = y; } found = true; result.Append(value[1]); if (value[0] == 'N') { fg = glyph.Foreground; bg = glyph.Background; } else { fg = glyph.Background; bg = glyph.Foreground; } } } if (!found) { result.Append("\uFFFD"); fg = Color.Red.ToArgb(); bg = Color.White.ToArgb(); parseErrors++; } if (fgColors != null) { fgColors[x + width * y] = Color.FromArgb(fg); } if (bgColors != null) { bgColors[x + width * y] = Color.FromArgb(bg); } } result.Append("\n"); } return result.ToString(); }
public bool FullEquals(GlyphKey other) { return Foreground == other.Foreground && Background == other.Background && Equals(other); }
public GlyphKey(GlyphKey glyph, GlyphKey cursor) { Background = glyph.Background; Foreground = glyph.Foreground; data = new bool[glyph.data.Length]; hashCode = 1; for (int i = 0; i < data.Length; i++) { data[i] = glyph.data[i] ^ cursor.data[i]; hashCode = unchecked(hashCode * 31 + (data[i] ? 1231 : 1237)); } }
private static Dictionary<GlyphKey, string> ParseGlyphMap(Bitmap glyphMap, out int cw, out int ch, out GlyphKey cursorGlyph) { Dictionary<GlyphKey, string> glyphDictionary = new Dictionary<GlyphKey, string>(); BitmapData data = glyphMap.LockBits(new Rectangle(Point.Empty, glyphMap.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); int glyphMapStride = data.Stride / 4; int[] glyphMapData = new int[glyphMapStride * data.Height]; Marshal.Copy(data.Scan0, glyphMapData, 0, glyphMapData.Length); glyphMap.UnlockBits(data); int redARGB = Color.Red.ToArgb(); bool isUnicodeMap = glyphMapData[0] == redARGB || glyphMapData[0] == Color.Blue.ToArgb() || glyphMapData[0] == Color.Yellow.ToArgb(); int ww = isUnicodeMap ? 256 : 32, hh = isUnicodeMap ? 256 : 8; cw = glyphMap.Width / ww; ch = glyphMap.Height / hh; cursorGlyph = new GlyphKey(glyphMapData, glyphMapStride, 0, cw, ch); for (int y = 0; y < hh; y++) { for (int x = 0; x < ww; x++) { if ((x == 0 && y == 0) || (!isUnicodeMap && x == 31 && y == 7) || (isUnicodeMap && glyphMapData[x * cw + glyphMapStride * y * ch] == redARGB)) continue; GlyphKey charGlyph = new GlyphKey(glyphMapData, glyphMapStride, x * cw + glyphMapStride * y * ch, cw, ch); if (!glyphDictionary.ContainsKey(charGlyph)) { char chr = isUnicodeMap ? (char)(x + 256 * y) : charMap[x + 32 * y]; glyphDictionary.Add(charGlyph, (charGlyph.Background == cursorGlyph.Background ? "N" : "R") + chr); } } } return glyphDictionary; }