public static int CountColors(this Image image)
        {
            if (image == null)
            {
                throw new ArgumentNullException("image");
            }

            HashSet<int> colors = new HashSet<int>();

            FastBitmap fastBitmap = new FastBitmap(image);
            fastBitmap.Lock();

            // Loop through all the pixels of the image
            // and add the colors to the HashSet - duplicates
            // are automatically ignored by that collection type
            for (int x = 0; x < image.Width; x++)
            {
                for (int y = 0; y < image.Height; y++)
                {
                    // We use ToArgb because Colors are compared on more than their ARGB values - see Color class documentation on MSDN
                    colors.Add(fastBitmap.GetPixel(x, y).ToArgb());
                }
            }

            fastBitmap.Unlock();

            return colors.Count;
        }
示例#2
0
        public void TestFastBitmapCreation()
        {
            Bitmap bitmap = new Bitmap(64, 64);
            FastBitmap fastBitmap = new FastBitmap(bitmap);
            fastBitmap.Lock();
            fastBitmap.Unlock();

            // Try creating a FastBitmap with different 32bpp depths
            try
            {
                // ReSharper disable once ObjectCreationAsStatement
                new FastBitmap(new Bitmap(1, 1, PixelFormat.Format32bppArgb));
                // ReSharper disable once ObjectCreationAsStatement
                new FastBitmap(new Bitmap(1, 1, PixelFormat.Format32bppPArgb));
                // ReSharper disable once ObjectCreationAsStatement
                new FastBitmap(new Bitmap(1, 1, PixelFormat.Format32bppRgb));
            }
            catch (ArgumentException)
            {
                Assert.Fail("The FastBitmap should accept any type of 32bpp pixel format bitmap");
            }

            // Try creating a FastBitmap with a bitmap of a bit depth different from 32bpp
            Bitmap invalidBitmap = new Bitmap(64, 64, PixelFormat.Format4bppIndexed);

            // ReSharper disable once ObjectCreationAsStatement
            new FastBitmap(invalidBitmap);
        }
        /// <summary>
        /// Locks this bitmap into memory and returns a FastBitmap that can be used to manipulate its pixels
        /// </summary>
        /// <param name="bitmap">The bitmap to lock</param>
        /// <returns>A locked FastBitmap</returns>
        public static FastBitmap FastLock(this Bitmap bitmap)
        {
            var fast = new FastBitmap(bitmap);

            fast.Lock();

            return(fast);
        }
        //tiles = 16 means 16 x 16 atlas
        public List<Bitmap> Atlas2dInto1d(Bitmap atlas2d, int tiles, int atlassizezlimit)
        {
            FastBitmap orig = new FastBitmap();
            orig.bmp = atlas2d;

            int tilesize = atlas2d.Width / tiles;

            int atlasescount = Math.Max(1, (tiles * tiles * tilesize) / atlassizezlimit);
            List<Bitmap> atlases = new List<Bitmap>();

            orig.Lock();

            //256 x 1
            FastBitmap atlas1d = null;

            for (int i = 0; i < tiles * tiles; i++)
            {
                int x = i % tiles;
                int y = i / tiles;
                int tilesinatlas = (tiles * tiles / atlasescount);
                if (i % tilesinatlas == 0)
                {
                    if (atlas1d != null)
                    {
                        atlas1d.Unlock();
                        atlases.Add(atlas1d.bmp);
                    }
                    atlas1d = new FastBitmap();
                    atlas1d.bmp = new Bitmap(tilesize, atlassizezlimit);
                    atlas1d.Lock();
                }
                for (int xx = 0; xx < tilesize; xx++)
                {
                    for (int yy = 0; yy < tilesize; yy++)
                    {
                        int c = orig.GetPixel(x * tilesize + xx, y * tilesize + yy);
                        atlas1d.SetPixel(xx, (i % tilesinatlas) * tilesize + yy, c);
                    }
                }
            }
            atlas1d.Unlock();
            atlases.Add(atlas1d.bmp);
            orig.Unlock();
            return atlases;
        }
