示例#1
0
    public void Show(DesignPattern pattern, System.Action confirm, System.Action cancel)
    {
        this.CurrentBrush = new Brush()
        {
            Editor = this
        };
        if (pattern != null)
        {
            this.CurrentPattern = new Pattern(this, pattern);
            this.CurrentPattern.Load();

            IsShown       = true;
            ConfirmAction = confirm;
            CancelAction  = cancel;

            Type = pattern.Type;
        }

        Preview.texture = Previews.AllPreviews[Type].Camera.targetTexture;
        Previews.AllPreviews[Type].ResetPosition();
        Previews.AllPreviews[Type].Render();

        Tools.PatternChanged();
        Tools.BrushUpdated();
        Tools.SwitchTool(Tools.Tool.None);
        Tools.SwitchToolset(Tools.Toolset.RasterLayer);
        PixelGrid.PatternLoaded();
    }
示例#2
0
 public void SetType(DesignPattern.TypeEnum type)
 {
     _Type = type;
     Editor.SetType(type);
     Info = DesignPatternInformation.Types[Type];
     this.Load();
 }
示例#3
0
    public void Show(DesignPattern pattern, System.Action confirm, System.Action cancel)
    {
        try
        {
            Logger.Log(Logger.Level.DEBUG, "[PatternEditor] Showing pattern editor...");

            Logger.Log(Logger.Level.DEBUG, "[PatternEditor] Creating new brush...");
            if (this.CurrentBrush != null)
            {
                this.CurrentBrush.Dispose();
                this.CurrentBrush = null;
            }

            this.CurrentBrush = new Brush()
            {
                Editor = this
            };
            if (pattern != null)
            {
                Logger.Log(Logger.Level.DEBUG, "[PatternEditor] Adding pattern to editor.");
                IsPro = pattern is ProDesignPattern;
                this.CurrentPattern = new Pattern(this, pattern);
                this.CurrentPattern.Load();

                IsShown       = true;
                ConfirmAction = confirm;
                CancelAction  = cancel;

                Type = pattern.Type;
            }

            Logger.Log(Logger.Level.DEBUG, "[PatternEditor] Setting textures to previews.");
            Preview.texture = Previews.AllPreviews[Type].Camera.targetTexture;
            Previews.AllPreviews[Type].ResetPosition();
            Previews.AllPreviews[Type].Render();

            Logger.Log(Logger.Level.DEBUG, "[PatternEditor] Updating tools state.");
            Tools.PatternChanged();
            Tools.BrushUpdated();
            Tools.SwitchTool(Tools.Tool.None);
            Tools.SwitchToolset(Tools.Toolset.RasterLayer);
            PixelGrid.PatternLoaded();
        }
        catch (System.Exception e) { Logger.Log(Logger.Level.ERROR, "[PatternEditor] Error while showing PatternEditor: " + e.ToString()); }
    }
    public ACNHFileFormat(byte[] bytes)
    {
        Version   = bytes[0];
        Name      = System.Text.Encoding.Unicode.GetString(bytes, 1, 0x29).Replace(" ", "").Trim();
        Palette   = new DesignPattern.DesignColor[15];
        this.Type = (DesignPattern.TypeEnum)bytes[0x2B];
        for (int i = 0; i < 15; i++)
        {
            Palette[i] = new DesignPattern.DesignColor()
            {
                R = bytes[0x2C + i * 3 + 0], G = bytes[0x2C + i * 3 + 1], B = bytes[0x2C + i * 3 + 2]
            }
        }
        ;
        this.Pixels = new byte[Width / 2 * Height];
        Array.Copy(bytes, 0x59, this.Pixels, 0, this.Pixels.Length);
    }
}
    public static (int, int, int, int) FindPattern(TextureBitmap bitmap, DesignPattern.TypeEnum type)
    {
        bool isPro = type != DesignPattern.TypeEnum.SimplePattern;

        unsafe
        {
            var    colors       = bitmap.GetColors();
            int    bitmapWidth  = bitmap.Width;
            int    bitmapHeight = bitmap.Height;
            bool[] bw           = new bool[bitmapWidth * bitmapHeight];   // true = black
            int    min          = 180;
            int    max          = 235;
            for (int x = 0; x < bitmapWidth; x++)
            {
                for (int y = 0; y < bitmapHeight; y++)
                {
                    float h;
                    float s;
                    float v;
                    var   col = colors[x + y * bitmapWidth];
                    int   r   = (int)(col.R);
                    int   g   = (int)(col.G);
                    int   b   = (int)(col.B);
                    r = r * (r >= min && r <= max ? 0 : 1);
                    g = g * (g >= min && g <= max ? 0 : 1);
                    b = b * (b >= min && b <= max ? 0 : 1);
                    bw[x + y * bitmapWidth] = r == 0 && g == 0;
                }
            }

            int widthThreshold = 5;
            int minWidth       = 2;
            List <(int, int, int)> horizontalLines = new List <(int, int, int)>();
            List <(int, int, int)> verticalLines   = new List <(int, int, int)>();

            for (int y = 0; y < bitmapHeight; y++)
            {
                int  currentDashWidth  = 0;
                int  currentSpaceWidth = 0;
                int  dashes            = 0;
                int  dashWidth         = 0;
                int  start             = 0;
                bool black             = false;

                for (int x = 0; x < bitmapWidth; x++)
                {
                    int idx = x + y * bitmapWidth;
                    if (bw[idx])
                    {
                        if (!black)
                        {
                            currentDashWidth = 0;
                            if (dashes > 0 && currentSpaceWidth > dashWidth)
                            {
                                dashes = 0; dashWidth = 0;
                            }
                            if (dashes == 0)
                            {
                                start = x;
                            }
                        }
                        black = true;
                        currentDashWidth++;
                    }
                    else
                    {
                        if (dashes == 0 && currentDashWidth >= minWidth)
                        {
                            dashWidth = currentDashWidth;
                        }

                        if (dashWidth > 0)
                        {
                            if (black)
                            {
                                currentSpaceWidth = 0;
                                if (currentDashWidth < dashWidth - widthThreshold || currentDashWidth < minWidth || currentDashWidth > dashWidth + widthThreshold)
                                {
                                    dashes = 0; dashWidth = 0;
                                }
                                else
                                {
                                    dashes++;
                                    if (dashes >= 14)
                                    {
                                        horizontalLines.Add((start, y, x));
                                        dashWidth = 0;
                                        dashes    = 0;
                                        continue;
                                    }
                                }
                            }
                            if (dashes > 0)
                            {
                                currentSpaceWidth++;
                            }
                        }
                        black = false;
                    }
                }
            }

            for (int x = 0; x < bitmapWidth; x++)
            {
                int  currentDashWidth  = 0;
                int  currentSpaceWidth = 0;
                int  dashes            = 0;
                int  dashWidth         = 0;
                int  start             = 0;
                bool black             = false;

                for (int y = 0; y < bitmapHeight; y++)
                {
                    int idx = x + y * bitmapWidth;
                    if (bw[idx])
                    {
                        if (!black)
                        {
                            currentDashWidth = 0;
                            if (dashes > 0 && currentSpaceWidth > dashWidth)
                            {
                                dashes = 0; dashWidth = 0;
                            }
                            if (dashes == 0)
                            {
                                start = y;
                            }
                        }
                        black = true;
                        currentDashWidth++;
                    }
                    else
                    {
                        if (dashes == 0 && currentDashWidth >= minWidth)
                        {
                            dashWidth = currentDashWidth;
                        }

                        if (dashWidth > 0)
                        {
                            if (black)
                            {
                                currentSpaceWidth = 0;
                                if (currentDashWidth < dashWidth - widthThreshold || currentDashWidth < minWidth || currentDashWidth > dashWidth + widthThreshold)
                                {
                                    dashes = 0; dashWidth = 0;
                                }
                                else
                                {
                                    dashes++;
                                    if (dashes >= 14)
                                    {
                                        verticalLines.Add((x, start, y));
                                        dashWidth = 0;
                                        dashes    = 0;
                                        continue;
                                    }
                                }
                            }
                            if (dashes > 0)
                            {
                                currentSpaceWidth++;
                            }
                        }
                        black = false;
                    }
                }
            }

            int sizeThreshold = 10;

            // find pairing horizontal lines
            List <List <int> > horizontalGroups = new List <List <int> >();
            List <int>         foundHorizontal  = new List <int>();
            for (int i = 0; i < horizontalLines.Count - 1; i++)
            {
                if (!foundHorizontal.Contains(i))
                {
                    List <int> group = new List <int>();
                    group.Add(i);
                    for (int j = i + 1; j < horizontalLines.Count; j++)
                    {
                        if (UnityEngine.Mathf.Abs(horizontalLines[i].Item1 - horizontalLines[j].Item1) < sizeThreshold &&
                            UnityEngine.Mathf.Abs(horizontalLines[i].Item3 - horizontalLines[j].Item3) < sizeThreshold)
                        {
                            group.Add(j);
                            foundHorizontal.Add(j);
                        }
                    }
                    horizontalGroups.Add(group);
                }
            }

            // find pairing vertical lines
            List <List <int> > verticalGroups = new List <List <int> >();
            List <int>         foundVertical  = new List <int>();
            for (int i = 0; i < verticalLines.Count - 1; i++)
            {
                if (!foundVertical.Contains(i))
                {
                    List <int> group = new List <int>();
                    group.Add(i);
                    for (int j = i + 1; j < verticalLines.Count; j++)
                    {
                        if (UnityEngine.Mathf.Abs(verticalLines[i].Item2 - verticalLines[j].Item2) < sizeThreshold &&
                            UnityEngine.Mathf.Abs(verticalLines[i].Item3 - verticalLines[j].Item3) < sizeThreshold)
                        {
                            group.Add(j);
                            foundVertical.Add(j);
                        }
                    }
                    verticalGroups.Add(group);
                }
            }

            (int, int)whiteR = (235, 255);
            (int, int)whiteG = (235, 255);
            (int, int)whiteB = (200, 255);
            List <(int, int, int, int, bool[])> rects = new List <(int, int, int, int, bool[])>();
            for (int i = 0; i < verticalGroups.Count; i++)
            {
                var vTop    = verticalLines[verticalGroups[i][0]].Item2;
                var vBottom = verticalLines[verticalGroups[i][0]].Item3;
                var vX      = verticalLines[verticalGroups[i][0]].Item1;

                for (int j = 0; j < horizontalGroups.Count; j++)
                {
                    var hLeft  = horizontalLines[horizontalGroups[j][0]].Item1;
                    var hRight = horizontalLines[horizontalGroups[j][0]].Item3;
                    var hY     = horizontalLines[horizontalGroups[j][0]].Item2;

                    UnityEngine.Debug.Log(vTop + "-" + vBottom + "(" + vX + ") " + hLeft + "-" + hRight + "(" + hY + ")");
                    if ((UnityEngine.Mathf.Abs(hY - vTop) < sizeThreshold ||
                         UnityEngine.Mathf.Abs(hY - vBottom) < sizeThreshold) &&
                        (UnityEngine.Mathf.Abs(vX - hLeft) < sizeThreshold ||
                         UnityEngine.Mathf.Abs(vX - hRight) < sizeThreshold))
                    {
                        // its a rect!
                        int    w    = hRight - hLeft;
                        int    h    = vBottom - vTop;
                        bool[] rect = new bool[w * h];

                        // find outer top
                        int outerTop = -1;
                        for (int y = -30; y < 0; y++)
                        {
                            int r = (int)(colors[(hLeft + w / 2) + (vTop + y) * bitmapWidth].R);
                            int g = (int)(colors[(hLeft + w / 2) + (vTop + y) * bitmapWidth].G);
                            int b = (int)(colors[(hLeft + w / 2) + (vTop + y) * bitmapWidth].B);
                            if (r >= 240 && g >= 240 && b >= 220)
                            {
                                outerTop = vTop + y;
                                break;
                            }
                        }
                        // find outer left
                        int outerLeft = -1;
                        for (int x = -30; x < 0; x++)
                        {
                            int r = (int)(colors[(hLeft + x) + (vTop + h / 2) * bitmapWidth].R);
                            int g = (int)(colors[(hLeft + x) + (vTop + h / 2) * bitmapWidth].G);
                            int b = (int)(colors[(hLeft + x) + (vTop + h / 2) * bitmapWidth].B);
                            if (r >= 240 && g >= 240 && b >= 220)
                            {
                                outerLeft = hLeft + x;
                                break;
                            }
                        }
                        // find outer bottom
                        int outerBottom = -1;
                        for (int y = 29; y >= 0; y--)
                        {
                            int r = (int)(colors[(hLeft + w / 2) + (vBottom + y) * bitmapWidth].R);
                            int g = (int)(colors[(hLeft + w / 2) + (vBottom + y) * bitmapWidth].G);
                            int b = (int)(colors[(hLeft + w / 2) + (vBottom + y) * bitmapWidth].B);
                            if (r >= 240 && g >= 240 && b >= 220)
                            {
                                outerBottom = vBottom + y + 1;
                                break;
                            }
                        }
                        // find outer right
                        int outerRight = -1;
                        for (int x = 29; x >= 0; x--)
                        {
                            int r = (int)(colors[(hRight + x) + (vTop + h / 2) * bitmapWidth].R);
                            int g = (int)(colors[(hRight + x) + (vTop + h / 2) * bitmapWidth].G);
                            int b = (int)(colors[(hRight + x) + (vTop + h / 2) * bitmapWidth].B);
                            if (r >= 240 && g >= 240 && b >= 220)
                            {
                                outerRight = hRight + x + 1;
                                break;
                            }
                        }

                        UnityEngine.Debug.LogError(outerLeft + "," + outerTop + " (" + (outerBottom - outerTop) + "x" + (outerRight - outerLeft) + ")");
                        if (outerRight == -1 || outerLeft == -1 || outerTop == -1 || outerBottom == -1)
                        {
                            return(-1, -1, -1, -1);
                        }

                        int padding = UnityEngine.Mathf.CeilToInt(((float)(outerRight - outerLeft)) * 0.090f);

                        int realLeft   = outerLeft + padding;
                        int realRight  = outerRight - (padding - 1);
                        int realTop    = outerTop + padding;
                        int realBottom = outerBottom - (padding - 1);

                        return(realLeft, realTop, realRight - realLeft, realBottom - realTop);
                    }
                }
            }
        }

        return(-1, -1, -1, -1);
    }
