Esempio n. 1
0
        public static unsafe byte[] GetMaskFromImage(Bitmap bmp)
        {
            int          stride       = ((bmp.Width + 7) / 8) * 8;
            FastBitArray arr          = new FastBitArray(stride * bmp.Height);
            int          strideFactor = 0;

            var data      = bmp.BasicLockBits();
            int bmpStride = data.Stride / 4;

            uint *ptrInt = (uint *)data.Scan0;

            for (int y = 0; y < bmp.Height; y++)
            {
                for (int x = 0; x < bmp.Width; x++)
                {
                    if (*(ptrInt + x + (y * bmpStride)) == 0xFFFFFFFFu)
                    {
                        arr.SetTrueReverse(x + strideFactor);
                    }
                }

                strideFactor += stride;
            }

            bmp.UnlockBits(data);

            return(arr.ToByteArray());
        }
Esempio n. 2
0
        public static unsafe FastBitArray GetMaskForBitmap(Bitmap bmp, AssetSprite spr, ref Rect maskbbox, FastBitArray existingMask = null)
        {
            int          stride = ((spr.Width + 7) / 8) * 8;
            FastBitArray res    = existingMask ?? new FastBitArray(stride * spr.Height);

            Rect bbox = GetBBoxForBitmap(bmp, spr);

            var info = spr.CollisionMask;
            int sprLeft, sprTop, sprRight, sprBottom;

            // Word of note: There's a lot of copies of nearly the same code here. This is to reduce the number of conditions.

            int strideFactor = bbox.Top * stride;

            switch (info.Type)
            {
            case MaskType.Rectangle:
            case MaskType.RectangleWithRotation:
                if (maskbbox != null)
                {
                    for (int y = bbox.Top; y <= bbox.Bottom; y++)
                    {
                        for (int x = bbox.Left; x <= bbox.Right; x++)
                        {
                            res.SetTrueReverse(x + strideFactor);
                            if (x < maskbbox.Left)
                            {
                                maskbbox.Left = x;
                            }
                            if (y < maskbbox.Top)
                            {
                                maskbbox.Top = y;
                            }
                            if (x > maskbbox.Right)
                            {
                                maskbbox.Right = x;
                            }
                            if (y > maskbbox.Bottom)
                            {
                                maskbbox.Bottom = y;
                            }
                        }

                        strideFactor += stride;
                    }
                }
                else
                {
                    for (int y = bbox.Top; y <= bbox.Bottom; y++)
                    {
                        for (int x = bbox.Left; x <= bbox.Right; x++)
                        {
                            res.SetTrueReverse(x + strideFactor);
                        }

                        strideFactor += stride;
                    }
                }
                break;

            case MaskType.Precise:
            case MaskType.PrecisePerFrame:
                int tolerance = info.AlphaTolerance ?? 0;
                var data      = bmp.BasicLockBits();
                unsafe
                {
                    byte *ptr = (byte *)data.Scan0;
                    if (maskbbox != null)
                    {
                        for (int y = bbox.Top; y <= bbox.Bottom; y++)
                        {
                            for (int x = bbox.Left; x <= bbox.Right; x++)
                            {
                                if (*(ptr + (x * 4) + (y * data.Stride) + 3) > tolerance)
                                {
                                    res.SetTrueReverse(x + strideFactor);
                                    if (x < maskbbox.Left)
                                    {
                                        maskbbox.Left = x;
                                    }
                                    if (y < maskbbox.Top)
                                    {
                                        maskbbox.Top = y;
                                    }
                                    if (x > maskbbox.Right)
                                    {
                                        maskbbox.Right = x;
                                    }
                                    if (y > maskbbox.Bottom)
                                    {
                                        maskbbox.Bottom = y;
                                    }
                                }
                            }

                            strideFactor += stride;
                        }
                    }
                    else
                    {
                        for (int y = bbox.Top; y <= bbox.Bottom; y++)
                        {
                            for (int x = bbox.Left; x <= bbox.Right; x++)
                            {
                                if (*(ptr + (x * 4) + (y * data.Stride) + 3) > tolerance)
                                {
                                    res.SetTrueReverse(x + strideFactor);
                                }
                            }

                            strideFactor += stride;
                        }
                    }
                }
                bmp.UnlockBits(data);
                break;

            case MaskType.Diamond:
            {
                if (info.Mode == MaskMode.FullImage)
                {
                    sprLeft   = 0;
                    sprTop    = 0;
                    sprRight  = spr.Width - 1;
                    sprBottom = spr.Height - 1;
                }
                else
                {
                    sprLeft   = (int)info.Left;
                    sprTop    = (int)info.Top;
                    sprRight  = (int)info.Right;
                    sprBottom = (int)info.Bottom;
                }

                float centerX = (sprLeft + sprRight) / 2;
                float centerY = (sprTop + sprBottom) / 2;
                float radiusX = centerX - sprLeft + 0.5f;
                float radiusY = centerY - sprTop + 0.5f;

                if (radiusX <= 0 || radiusY <= 0)
                {
                    break;
                }

                if (maskbbox != null)
                {
                    for (int y = bbox.Top; y <= bbox.Bottom; y++)
                    {
                        for (int x = bbox.Left; x <= bbox.Right; x++)
                        {
                            float normalX = (x - centerX) / radiusX;
                            float normalY = (y - centerY) / radiusY;
                            if (Math.Abs(normalX) + Math.Abs(normalY) <= 1f)
                            {
                                res.SetTrueReverse(x + strideFactor);
                                if (x < maskbbox.Left)
                                {
                                    maskbbox.Left = x;
                                }
                                if (y < maskbbox.Top)
                                {
                                    maskbbox.Top = y;
                                }
                                if (x > maskbbox.Right)
                                {
                                    maskbbox.Right = x;
                                }
                                if (y > maskbbox.Bottom)
                                {
                                    maskbbox.Bottom = y;
                                }
                            }
                        }

                        strideFactor += stride;
                    }
                }
                else
                {
                    for (int y = bbox.Top; y <= bbox.Bottom; y++)
                    {
                        for (int x = bbox.Left; x <= bbox.Right; x++)
                        {
                            float normalX = (x - centerX) / radiusX;
                            float normalY = (y - centerY) / radiusY;
                            if (Math.Abs(normalX) + Math.Abs(normalY) <= 1f)
                            {
                                res.SetTrueReverse(x + strideFactor);
                            }
                        }

                        strideFactor += stride;
                    }
                }
                break;
            }

            case MaskType.Ellipse:
            {
                if (info.Mode == MaskMode.FullImage)
                {
                    sprLeft   = 0;
                    sprTop    = 0;
                    sprRight  = spr.Width - 1;
                    sprBottom = spr.Height - 1;
                }
                else
                {
                    sprLeft   = (int)info.Left;
                    sprTop    = (int)info.Top;
                    sprRight  = (int)info.Right;
                    sprBottom = (int)info.Bottom;
                }

                float centerX = (sprLeft + sprRight) / 2;
                float centerY = (sprTop + sprBottom) / 2;
                float radiusX = centerX - sprLeft + 0.5f;
                float radiusY = centerY - sprTop + 0.5f;

                if (radiusX <= 0 || radiusY <= 0)
                {
                    break;
                }

                if (maskbbox != null)
                {
                    for (int y = bbox.Top; y <= bbox.Bottom; y++)
                    {
                        for (int x = bbox.Left; x <= bbox.Right; x++)
                        {
                            float normalX = (x - centerX) / radiusX;
                            float normalY = (y - centerY) / radiusY;
                            if (Math.Pow(normalX, 2.0d) + Math.Pow(normalY, 2.0d) <= 1.0d)
                            {
                                res.SetTrueReverse(x + strideFactor);
                                if (x < maskbbox.Left)
                                {
                                    maskbbox.Left = x;
                                }
                                if (y < maskbbox.Top)
                                {
                                    maskbbox.Top = y;
                                }
                                if (x > maskbbox.Right)
                                {
                                    maskbbox.Right = x;
                                }
                                if (y > maskbbox.Bottom)
                                {
                                    maskbbox.Bottom = y;
                                }
                            }
                        }

                        strideFactor += stride;
                    }
                }
                else
                {
                    for (int y = bbox.Top; y <= bbox.Bottom; y++)
                    {
                        for (int x = bbox.Left; x <= bbox.Right; x++)
                        {
                            float normalX = (x - centerX) / radiusX;
                            float normalY = (y - centerY) / radiusY;
                            if (Math.Pow(normalX, 2.0d) + Math.Pow(normalY, 2.0d) <= 1.0d)
                            {
                                res.SetTrueReverse(x + strideFactor);
                            }
                        }

                        strideFactor += stride;
                    }
                }
                break;
            }
            }

            return(res);
        }