示例#5
0
        public void TestSequentialFastBitmapLocking()
        {
            Bitmap bitmap = new Bitmap(64, 64);
            FastBitmap fastBitmap = new FastBitmap(bitmap);

            Assert.IsFalse(fastBitmap.Locked, "Immediately after creation, the FastBitmap.Locked property must be false");

            fastBitmap.Lock();

            Assert.IsTrue(fastBitmap.Locked, "After a successful call to .Lock(), the .Locked property must be true");

            fastBitmap.Unlock();

            Assert.IsFalse(fastBitmap.Locked, "After a successful call to .Lock(), the .Locked property must be false");

            fastBitmap = new FastBitmap(bitmap);
            fastBitmap.Lock();
            fastBitmap.Unlock();
        }
        public static bool CompareColors(this Image image, Image other)
        {
            if (image == null || other == null)
            {
                throw new ArgumentNullException(image == null ? "image" : "other");
            }

            if (image.Size != other.Size)
            {
                return false;
            }

            FastBitmap fastImage = new FastBitmap(image);
            FastBitmap fastOther = new FastBitmap(other);

            try
            {
                fastImage.Lock();
                fastOther.Lock();

                for (int x = 0; x < image.Width; x++)
                {
                    for (int y = 0; y < image.Height; y++)
                    {
                        // We use ToArgb because Colors are compared on more than their ARGB values - see Color class documentation on MSDN
                        if (fastImage.GetPixel(x, y).ToArgb() != fastOther.GetPixel(x, y).ToArgb())
                        {
                            return false;
                        }
                    }
                }
            }
            finally
            {
                fastImage.Unlock();
                fastOther.Unlock();
            }

            return true;
        }
        public static Image ReplaceColor(this Image image, Color oldColor, Color newColor)
        {
            if (image == null)
            {
                throw new ArgumentNullException("image");
            }

            Image clone = image.Clone() as Image;

            // If they try to replace a color with itself (sneaky, sneaky!) then just return our cloned image immediately
            if (oldColor.ToArgb() == newColor.ToArgb())
            {
                return clone;
            }

            FastBitmap fastBitmap = new FastBitmap(clone);
            fastBitmap.Lock();

            for (int x = 0; x < image.Width; x++)
            {
                for (int y = 0; y < image.Height; y++)
                {
                    // We use ToArgb because Colors are compared on more than their ARGB values - see Color class documentation on MSDN
                    if (fastBitmap.GetPixel(x, y).ToArgb() == oldColor.ToArgb())
                    {
                        fastBitmap.SetPixel(x, y, newColor);
                    }
                }
            }

            fastBitmap.Unlock();

            return fastBitmap.Image;
        }
示例#8
0
        public void TestFailedSequentialFastBitmapLocking()
        {
            Bitmap bitmap = new Bitmap(64, 64);
            FastBitmap fastBitmap = new FastBitmap(bitmap);
            fastBitmap.Lock();

            fastBitmap = new FastBitmap(bitmap);
            fastBitmap.Lock();
        }
示例#9
0
 /// <summary>
 /// Generates a frame image with a given set of parameters.
 /// The seed is used to randomize the frame, and any call with the same width, height and seed will generate the same image
 /// </summary>
 /// <param name="width">The width of the image to generate</param>
 /// <param name="height">The height of the image to generate</param>
 /// <param name="seed">The seed for the image, used to seed the random number generator that will generate the image contents</param>
 /// <returns>An image with the passed parameters</returns>
 public static Bitmap GenerateRandomBitmap(int width, int height, int seed = -1)
 {
     if (seed == -1)
     {
         seed = _seedRandom.Next();
     }
     Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
     FastBitmap fastBitmap = new FastBitmap(bitmap);
     fastBitmap.Lock();
     // Plot the image with random pixels now
     Random r = new Random(seed);
     for (int y = 0; y < height; y++)
     {
         for (int x = 0; x < width; x++)
         {
             uint pixelColor = (uint)(r.NextDouble() * 0xFFFFFFFF);
             fastBitmap.SetPixel(x, y, pixelColor);
         }
     }
     fastBitmap.Unlock();
     return bitmap;
 }