示例#6
0
    public void FromBytes(byte[] bytes)
    {
        using (MemoryStream stream = new MemoryStream(bytes))
        {
            BinaryReader reader  = new BinaryReader(stream);
            byte         version = reader.ReadByte();
            if (version == 0x00)
            {
                var t = (DesignPattern.TypeEnum)reader.ReadByte();
                if (this._Type == DesignPattern.TypeEnum.SimplePattern && t != DesignPattern.TypeEnum.SimplePattern)
                {
                    throw new ArgumentException("Simple design spot can't hold pro design.", "project");
                }
                if (this._Type != DesignPattern.TypeEnum.SimplePattern && t == DesignPattern.TypeEnum.SimplePattern)
                {
                    throw new ArgumentException("Pro design spot can't hold simple design.", "project");
                }
                this._Type = t;
                Quantizer  = Quantizers[reader.ReadByte()];
                ColorCache = ColorCaches[reader.ReadByte()];

                var info = DesignPatternInformation.Types[this._Type];
                this.SubPatterns = new List <SubPattern>();
                for (int i = 0; i < info.Parts.Count; i++)
                {
                    var subPattern = new SubPattern(this, info.Parts[i], true);
                    this.SubPatterns.Add(subPattern);

                    int layerCount = reader.ReadByte();
                    for (int j = 0; j < layerCount; j++)
                    {
                        var layerType = reader.ReadByte();
                        if (layerType == 0x01)
                        {
                            int    objectX      = reader.ReadInt32();
                            int    objectY      = reader.ReadInt32();
                            int    objectW      = reader.ReadInt32();
                            int    objectH      = reader.ReadInt32();
                            byte   crop         = reader.ReadByte();
                            byte   resampling   = reader.ReadByte();
                            int    nameLength   = reader.ReadInt32();
                            string name         = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(nameLength));
                            int    bitmapWidth  = reader.ReadInt32();
                            int    bitmapHeight = reader.ReadInt32();
                            byte[] bitmapPixels = reader.ReadBytes(bitmapWidth * bitmapHeight * 4);
                            var    bitmap       = new System.Drawing.Bitmap(bitmapWidth, bitmapHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                            bitmap.FromBytes(bitmapPixels);
                            SmartObjectLayer layer = new SmartObjectLayer(subPattern, name, bitmap, objectX, objectY, objectW, objectH);
                            subPattern.Layers.Add(layer);
                            layer.Crop      = SmartObjectLayer.Crops[crop];
                            layer.Resampler = SmartObjectLayer.Resamplers[resampling];
                            layer.Colors    = new UnityEngine.Color[layer.Width * layer.Height];
                            layer.UpdateColors();
                            layer.UpdateTexture();
                        }
                        else if (layerType == 0x00)
                        {
                            int         nameLength = reader.ReadInt32();
                            string      name       = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(nameLength));
                            RasterLayer layer      = new RasterLayer(subPattern, name);
                            layer.Colors = new UnityEngine.Color[layer.Width * layer.Height];
                            for (int y = 0; y < layer.Height; y++)
                            {
                                for (int x = 0; x < layer.Width; x++)
                                {
                                    layer.Colors[x + y * layer.Width] = new UnityEngine.Color(reader.ReadByte() / 255f, reader.ReadByte() / 255f, reader.ReadByte() / 255f, reader.ReadByte() / 255f);
                                }
                            }
                            layer.UpdateTexture();
                            subPattern.Layers.Add(layer);
                        }
                    }
                }
            }
        }
        _CurrentSubPattern = 0;
        Editor.SetSize(CurrentSubPattern.Width, CurrentSubPattern.Height);
        Editor.LayersChanged();
        Editor.SubPatternChanged(CurrentSubPattern.Part);
        Editor.SetType(this._Type);
        Editor.Show(null, null, null);
        Editor.OnImageUpdated();
        Editor.Tools.HistoryChanged(CurrentSubPattern.History);
        for (int i = 0; i < SubPatterns.Count; i++)
        {
            SubPatterns[i].UpdateImage(false);
        }
        this.RegeneratePreview();
    }
