Пример #1
0
        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);
        }
Пример #2
0
 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));
     }
 }
Пример #3
0
 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));
 }
Пример #4
0
        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);
        }
Пример #5
0
 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);
 }
Пример #6
0
        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;
        }
Пример #7
0
        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);
        }
Пример #8
0
        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());
        }
Пример #9
0
 public bool FullEquals(GlyphKey other)
 {
     return(Foreground == other.Foreground && Background == other.Background && Equals(other));
 }
Пример #10
0
        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();
        }
Пример #11
0
 public bool FullEquals(GlyphKey other)
 {
     return Foreground == other.Foreground && Background == other.Background && Equals(other);
 }
Пример #12
0
 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));
     }
 }
Пример #13
0
 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;
 }