示例#10
0
        public void TestFastBitmapSetPixelBoundsException()
        {
            Bitmap bitmap = new Bitmap(64, 64);
            FastBitmap fastBitmap = new FastBitmap(bitmap);

            fastBitmap.Lock();

            try
            {
                fastBitmap.SetPixel(-1, -1, 0);
                Assert.Fail("When trying to access a coordinate that is out of bounds via GetPixel, an exception must be thrown");
            }
            catch (ArgumentOutOfRangeException) { }

            try
            {
                fastBitmap.SetPixel(fastBitmap.Width, 0, 0);
                Assert.Fail("When trying to access a coordinate that is out of bounds via GetPixel, an exception must be thrown");
            }
            catch (ArgumentOutOfRangeException) { }

            try
            {
                fastBitmap.SetPixel(0, fastBitmap.Height, 0);
                Assert.Fail("When trying to access a coordinate that is out of bounds via GetPixel, an exception must be thrown");
            }
            catch (ArgumentOutOfRangeException) { }

            fastBitmap.SetPixel(fastBitmap.Width - 1, fastBitmap.Height - 1, 0);
        }
示例#11
0
        public void TestFastBitmapLockingException()
        {
            Bitmap bitmap = new Bitmap(64, 64);
            FastBitmap fastBitmap = new FastBitmap(bitmap);

            fastBitmap.Lock();
            fastBitmap.Lock();
        }
示例#12
0
        public void TestFastBitmapLocker()
        {
            Bitmap bitmap = new Bitmap(64, 64);
            FastBitmap fastBitmap = new FastBitmap(bitmap);

            // Immediate lock and dispose
            fastBitmap.Lock().Dispose();
            Assert.IsFalse(fastBitmap.Locked, "After disposing of the FastBitmapLocker object, the underlying fast bitmap must be unlocked");

            using (var locker = fastBitmap.Lock())
            {
                fastBitmap.SetPixel(0, 0, 0);

                Assert.AreEqual(fastBitmap, locker.FastBitmap, "The fast bitmap referenced in the fast bitmap locker must be the one that had the original Lock() call");
            }

            Assert.IsFalse(fastBitmap.Locked, "After disposing of the FastBitmapLocker object, the underlying fast bitmap must be unlocked");

            // Test the conditional unlocking of the fast bitmap locker by unlocking the fast bitmap before exiting the 'using' block
            using (fastBitmap.Lock())
            {
                fastBitmap.SetPixel(0, 0, 0);
                fastBitmap.Unlock();
            }
        }
示例#13
0
        public void TestSetPixelInt()
        {
            Bitmap bitmap1 = new Bitmap(64, 64);
            Bitmap bitmap2 = new Bitmap(64, 64);

            FastBitmap fastBitmap1 = new FastBitmap(bitmap1);
            fastBitmap1.Lock();

            Random r = new Random();

            for (int y = 0; y < bitmap1.Height; y++)
            {
                for (int x = 0; x < bitmap1.Width; x++)
                {
                    int intColor = r.Next(0xFFFFFF);
                    Color color = Color.FromArgb(intColor);

                    fastBitmap1.SetPixel(x, y, intColor);
                    bitmap2.SetPixel(x, y, color);
                }
            }

            fastBitmap1.Unlock();

            AssertBitmapEquals(bitmap1, bitmap2,
                "Calls to FastBitmap.SetPixel() with an integer overload must be equivalent to calls to Bitmap.SetPixel() with a Color with the same ARGB value as the interger");
        }