示例#7
0
 public void SetType(DesignPattern.TypeEnum type)
 {
     this.Type = type;
 }
 public void SelectCloth(DesignPattern.TypeEnum type)
 {
     ConfirmCallback?.Invoke(type);
 }
示例#9
0
    public Pattern(PatternEditor editor, byte[] bytes)
    {
        try
        {
            Editor = editor;

            using (MemoryStream stream = new MemoryStream(bytes))
            {
                BinaryReader reader  = new BinaryReader(stream);
                byte         version = reader.ReadByte();
                var          t       = (DesignPattern.TypeEnum)reader.ReadByte();
                if (!Editor.IsPro && t != DesignPattern.TypeEnum.SimplePattern)
                {
                    throw new ArgumentException("Simple design spot can't hold pro design.", "project");
                }
                if (Editor.IsPro && t == DesignPattern.TypeEnum.SimplePattern)
                {
                    throw new ArgumentException("Pro design spot can't hold simple design.", "project");
                }
                this._Type = t;
                Quantizer  = Quantizers[reader.ReadByte()];
                ColorCache = ColorCaches[reader.ReadByte()];

                var info = DesignPatternInformation.Types[this._Type];
                this.SubPatterns = new List <SubPattern>();
                for (int i = 0; i < info.Parts.Count; i++)
                {
                    var subPattern = new SubPattern(this, info.Parts[i], true);
                    this.SubPatterns.Add(subPattern);

                    int layerCount = reader.ReadByte();
                    for (int j = 0; j < layerCount; j++)
                    {
                        var layerType = reader.ReadByte();
                        if (layerType == 0x01)
                        {
                            int    objectX      = reader.ReadInt32();
                            int    objectY      = reader.ReadInt32();
                            int    objectW      = reader.ReadInt32();
                            int    objectH      = reader.ReadInt32();
                            byte   crop         = reader.ReadByte();
                            byte   resampling   = reader.ReadByte();
                            int    nameLength   = reader.ReadInt32();
                            string name         = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(nameLength));
                            int    bitmapWidth  = reader.ReadInt32();
                            int    bitmapHeight = reader.ReadInt32();
                            byte[] bitmapPixels = reader.ReadBytes(bitmapWidth * bitmapHeight * 4);
                            var    bitmap       = new TextureBitmap(bitmapWidth, bitmapHeight);
                            int    m            = bitmapWidth * bitmapHeight * bitmap.PixelSize;
                            unsafe
                            {
                                byte *ptr = (byte *)bitmap.Bytes.ToPointer();
                                for (int k = 0; k < m; k++)
                                {
                                    *(ptr + k) = bitmapPixels[k];
                                }
                            }
                            if (version == 0)
                            {
                                bitmap.FlipY();
                            }
                            SmartObjectLayer layer = new SmartObjectLayer(subPattern, name, bitmap, objectX, objectY, objectW, objectH);
                            subPattern.Layers.Add(layer);
                            layer.Crop      = (TextureBitmap.CropMode)crop;
                            layer.Resampler = (ResamplingFilters)resampling;
                            layer.Bitmap    = bitmap;
                            layer.UpdateColors();
                            layer.UpdateTexture();
                        }
                        else if (layerType == 0x00)
                        {
                            int         nameLength = reader.ReadInt32();
                            string      name       = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(nameLength));
                            RasterLayer layer      = new RasterLayer(subPattern, name);

                            int    m            = layer.Width * layer.Height * layer.Texture.PixelSize;
                            byte[] bitmapPixels = reader.ReadBytes(m);
                            layer.Texture = new TextureBitmap(layer.Width, layer.Height);

                            unsafe
                            {
                                byte *ptr = (byte *)layer.Texture.Bytes.ToPointer();
                                for (int k = 0; k < m; k++)
                                {
                                    *(ptr + k) = bitmapPixels[k];
                                }
                            }
                            if (version == 0)
                            {
                                layer.Texture.FlipY();
                            }

                            layer.UpdateTexture();
                            subPattern.Layers.Add(layer);
                        }
                    }
                }
            }
            GC.Collect();
            _CurrentSubPattern = 0;

            Logger.Log(Logger.Level.INFO, "[PatternEditor/Pattern] Creating new pattern");
            StartPreviewThread();
            Logger.Log(Logger.Level.DEBUG, "[PatternEditor/Pattern] Pattern type: " + _Type.ToString());
            Bitmap = new TextureBitmap(Width, Height);
            Logger.Log(Logger.Level.DEBUG, "[PatternEditor/Pattern] Created TextureBitmap " + Width + "x" + Height);
            Bitmap.Clear();
            PreviewBitmap = new TextureBitmap(Width, Height);
            Logger.Log(Logger.Level.DEBUG, "[PatternEditor/Pattern] Created preview TextureBitmap " + Width + "x" + Height);
            PreviewBitmap.Clear();
            PreviewSprite = UnityEngine.Sprite.Create(PreviewBitmap.Texture, new UnityEngine.Rect(0, 0, PreviewBitmap.Width, PreviewBitmap.Height), new UnityEngine.Vector2(0.5f, 0.5f));
            Logger.Log(Logger.Level.DEBUG, "[PatternEditor/Pattern] Created preview sprite");

            UpscaledPreviewBitmap = new TextureBitmap(Width * 4, Height * 4);
            Logger.Log(Logger.Level.DEBUG, "[PatternEditor/Pattern] Created upscaled preview TextureBitmap " + (Width * 4) + "x" + (Height * 4));
            UpscaledPreviewBitmap.Clear();

            Info = DesignPatternInformation.Types[this._Type];
            Logger.Log(Logger.Level.DEBUG, "[PatternEditor/Pattern] Pattern information obtained.");
        }
        catch (System.Exception e)
        {
            Logger.Log(Logger.Level.ERROR, "[PatternEditor/Pattern] Error while creating pattern: " + e.ToString());
            this.Dispose();
            throw e;
        }
    }
示例#10
0
    public static (int, int, int, int) FindPattern(System.Drawing.Bitmap bitmap, DesignPattern.TypeEnum type)
    {
        bool isPro  = type != DesignPattern.TypeEnum.SimplePattern;
        var  colors = bitmap.ToColors();

        bool[] bw  = new bool[bitmap.Width * bitmap.Height];        // true = black
        int    min = 180;
        int    max = 235;

        for (int x = 0; x < bitmap.Width; x++)
        {
            for (int y = 0; y < bitmap.Height; y++)
            {
                float h;
                float s;
                float v;
                int   r = (int)(colors[x + y * bitmap.Width].r * 255f);
                int   g = (int)(colors[x + y * bitmap.Width].g * 255f);
                int   b = (int)(colors[x + y * bitmap.Width].b * 255f);
                r = r * (r >= min && r <= max ? 0 : 1);
                g = g * (g >= min && g <= max ? 0 : 1);
                b = b * (b >= min && b <= max ? 0 : 1);
                bw[x + y * bitmap.Width] = r == 0 && g == 0;
            }
        }

        int widthThreshold = 5;
        int minWidth       = 2;
        List <(int, int, int)> horizontalLines = new List <(int, int, int)>();
        List <(int, int, int)> verticalLines   = new List <(int, int, int)>();

        for (int y = 0; y < bitmap.Height; y++)
        {
            int  currentDashWidth  = 0;
            int  currentSpaceWidth = 0;
            int  dashes            = 0;
            int  dashWidth         = 0;
            int  start             = 0;
            bool black             = false;

            for (int x = 0; x < bitmap.Width; x++)
            {
                int idx = x + y * bitmap.Width;
                if (bw[idx])
                {
                    if (!black)
                    {
                        currentDashWidth = 0;
                        if (dashes > 0 && currentSpaceWidth > dashWidth)
                        {
                            dashes = 0; dashWidth = 0;
                        }
                        if (dashes == 0)
                        {
                            start = x;
                        }
                    }
                    black = true;
                    currentDashWidth++;
                }
                else
                {
                    if (dashes == 0 && currentDashWidth >= minWidth)
                    {
                        dashWidth = currentDashWidth;
                    }

                    if (dashWidth > 0)
                    {
                        if (black)
                        {
                            currentSpaceWidth = 0;
                            if (currentDashWidth < dashWidth - widthThreshold || currentDashWidth < minWidth || currentDashWidth > dashWidth + widthThreshold)
                            {
                                dashes = 0; dashWidth = 0;
                            }
                            else
                            {
                                dashes++;
                                if (dashes >= 14)
                                {
                                    horizontalLines.Add((start, y, x));
                                    dashWidth = 0;
                                    dashes    = 0;
                                    continue;
                                }
                            }
                        }
                        if (dashes > 0)
                        {
                            currentSpaceWidth++;
                        }
                    }
                    black = false;
                }
            }
        }

        for (int x = 0; x < bitmap.Width; x++)
        {
            int  currentDashWidth  = 0;
            int  currentSpaceWidth = 0;
            int  dashes            = 0;
            int  dashWidth         = 0;
            int  start             = 0;
            bool black             = false;

            for (int y = 0; y < bitmap.Height; y++)
            {
                int idx = x + y * bitmap.Width;
                if (bw[idx])
                {
                    if (!black)
                    {
                        currentDashWidth = 0;
                        if (dashes > 0 && currentSpaceWidth > dashWidth)
                        {
                            dashes = 0; dashWidth = 0;
                        }
                        if (dashes == 0)
                        {
                            start = y;
                        }
                    }
                    black = true;
                    currentDashWidth++;
                }
                else
                {
                    if (dashes == 0 && currentDashWidth >= minWidth)
                    {
                        dashWidth = currentDashWidth;
                    }

                    if (dashWidth > 0)
                    {
                        if (black)
                        {
                            currentSpaceWidth = 0;
                            if (currentDashWidth < dashWidth - widthThreshold || currentDashWidth < minWidth || currentDashWidth > dashWidth + widthThreshold)
                            {
                                dashes = 0; dashWidth = 0;
                            }
                            else
                            {
                                dashes++;
                                if (dashes >= 14)
                                {
                                    verticalLines.Add((x, start, y));
                                    dashWidth = 0;
                                    dashes    = 0;
                                    continue;
                                }
                            }
                        }
                        if (dashes > 0)
                        {
                            currentSpaceWidth++;
                        }
                    }
                    black = false;
                }
            }
        }

        UnityEngine.Debug.Log("VERTICAL: " + verticalLines.Count);
        UnityEngine.Debug.Log("HORIZONTAL: " + horizontalLines.Count);
        int sizeThreshold = 10;

        // find pairing horizontal lines
        List <List <int> > horizontalGroups = new List <List <int> >();
        List <int>         foundHorizontal  = new List <int>();

        for (int i = 0; i < horizontalLines.Count - 1; i++)
        {
            if (!foundHorizontal.Contains(i))
            {
                List <int> group = new List <int>();
                group.Add(i);
                for (int j = i + 1; j < horizontalLines.Count; j++)
                {
                    if (UnityEngine.Mathf.Abs(horizontalLines[i].Item1 - horizontalLines[j].Item1) < sizeThreshold &&
                        UnityEngine.Mathf.Abs(horizontalLines[i].Item3 - horizontalLines[j].Item3) < sizeThreshold)
                    {
                        group.Add(j);
                        foundHorizontal.Add(j);
                    }
                }
                horizontalGroups.Add(group);
            }
        }

        // find pairing vertical lines
        List <List <int> > verticalGroups = new List <List <int> >();
        List <int>         foundVertical  = new List <int>();

        for (int i = 0; i < verticalLines.Count - 1; i++)
        {
            if (!foundVertical.Contains(i))
            {
                List <int> group = new List <int>();
                group.Add(i);
                for (int j = i + 1; j < verticalLines.Count; j++)
                {
                    if (UnityEngine.Mathf.Abs(verticalLines[i].Item2 - verticalLines[j].Item2) < sizeThreshold &&
                        UnityEngine.Mathf.Abs(verticalLines[i].Item3 - verticalLines[j].Item3) < sizeThreshold)
                    {
                        group.Add(j);
                        foundVertical.Add(j);
                    }
                }
                verticalGroups.Add(group);
            }
        }
        UnityEngine.Debug.Log("VERTICAL: " + verticalGroups.Count);
        UnityEngine.Debug.Log("HORIZONTAL: " + horizontalGroups.Count);

        (int, int)whiteR = (235, 255);
        (int, int)whiteG = (235, 255);
        (int, int)whiteB = (200, 255);
        List <(int, int, int, int, bool[])> rects = new List <(int, int, int, int, bool[])>();

        for (int i = 0; i < verticalGroups.Count; i++)
        {
            var vTop    = verticalLines[verticalGroups[i][0]].Item2;
            var vBottom = verticalLines[verticalGroups[i][0]].Item3;
            var vX      = verticalLines[verticalGroups[i][0]].Item1;

            for (int j = 0; j < horizontalGroups.Count; j++)
            {
                var hLeft  = horizontalLines[horizontalGroups[j][0]].Item1;
                var hRight = horizontalLines[horizontalGroups[j][0]].Item3;
                var hY     = horizontalLines[horizontalGroups[j][0]].Item2;

                UnityEngine.Debug.Log(vTop + "-" + vBottom + "(" + vX + ") " + hLeft + "-" + hRight + "(" + hY + ")");
                if ((UnityEngine.Mathf.Abs(hY - vTop) < sizeThreshold ||
                     UnityEngine.Mathf.Abs(hY - vBottom) < sizeThreshold) &&
                    (UnityEngine.Mathf.Abs(vX - hLeft) < sizeThreshold ||
                     UnityEngine.Mathf.Abs(vX - hRight) < sizeThreshold))
                {
                    // its a rect!
                    int    w    = hRight - hLeft;
                    int    h    = vBottom - vTop;
                    bool[] rect = new bool[w * h];

                    // find outer top
                    int outerTop = -1;
                    for (int y = -30; y < 0; y++)
                    {
                        int r = (int)(colors[(hLeft + w / 2) + (vTop + y) * bitmap.Width].r * 255f);
                        int g = (int)(colors[(hLeft + w / 2) + (vTop + y) * bitmap.Width].g * 255f);
                        int b = (int)(colors[(hLeft + w / 2) + (vTop + y) * bitmap.Width].b * 255f);
                        if (r >= 240 && g >= 240 && b >= 220)
                        {
                            outerTop = vTop + y;
                            break;
                        }
                    }
                    // find outer left
                    int outerLeft = -1;
                    for (int x = -30; x < 0; x++)
                    {
                        int r = (int)(colors[(hLeft + x) + (vTop + h / 2) * bitmap.Width].r * 255f);
                        int g = (int)(colors[(hLeft + x) + (vTop + h / 2) * bitmap.Width].g * 255f);
                        int b = (int)(colors[(hLeft + x) + (vTop + h / 2) * bitmap.Width].b * 255f);
                        if (r >= 240 && g >= 240 && b >= 220)
                        {
                            outerLeft = hLeft + x;
                            break;
                        }
                    }
                    // find outer bottom
                    int outerBottom = -1;
                    for (int y = 29; y >= 0; y--)
                    {
                        int r = (int)(colors[(hLeft + w / 2) + (vBottom + y) * bitmap.Width].r * 255f);
                        int g = (int)(colors[(hLeft + w / 2) + (vBottom + y) * bitmap.Width].g * 255f);
                        int b = (int)(colors[(hLeft + w / 2) + (vBottom + y) * bitmap.Width].b * 255f);
                        if (r >= 240 && g >= 240 && b >= 220)
                        {
                            outerBottom = vBottom + y + 1;
                            break;
                        }
                    }
                    // find outer right
                    int outerRight = -1;
                    for (int x = 29; x >= 0; x--)
                    {
                        int r = (int)(colors[(hRight + x) + (vTop + h / 2) * bitmap.Width].r * 255f);
                        int g = (int)(colors[(hRight + x) + (vTop + h / 2) * bitmap.Width].g * 255f);
                        int b = (int)(colors[(hRight + x) + (vTop + h / 2) * bitmap.Width].b * 255f);
                        if (r >= 240 && g >= 240 && b >= 220)
                        {
                            outerRight = hRight + x + 1;
                            break;
                        }
                    }

                    UnityEngine.Debug.LogError(outerLeft + "," + outerTop + " (" + (outerBottom - outerTop) + "x" + (outerRight - outerLeft) + ")");
                    if (outerRight == -1 || outerLeft == -1 || outerTop == -1 || outerBottom == -1)
                    {
                        return(-1, -1, -1, -1);
                    }

                    int padding = UnityEngine.Mathf.CeilToInt(((float)(outerRight - outerLeft)) * 0.090f);

                    /*
                     * for (int x = 0; x < w; x++)
                     * {
                     *      for (int y = 0; y < h; y++)
                     *      {
                     *              int r = (int) (colors[(hLeft + x) + (vTop + y) * bitmap.Width].r * 255f);
                     *              int g = (int) (colors[(hLeft + x) + (vTop + y) * bitmap.Width].g * 255f);
                     *              int b = (int) (colors[(hLeft + x) + (vTop + y) * bitmap.Width].b * 255f);
                     *              rect[x + y * w] = !(r >= whiteR.Item1 && r <= whiteR.Item2 && g >= whiteG.Item1 && g <= whiteG.Item2 && b >= whiteB.Item1 && b <= whiteB.Item2);
                     *      }
                     * }
                     *
                     */
                    int realLeft   = outerLeft + padding;
                    int realRight  = outerRight - (padding - 1);
                    int realTop    = outerTop + padding;
                    int realBottom = outerBottom - (padding - 1);

                    return(realLeft, realTop, realRight - realLeft, realBottom - realTop);

                    /*
                     * int nonWhiteThreshold = (vBottom - vTop) / 5;
                     * for (int x = 0; x < w; x++)
                     * {
                     *      int nonWhite = 0;
                     *      for (int y = 0; y < h; y++)
                     *      {
                     *              if (rect[x + y * w]) nonWhite++;
                     *      }
                     *      if (nonWhite > nonWhiteThreshold)
                     *      {
                     *              realLeft = hLeft + x;
                     *              break;
                     *      }
                     * }
                     *
                     * for (int x = w - 1; x >= 0; x--)
                     * {
                     *      int nonWhite = 0;
                     *      for (int y = 0; y < h; y++)
                     *      {
                     *              if (rect[x + y * w]) nonWhite++;
                     *      }
                     *      if (nonWhite > nonWhiteThreshold)
                     *      {
                     *              realRight = hLeft + x + 2;
                     *              break;
                     *      }
                     * }
                     *
                     * nonWhiteThreshold = (vBottom - vTop) / 8;
                     * for (int y = 0; y < h; y++)
                     * {
                     *      int nonWhite = 0;
                     *      for (int x = 0; x < w; x++)
                     *      {
                     *              if (rect[x + y * w]) nonWhite++;
                     *      }
                     *      if (nonWhite > nonWhiteThreshold)
                     *      {
                     *              realTop = vTop + y;
                     *              break;
                     *      }
                     * }
                     *
                     * realBottom = realTop + (realRight - realLeft);*/

                    /*UnityEngine.Debug.Log(realLeft + "," + realTop + "," + realRight + "," + realBottom);
                     * rects.Add((realLeft, realTop, realRight - realLeft, realBottom - realTop, rect));
                     *
                     * break;*/
                }
            }
        }

        /*
         * if (rects.Count > 0)
         * {
         *      var w = isPro ? 64 : 32;
         *      var h = w;
         *
         *      float center = UnityEngine.Mathf.Ceil((float) rects[0].Item3) / ((float) w);
         *      var result = new System.Drawing.Bitmap((int) (rects[0].Item3), (int) (rects[0].Item4), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
         *      using (Graphics graphics = Graphics.FromImage(result))
         *      {
         *              graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
         *              graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
         *              graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
         *              if (isPro)
         *              {
         *                      graphics.DrawImage(bitmap, new Rectangle(0, 0, rects[0].Item3, rects[0].Item4), new Rectangle(rects[0].Item1, rects[0].Item2, rects[0].Item3, rects[0].Item4), GraphicsUnit.Pixel);
         *              }
         *              else
         *              {
         *                      graphics.DrawImage(bitmap, new Rectangle(0, 0, rects[0].Item3, rects[0].Item4), new Rectangle(rects[0].Item1, rects[0].Item2, rects[0].Item3, rects[0].Item4), GraphicsUnit.Pixel);
         *              }
         *      }
         *
         *      result.Save("result.png");
         *      var sampler = new NearestNeighbourSampling();
         *      var r = sampler.Resample(result, w, h);
         *      result.Dispose();
         *      result = r;
         *      foreach (var part in DesignPatternInformation.Types[type].Parts)
         *              for (var y = 0; y < part.Height; y++)
         *                      for (var x = 0; x < part.Width; x++)
         *                              if (part.Visible[x + y * part.Width] == '0')
         *                                      result.SetPixel(part.X + x, part.Y + y, Color.FromArgb(0, 0, 0, 0));
         *
         *      return result;
         * }*/
        return(-1, -1, -1, -1);
    }