示例#14
0
        public void TestGetPixel()
        {
            Bitmap original = GenerateRandomBitmap(64, 64);
            Bitmap copy = original.Clone(new Rectangle(0, 0, 64, 64), original.PixelFormat);

            FastBitmap fastOriginal = new FastBitmap(original);
            fastOriginal.Lock();

            for (int y = 0; y < original.Height; y++)
            {
                for (int x = 0; x < original.Width; x++)
                {
                    Assert.AreEqual(fastOriginal.GetPixel(x, y).ToArgb(), copy.GetPixel(x, y).ToArgb(),
                        "Calls to FastBitmap.GetPixel() must return the same value as returned by Bitmap.GetPixel()");
                }
            }

            fastOriginal.Unlock();
        }
        protected override Image CreateImage()
        {
            // set design-mode properties
            foreach (Layer layer in this.Layers)
                if (layer is ImageLayer)
                {
                    ImageLayer imageLayer = (ImageLayer) layer;
                    imageLayer._site = this.Site;
                    imageLayer._designMode = this.DesignMode;
                }

            // process layers
            foreach (Layer layer in this.Layers)
                layer.Process();

            // for SizeMode = Auto, we need to calculate the output dimensions
            // based on the combination of all layers' dimensions
            int outputWidth, outputHeight;
            if (this.AutoSize)
            {
                Rectangle outputDimensions = Rectangle.Empty;
                foreach (Layer layer in this.Layers)
                {
                    Rectangle? bounds = layer.Bounds;
                    if (bounds != null)
                        outputDimensions = Rectangle.Union(outputDimensions, bounds.Value);
                }
                outputWidth = outputDimensions.Width;
                outputHeight = outputDimensions.Height;
            }
            else
            {
                outputWidth = this.Width.Value;
                outputHeight = this.Height.Value;
            }

            if (outputWidth == 0 && outputHeight == 0)
                return null;

            // create output bitmap and lock data
            FastBitmap output = new FastBitmap(outputWidth, outputHeight, PixelFormat.Format24bppRgb);

            // lock layer bitmaps and output bitmap
            output.Lock();
            foreach (Layer layer in this.Layers)
                layer.Bitmap.Lock();

            // calculate colors of flattened image
            // 1. take offsetx, offsety into consideration
            // 2. calculate alpha of color (alpha, opacity, mask)
            // 3. mix colors of current layer and layer below
            for (int y = 0; y < outputHeight; ++y)
            {
                for (int x = 0; x < outputWidth; ++x)
                {
                    Color c0 = Color.Transparent;
                    foreach (Layer layer in this.Layers)
                    {
                        Color c1 = Color.Transparent;

                        if (x >= layer.X &&
                            x <= layer.X + layer.Bitmap.Width - 1 &&
                            y >= layer.Y &&
                            y <= layer.Y + layer.Bitmap.Height - 1)
                        {
                            c1 = layer.Bitmap[x - layer.X, y - layer.Y];
                        }

                        if (c1.A == 255)
                        {
                            c0 = c1;
                        }
                        else
                        {
                            double a = c1.A / 255.0;
                            double tr = c1.R * a + c0.R * (1.0 - a);
                            double tg = c1.G * a + c0.G * (1.0 - a);
                            double tb = c1.B * a + c0.B * (1.0 - a);
                            tr = Math.Round(tr);
                            tg = Math.Round(tg);
                            tb = Math.Round(tb);
                            tr = Math.Min(tr, 255);
                            tg = Math.Min(tg, 255);
                            tb = Math.Min(tb, 255);
                            c0 = Color.FromArgb((byte) tr, (byte) tg, (byte) tb);
                        }
                    }
                    output[x, y] = c0;
                }
            }

            // unlock layer bitmaps and output bitmap
            foreach (Layer layer in this.Layers)
                layer.Bitmap.Unlock();
            output.Unlock();

            return output.InnerBitmap;
        }