/// <summary>
        /// Adjusts the alpha component of the given image.
        /// </summary>
        /// <param name="source">
        /// The <see cref="Image"/> source to adjust.
        /// </param>
        /// <param name="percentage">
        /// The percentage value between 0 and 100 for adjusting the opacity.
        /// </param>
        /// <param name="rectangle">The rectangle to define the bounds of the area to adjust the opacity. 
        /// If null then the effect is applied to the entire image.</param>
        /// <returns>
        /// The <see cref="Bitmap"/> with the alpha component adjusted.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown if the percentage value falls outside the acceptable range.
        /// </exception>
        public static Bitmap Alpha(Image source, int percentage, Rectangle? rectangle = null)
        {
            if (percentage > 100 || percentage < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(percentage), "Percentage should be between 0 and 100.");
            }

            float factor = (float)percentage / 100;
            int width = source.Width;
            int height = source.Height;

            // Traditional examples using a color matrix alter the rgb values also.
            using (FastBitmap bitmap = new FastBitmap(source))
            {
                // Loop through the pixels.
                Parallel.For(
                    0,
                    height,
                    y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            // ReSharper disable AccessToDisposedClosure
                            Color color = bitmap.GetPixel(x, y);
                            bitmap.SetPixel(x, y, Color.FromArgb(Convert.ToInt32(color.A * factor), color.R, color.G, color.B));
                            // ReSharper restore AccessToDisposedClosure
                        }
                    });
            }

            return (Bitmap)source;
        }
        /// <summary>
        /// Processes the given bitmap to apply the threshold.
        /// </summary>
        /// <param name="source">
        /// The image to process.
        /// </param>
        /// <returns>
        /// A processed bitmap.
        /// </returns>
        public Bitmap ProcessFilter(Bitmap source)
        {
            int width = source.Width;
            int height = source.Height;

            using (FastBitmap sourceBitmap = new FastBitmap(source))
            {
                Parallel.For(
                    0, 
                    height, 
                    y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            // ReSharper disable AccessToDisposedClosure
                            Color color = sourceBitmap.GetPixel(x, y);
                            sourceBitmap.SetPixel(x, y, color.B >= this.threshold ? Color.White : Color.Black);

                            // ReSharper restore AccessToDisposedClosure
                        }
                    });
            }

            return source;
        }
Beispiel #3
0
        /// <summary>
        /// Applies the given image mask to the source.
        /// </summary>
        /// <param name="source">
        /// The source <see cref="Image"/>.
        /// </param>
        /// <param name="mask">
        /// The mask <see cref="Image"/>.
        /// </param>
        /// <exception cref="ArgumentException">
        /// Thrown if the two images are of different size.
        /// </exception>
        /// <returns>
        /// The masked <see cref="Bitmap"/>.
        /// </returns>
        public static Bitmap ApplyMask(Image source, Image mask)
        {
            if (mask.Size != source.Size)
            {
                throw new ArgumentException();
            }

            int width = mask.Width;
            int height = mask.Height;

            Bitmap toMask = new Bitmap(source);
            toMask.SetResolution(source.HorizontalResolution, source.VerticalResolution);

            // Loop through and replace the alpha channel
            using (FastBitmap maskBitmap = new FastBitmap(mask))
            {
                using (FastBitmap sourceBitmap = new FastBitmap(toMask))
                {
                    Parallel.For(
                        0,
                        height,
                        y =>
                        {
                            for (int x = 0; x < width; x++)
                            {
                                // ReSharper disable AccessToDisposedClosure
                                Color maskColor = maskBitmap.GetPixel(x, y);
                                Color sourceColor = sourceBitmap.GetPixel(x, y);

                                if (sourceColor.A != 0)
                                {
                                    sourceBitmap.SetPixel(x, y, Color.FromArgb(maskColor.A, sourceColor.R, sourceColor.G, sourceColor.B));
                                }

                                // ReSharper restore AccessToDisposedClosure
                            }
                        });
                }
            }

            // Ensure the background is cleared out on non alpha supporting formats.
            Bitmap clear = new Bitmap(width, height, PixelFormat.Format32bppPArgb);
            clear.SetResolution(source.HorizontalResolution, source.VerticalResolution);
            using (Graphics graphics = Graphics.FromImage(clear))
            {
                graphics.SmoothingMode = SmoothingMode.AntiAlias;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.Clear(Color.Transparent);

                graphics.DrawImageUnscaled(toMask, 0, 0, width, height);
            }

            toMask.Dispose();
            return clear;
        }
Beispiel #4
0
        public Bitmap DrawImage(Color[] colors)
        {
            if (Width < 1 || Height < 1) {
                return null;
            }

            var image = new Bitmap(Width, Height);
            var fastBmp = new FastBitmap(image);

            fastBmp.LockImage();
            for (int y = 0, i = 0; y < Height; y++) {
                for (var x = 0; x < Width; x++) {
                    fastBmp.SetPixel(x, y, colors[(int)Cells[i++].Type]);
                }
            }
            fastBmp.UnlockImage();

            return image;
        }
Beispiel #5
0
		public Bitmap DrawImage(Color[] Colors) {
			if (Width < 1 || Height < 1) {
				return null;
			}

			Bitmap Image = new Bitmap(Width, Height);
			FastBitmap fastBmp = new FastBitmap(Image);

			using (Graphics g = Graphics.FromImage(Image)) {

				fastBmp.LockImage();
				for (int y = 0, i = 0; y < Height; y++) {
					for (int x = 0; x < Width; x++) {
						fastBmp.SetPixel(x, y, Colors[(int)Cells[i++].Type]);
					}
				}
				fastBmp.UnlockImage();
			}

			return Image;
		}
        /// <summary>
        /// Processes the given bitmap to apply the current instance of <see cref="IEdgeFilter"/>.
        /// </summary>
        /// <param name="source">The image to process.</param>
        /// <returns>A processed bitmap.</returns>
        public Bitmap ProcessFilter(Image source)
        {
            int width = source.Width;
            int height = source.Height;
            int maxWidth = width + 1;
            int maxHeight = height + 1;
            int bufferedWidth = width + 2;
            int bufferedHeight = height + 2;

            Bitmap destination = new Bitmap(width, height, PixelFormat.Format32bppPArgb);
            Bitmap input = new Bitmap(bufferedWidth, bufferedHeight, PixelFormat.Format32bppPArgb);
            destination.SetResolution(source.HorizontalResolution, source.VerticalResolution);
            input.SetResolution(source.HorizontalResolution, source.VerticalResolution);

            using (Graphics graphics = Graphics.FromImage(input))
            {
                // Fixes an issue with transparency not converting properly.
                graphics.Clear(Color.Transparent);

                Rectangle destinationRectangle = new Rectangle(0, 0, bufferedWidth, bufferedHeight);
                Rectangle rectangle = new Rectangle(0, 0, width, height);

                // If it's greyscale apply a colormatrix to the image.
                using (ImageAttributes attributes = new ImageAttributes())
                {
                    if (this.greyscale)
                    {
                        attributes.SetColorMatrix(ColorMatrixes.GreyScale);
                    }

                    // We use a trick here to detect right to the edges of the image.
                    // flip/tile the image with a pixel in excess in each direction to duplicate pixels.
                    // Later on we draw pixels without that excess.
                    using (TextureBrush tb = new TextureBrush(source, rectangle, attributes))
                    {
                        tb.WrapMode = WrapMode.TileFlipXY;
                        tb.TranslateTransform(1, 1);

                        graphics.FillRectangle(tb, destinationRectangle);
                    }
                }
            }

            try
            {
                double[,] horizontalFilter = this.edgeFilter.HorizontalGradientOperator;

                int kernelLength = horizontalFilter.GetLength(0);
                int radius = kernelLength >> 1;

                using (FastBitmap sourceBitmap = new FastBitmap(input))
                {
                    using (FastBitmap destinationBitmap = new FastBitmap(destination))
                    {
                        // Loop through the pixels.
                        Parallel.For(
                            0,
                            bufferedHeight,
                            y =>
                            {
                                for (int x = 0; x < bufferedWidth; x++)
                                {
                                    double rX = 0;
                                    double gX = 0;
                                    double bX = 0;

                                    // Apply each matrix multiplier to the color components for each pixel.
                                    for (int fy = 0; fy < kernelLength; fy++)
                                    {
                                        int fyr = fy - radius;
                                        int offsetY = y + fyr;

                                        // Skip the current row
                                        if (offsetY < 0)
                                        {
                                            continue;
                                        }

                                        // Outwith the current bounds so break.
                                        if (offsetY >= bufferedHeight)
                                        {
                                            break;
                                        }

                                        for (int fx = 0; fx < kernelLength; fx++)
                                        {
                                            int fxr = fx - radius;
                                            int offsetX = x + fxr;

                                            // Skip the column
                                            if (offsetX < 0)
                                            {
                                                continue;
                                            }

                                            if (offsetX < bufferedWidth)
                                            {
                                                // ReSharper disable once AccessToDisposedClosure
                                                Color currentColor = sourceBitmap.GetPixel(offsetX, offsetY);
                                                double r = currentColor.R;
                                                double g = currentColor.G;
                                                double b = currentColor.B;

                                                rX += horizontalFilter[fy, fx] * r;

                                                gX += horizontalFilter[fy, fx] * g;

                                                bX += horizontalFilter[fy, fx] * b;
                                            }
                                        }
                                    }

                                    // Apply the equation and sanitize.
                                    byte red = rX.ToByte();
                                    byte green = gX.ToByte();
                                    byte blue = bX.ToByte();

                                    Color newColor = Color.FromArgb(red, green, blue);
                                    if (y > 0 && x > 0 && y < maxHeight && x < maxWidth)
                                    {
                                        // ReSharper disable once AccessToDisposedClosure
                                        destinationBitmap.SetPixel(x - 1, y - 1, newColor);
                                    }
                                }
                            });
                    }
                }
            }
            finally
            {
                // We created a new image. Cleanup.
                input.Dispose();
            }

            return destination;
        }
        public static void GenerateBitmap(byte[] data, FastBitmap bmp, int startY, int dataAddress, List<Color> fourColors, int addY)
        {
            int index = 0;
            bool onlyHalf = false;
            int y = startY;
            int x = 0;
            int colorZeroValue = fourColors[0].ToArgb();
            while (y < bmp.Height && dataAddress + index + 2 < data.Length)
            {
                int runLength;
                int color;
                bool restOfLine;
                index += DecodeRle(dataAddress + index, data, out color, out runLength, ref onlyHalf, out restOfLine);
                if (restOfLine)
                    runLength = bmp.Width - x;

                Color c = fourColors[color]; // set color via the four colors
                for (int i = 0; i < runLength; i++, x++)
                {
                    if (x >= bmp.Width - 1)
                    {
                        if (y < bmp.Height && x < bmp.Width && c != fourColors[0])
                            bmp.SetPixel(x, y, c);

                        if (onlyHalf)
                        {
                            onlyHalf = false;
                            index++;
                        }
                        x = 0;
                        y += addY;
                        break;
                    }
                    if (y < bmp.Height && c.ToArgb() != colorZeroValue)
                        bmp.SetPixel(x, y, c);
                }
            }
        }
        /// <summary>
        /// Applies the halftone filter. 
        /// </summary>
        /// <param name="source">
        /// The <see cref="Bitmap"/> to apply the filter to.
        /// </param>
        /// <returns>
        /// The <see cref="Bitmap"/> with the filter applied.
        /// </returns>
        public Bitmap ApplyFilter(Bitmap source)
        {
            // TODO: Make this class implement an interface?
            Bitmap padded = null;
            Bitmap cyan = null;
            Bitmap magenta = null;
            Bitmap yellow = null;
            Bitmap keyline = null;
            Bitmap newImage = null;

            try
            {
                int sourceWidth = source.Width;
                int sourceHeight = source.Height;
                int width = source.Width + this.distance;
                int height = source.Height + this.distance;

                // Draw a slightly larger image, flipping the top/left pixels to prevent
                // jagged edge of output.
                padded = new Bitmap(width, height, PixelFormat.Format32bppPArgb);
                padded.SetResolution(source.HorizontalResolution, source.VerticalResolution);
                using (Graphics graphicsPadded = Graphics.FromImage(padded))
                {
                    graphicsPadded.Clear(Color.White);
                    Rectangle destinationRectangle = new Rectangle(0, 0, sourceWidth + this.distance, source.Height + this.distance);
                    using (TextureBrush tb = new TextureBrush(source))
                    {
                        tb.WrapMode = WrapMode.TileFlipXY;
                        tb.TranslateTransform(this.distance, this.distance);
                        graphicsPadded.FillRectangle(tb, destinationRectangle);
                    }
                }

                // Calculate min and max widths/heights.
                Rectangle rotatedBounds = this.GetBoundingRectangle(width, height);
                int minY = -(rotatedBounds.Height + height);
                int maxY = rotatedBounds.Height + height;
                int minX = -(rotatedBounds.Width + width);
                int maxX = rotatedBounds.Width + width;
                Point center = Point.Empty;

                // Yellow oversaturates the output.
                int offset = this.distance;
                float yellowMultiplier = this.distance * 1.587f;
                float magentaMultiplier = this.distance * 2.176f;
                float multiplier = this.distance * 2.2f;
                float max = this.distance * (float)Math.Sqrt(2);
                float magentaMax = this.distance * (float)Math.Sqrt(1.4545);

                // Bump up the keyline max so that black looks black.
                float keylineMax = max * (float)Math.Sqrt(2);

                // Color sampled process colours from Wikipedia pages.
                // Keyline brush is declared separately.
                Brush cyanBrush = new SolidBrush(Color.FromArgb(0, 183, 235));
                Brush magentaBrush = new SolidBrush(Color.FromArgb(255, 0, 144));
                Brush yellowBrush = new SolidBrush(Color.FromArgb(255, 239, 0));

                // Create our images.
                cyan = new Bitmap(width, height, PixelFormat.Format32bppPArgb);
                magenta = new Bitmap(width, height, PixelFormat.Format32bppPArgb);
                yellow = new Bitmap(width, height, PixelFormat.Format32bppPArgb);
                keyline = new Bitmap(width, height, PixelFormat.Format32bppPArgb);
                newImage = new Bitmap(sourceWidth, sourceHeight, PixelFormat.Format32bppPArgb);

                // Ensure the correct resolution is set.
                cyan.SetResolution(source.HorizontalResolution, source.VerticalResolution);
                magenta.SetResolution(source.HorizontalResolution, source.VerticalResolution);
                yellow.SetResolution(source.HorizontalResolution, source.VerticalResolution);
                keyline.SetResolution(source.HorizontalResolution, source.VerticalResolution);
                newImage.SetResolution(source.HorizontalResolution, source.VerticalResolution);

                // Check bounds against this.
                Rectangle rectangle = new Rectangle(0, 0, width, height);

                using (Graphics graphicsCyan = Graphics.FromImage(cyan))
                using (Graphics graphicsMagenta = Graphics.FromImage(magenta))
                using (Graphics graphicsYellow = Graphics.FromImage(yellow))
                using (Graphics graphicsKeyline = Graphics.FromImage(keyline))
                {
                    // Set the quality properties.
                    graphicsCyan.PixelOffsetMode = PixelOffsetMode.Half;
                    graphicsMagenta.PixelOffsetMode = PixelOffsetMode.Half;
                    graphicsYellow.PixelOffsetMode = PixelOffsetMode.Half;
                    graphicsKeyline.PixelOffsetMode = PixelOffsetMode.Half;

                    graphicsCyan.SmoothingMode = SmoothingMode.AntiAlias;
                    graphicsMagenta.SmoothingMode = SmoothingMode.AntiAlias;
                    graphicsYellow.SmoothingMode = SmoothingMode.AntiAlias;
                    graphicsKeyline.SmoothingMode = SmoothingMode.AntiAlias;

                    graphicsCyan.CompositingQuality = CompositingQuality.HighQuality;
                    graphicsMagenta.CompositingQuality = CompositingQuality.HighQuality;
                    graphicsYellow.CompositingQuality = CompositingQuality.HighQuality;
                    graphicsKeyline.CompositingQuality = CompositingQuality.HighQuality;

                    // Set up the canvas.
                    graphicsCyan.Clear(Color.White);
                    graphicsMagenta.Clear(Color.White);
                    graphicsYellow.Clear(Color.White);
                    graphicsKeyline.Clear(Color.White);

                    // This is too slow. The graphics object can't be called within a parallel
                    // loop so we have to do it old school. :(
                    using (FastBitmap sourceBitmap = new FastBitmap(padded))
                    {
                        for (int y = minY; y < maxY; y += offset)
                        {
                            for (int x = minX; x < maxX; x += offset)
                            {
                                Color color;
                                CmykColor cmykColor;
                                float brushWidth;

                                // Cyan
                                Point rotatedPoint = ImageMaths.RotatePoint(new Point(x, y), this.cyanAngle, center);
                                int angledX = rotatedPoint.X;
                                int angledY = rotatedPoint.Y;
                                if (rectangle.Contains(new Point(angledX, angledY)))
                                {
                                    color = sourceBitmap.GetPixel(angledX, angledY);
                                    cmykColor = color;
                                    brushWidth = Math.Min((cmykColor.C / 100f) * multiplier, max);
                                    graphicsCyan.FillEllipse(cyanBrush, angledX, angledY, brushWidth, brushWidth);
                                }

                                // Magenta
                                rotatedPoint = ImageMaths.RotatePoint(new Point(x, y), this.magentaAngle, center);
                                angledX = rotatedPoint.X;
                                angledY = rotatedPoint.Y;
                                if (rectangle.Contains(new Point(angledX, angledY)))
                                {
                                    color = sourceBitmap.GetPixel(angledX, angledY);
                                    cmykColor = color;
                                    brushWidth = Math.Min((cmykColor.M / 100f) * magentaMultiplier, magentaMax);
                                    graphicsMagenta.FillEllipse(magentaBrush, angledX, angledY, brushWidth, brushWidth);
                                }

                                // Yellow
                                rotatedPoint = ImageMaths.RotatePoint(new Point(x, y), this.yellowAngle, center);
                                angledX = rotatedPoint.X;
                                angledY = rotatedPoint.Y;
                                if (rectangle.Contains(new Point(angledX, angledY)))
                                {
                                    color = sourceBitmap.GetPixel(angledX, angledY);
                                    cmykColor = color;
                                    brushWidth = Math.Min((cmykColor.Y / 100f) * yellowMultiplier, max);
                                    graphicsYellow.FillEllipse(yellowBrush, angledX, angledY, brushWidth, brushWidth);
                                }

                                // Keyline
                                rotatedPoint = ImageMaths.RotatePoint(new Point(x, y), this.keylineAngle, center);
                                angledX = rotatedPoint.X;
                                angledY = rotatedPoint.Y;
                                if (rectangle.Contains(new Point(angledX, angledY)))
                                {
                                    color = sourceBitmap.GetPixel(angledX, angledY);
                                    cmykColor = color;
                                    brushWidth = Math.Min((cmykColor.K / 100f) * multiplier, keylineMax);

                                    // Just using black is too dark.
                                    Brush keylineBrush = new SolidBrush(CmykColor.FromCmykColor(0, 0, 0, cmykColor.K));
                                    graphicsKeyline.FillEllipse(keylineBrush, angledX, angledY, brushWidth, brushWidth);
                                }
                            }
                        }
                    }

                    // Set our white background.
                    using (Graphics graphics = Graphics.FromImage(newImage))
                    {
                        graphics.Clear(Color.White);
                    }

                    // Blend the colors now to mimic adaptive blending.
                    using (FastBitmap cyanBitmap = new FastBitmap(cyan))
                    using (FastBitmap magentaBitmap = new FastBitmap(magenta))
                    using (FastBitmap yellowBitmap = new FastBitmap(yellow))
                    using (FastBitmap keylineBitmap = new FastBitmap(keyline))
                    using (FastBitmap destinationBitmap = new FastBitmap(newImage))
                    {
                        Parallel.For(
                            offset,
                            height,
                            y =>
                            {
                                for (int x = offset; x < width; x++)
                                {
                                    // ReSharper disable AccessToDisposedClosure
                                    Color cyanPixel = cyanBitmap.GetPixel(x, y);
                                    Color magentaPixel = magentaBitmap.GetPixel(x, y);
                                    Color yellowPixel = yellowBitmap.GetPixel(x, y);
                                    Color keylinePixel = keylineBitmap.GetPixel(x, y);

                                    // Negate the offset.
                                    int xBack = x - offset;
                                    int yBack = y - offset;

                                    CmykColor blended = cyanPixel.AddAsCmykColor(magentaPixel, yellowPixel, keylinePixel);
                                    if (rectangle.Contains(new Point(xBack, yBack)))
                                    {
                                        destinationBitmap.SetPixel(xBack, yBack, blended);
                                    }
                                    // ReSharper restore AccessToDisposedClosure
                                }
                            });
                    }
                }

                padded.Dispose();
                cyan.Dispose();
                magenta.Dispose();
                yellow.Dispose();
                keyline.Dispose();
                source.Dispose();
                source = newImage;
            }
            catch
            {
                if (padded != null)
                {
                    padded.Dispose();
                }

                if (cyan != null)
                {
                    cyan.Dispose();
                }

                if (magenta != null)
                {
                    magenta.Dispose();
                }

                if (yellow != null)
                {
                    yellow.Dispose();
                }

                if (keyline != null)
                {
                    keyline.Dispose();
                }

                if (newImage != null)
                {
                    newImage.Dispose();
                }
            }

            return source;
        }
Beispiel #9
0
        /// <summary>
        /// Adjust the gamma (intensity of the light) component of the given image.
        /// </summary>
        /// <param name="source">
        /// The <see cref="Image"/> source to adjust.
        /// </param>
        /// <param name="value">
        /// The value to adjust the gamma by (typically between .2 and 5).
        /// </param>
        /// <returns>
        /// The <see cref="Bitmap"/> with the gamma adjusted.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown if the value falls outside the acceptable range.
        /// </exception>
        public static Bitmap Gamma(Image source, float value)
        {
            if (value > 5 || value < .1)
            {
                throw new ArgumentOutOfRangeException("value", "Value should be between .1 and 5.");
            }

            int width = source.Width;
            int height = source.Height;
            Bitmap destination = new Bitmap(width, height);
            destination.SetResolution(source.HorizontalResolution, source.VerticalResolution);

            byte[] ramp = new byte[256];
            for (int x = 0; x < 256; ++x)
            {
                byte val = ((255.0 * Math.Pow(x / 255.0, value)) + 0.5).ToByte();
                ramp[x] = val;
            }

            using (FastBitmap fastSource = new FastBitmap(source))
            {
                using (FastBitmap fastDestination = new FastBitmap(destination))
                {
                    Parallel.For(
                        0,
                        height,
                        y =>
                        {
                            for (int x = 0; x < width; x++)
                            {
                                // ReSharper disable once AccessToDisposedClosure
                                Color color = fastSource.GetPixel(x, y);
                                byte r = ramp[color.R];
                                byte g = ramp[color.G];
                                byte b = ramp[color.B];

                                // ReSharper disable once AccessToDisposedClosure
                                fastDestination.SetPixel(x, y, Color.FromArgb(color.A, r, g, b));
                            }
                        });
                }
            }

            //Rectangle rectangle = new Rectangle(0, 0, width, height);
            //using (Graphics graphics = Graphics.FromImage(destination))
            //{
            //    using (ImageAttributes attributes = new ImageAttributes())
            //    {
            //        attributes.SetGamma(value);
            //        graphics.DrawImage(source, rectangle, 0, 0, width, height, GraphicsUnit.Pixel, attributes);
            //    }
            //}

            source.Dispose();
            return destination;
        }
Beispiel #10
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();
            }
        }
Beispiel #11
0
        /// <summary>
        /// Traces the edges of a given <see cref="Image"/>.
        /// </summary>
        /// <param name="source">
        /// The source <see cref="Image"/>.
        /// </param>
        /// <param name="destination">
        /// The destination <see cref="Image"/>.
        /// </param>
        /// <param name="threshold">
        /// The threshold (between 0 and 255).
        /// </param>
        /// <returns>
        /// The a new instance of <see cref="Bitmap"/> traced.
        /// </returns>
        public static Bitmap Trace(Image source, Image destination, byte threshold = 0)
        {
            int width = source.Width;
            int height = source.Height;

            // Grab the edges converting to greyscale, and invert the colors.
            ConvolutionFilter filter = new ConvolutionFilter(new SobelEdgeFilter(), true);

            using (Bitmap temp = filter.Process2DFilter(source))
            {
                destination = new InvertMatrixFilter().TransformImage(temp, destination);

                // Darken it slightly to aid detection
                destination = Adjustments.Brightness(destination, -5);
            }

            // Loop through and replace any colors more white than the threshold
            // with a transparent one.
            using (FastBitmap destinationBitmap = new FastBitmap(destination))
            {
                Parallel.For(
                    0,
                    height,
                    y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            // ReSharper disable AccessToDisposedClosure
                            Color color = destinationBitmap.GetPixel(x, y);
                            if (color.B >= threshold)
                            {
                                destinationBitmap.SetPixel(x, y, Color.Transparent);
                            }
                            // ReSharper restore AccessToDisposedClosure
                        }
                    });
            }

            // Darken it again to average out the color.
            destination = Adjustments.Brightness(destination, -5);

            return (Bitmap)destination;
        }
Beispiel #12
0
        public Bitmap GetImageTransparentPal(int index)
        {
            if (ImagesPal == null || ImagesPal.Count <= index) {
                return null;
            }
            if (IsDrawnPal(index) == false) {
                if (DrawPalImage(index) == false) {
                    throw new Exception("Failed to draw pal-image on index #" + index);
                }
            }

            var img = ImagesPal[index].Image.Clone() as Bitmap;
            if (img == null) {
                throw new Exception("Invalid pal image on index #" + index);
            }
            var bg = Palette[0];
            var fb = new FastBitmap(img);

            fb.LockImage();
            for (var x = 0; x < img.Width; x++) {
                for (var y = 0; y < img.Height; y++) {
                    if (fb.GetPixel(x, y) == bg) {
                        fb.SetPixel(x, y, Color.Transparent);
                    }
                }
            }
            fb.UnlockImage();

            return img;
        }
Beispiel #13
0
		public Bitmap GetImageTransparentPal(int index) {
			if (ImagesPal == null || ImagesPal.Count <= index) {
				return null;
			}
			if (IsDrawnPal(index) == false) {
				if (DrawPalImage(index) == false) {
					// TODO: Exception?
					return null;
				}
			}

			Bitmap img = ImagesPal[index].Image.Clone() as Bitmap;
			Color bg = Palette[0];
			FastBitmap fb = new FastBitmap(img);

			fb.LockImage();
			for (int x = 0; x < img.Width; x++) {
				for (int y = 0; y < img.Height; y++) {
					if (fb.GetPixel(x, y) == bg) {
						fb.SetPixel(x, y, Color.Transparent);
					}
				}
			}
			fb.UnlockImage();

			return img;
		}
Beispiel #14
0
		public bool DrawRgbaImage(int imageIndex) {
			if (ImagesRgba == null || ImagesRgba.Count <= imageIndex) {
				return false;
			}
			if (imageIndex < 0 || imageIndex >= ImagesRgba.Count) {
				return false;
			}

			RoSpriteImageRgba sprImg = ImagesRgba[imageIndex];
			if (sprImg == null || sprImg.Data == null || sprImg.Data.Length == 0 || sprImg.Width < 1 || sprImg.Height < 1) {
				return false;
			}

			sprImg.Image = new Bitmap(sprImg.Width, sprImg.Height);
			FastBitmap fb = new FastBitmap(sprImg.Image);

			int index = 0, alpha = 0, red = 0, green = 0, blue = 0;
			Color col;
			fb.LockImage();
			for (int y = 0; y < sprImg.Height; y++) {
				for (int x = 0; x < sprImg.Width; x++, index += 4) {
					// A B G R
					alpha = sprImg.Data[index];
					blue = sprImg.Data[index + 1];
					green = sprImg.Data[index + 2];
					red = sprImg.Data[index + 3];
					col = Color.FromArgb(alpha, red, green, blue);
					fb.SetPixel(x, y, col);
				}
			}
			fb.UnlockImage();

			return true;
		}
Beispiel #15
0
		public bool DrawPalImage(int imageIndex) {
			if (ImagesPal == null || ImagesPal.Count <= imageIndex) {
				return false;
			}
			if (imageIndex < 0 || imageIndex >= ImagesPal.Count) {
				return false;
			}

			RoSpriteImagePal sprImg = ImagesPal[imageIndex];
			if (Version >= 0x201 && sprImg.Decoded == false) {
				sprImg.Data = RLE.Decode(sprImg.Data);
				sprImg.Decoded = true;
			}
			if (sprImg.Data == null || sprImg.Data.Length == 0 || sprImg.Width < 1 || sprImg.Height < 1) {
				return false;
			}

			sprImg.Image = new Bitmap(sprImg.Width, sprImg.Height);
			FastBitmap fb = new FastBitmap(sprImg.Image);

			int index;
			fb.LockImage();
			for (int x = 0; x < sprImg.Width; x++) {
				for (int y = 0; y < sprImg.Height; y++) {
					index = (x + (y * sprImg.Width));
					if (index >= sprImg.Data.Length) {
						fb.SetPixel(x, y, Color.Transparent);
						continue;
					}
					fb.SetPixel(x, y, Palette[sprImg.Data[index]]);
				}
			}
			fb.UnlockImage();

			return true;
		}
Beispiel #16
0
        public Bitmap GetImageTransparentRgba(int index)
        {
            if (ImagesRgba == null || ImagesRgba.Count <= index) {
                return null;
            }
            if (IsDrawnRgba(index) == false) {
                DrawRgbaImage(index);
            }

            var img = ImagesRgba[index].Image.Clone() as Bitmap;
            if (img == null) {
                throw new Exception("Invalid rgba image on index #" + index);
            }
            var bg = Color.Fuchsia;
            var fb = new FastBitmap(img);

            fb.LockImage();
            for (var x = 0; x < img.Width; x++) {
                for (var y = 0; y < img.Height; y++) {
                    if (fb.GetPixel(x, y) == bg) {
                        fb.SetPixel(x, y, Color.Transparent);
                    }
                }
            }
            fb.UnlockImage();

            return img;
        }
Beispiel #17
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;
 }
Beispiel #18
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);
        }
Beispiel #19
0
        public void TestFastBitmapUnlockedSetAccessException()
        {
            Bitmap bitmap = new Bitmap(64, 64);
            FastBitmap fastBitmap = new FastBitmap(bitmap);

            fastBitmap.SetPixel(0, 0, 0);
        }
        /// <summary>
        /// Adjust the gamma (intensity of the light) component of the given image.
        /// </summary>
        /// <param name="source">
        /// The <see cref="Image"/> source to adjust.
        /// </param>
        /// <param name="value">
        /// The value to adjust the gamma by (typically between .2 and 5).
        /// </param>
        /// <returns>
        /// The <see cref="Bitmap"/> with the gamma adjusted.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown if the value falls outside the acceptable range.
        /// </exception>
        public static Bitmap Gamma(Image source, float value)
        {
            if (value > 5 || value < .1)
            {
                throw new ArgumentOutOfRangeException(nameof(value), "Value should be between .1 and 5.");
            }

            byte[] ramp = new byte[256];
            for (int x = 0; x < 256; ++x)
            {
                byte val = ((255.0 * Math.Pow(x / 255.0, value)) + 0.5).ToByte();
                ramp[x] = val;
            }

            int width = source.Width;
            int height = source.Height;

            using (FastBitmap bitmap = new FastBitmap(source))
            {
                Parallel.For(
                    0,
                    height,
                    y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            // ReSharper disable once AccessToDisposedClosure
                            Color composite = bitmap.GetPixel(x, y);
                            Color linear = Color.FromArgb(composite.A, ramp[composite.R], ramp[composite.G], ramp[composite.B]);
                            // ReSharper disable once AccessToDisposedClosure
                            bitmap.SetPixel(x, y, linear);
                        }
                    });
            }

            return (Bitmap)source;
        }
        /// <summary>
        /// Converts an image from a linear color-space to the equivalent sRGB color-space.
        /// </summary>
        /// <param name="source">
        /// The <see cref="Image"/> source to convert.
        /// </param>
        /// <returns>
        /// The <see cref="Bitmap"/>.
        /// </returns>
        public static Bitmap ToSRGB(Image source)
        {
            // Create only once and lazily.
            byte[] ramp = SRGBBytes.Value;

            int width = source.Width;
            int height = source.Height;

            using (FastBitmap bitmap = new FastBitmap(source))
            {
                Parallel.For(
                    0,
                    height,
                    y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            // ReSharper disable once AccessToDisposedClosure
                            Color composite = bitmap.GetPixel(x, y);
                            Color linear = Color.FromArgb(composite.A, ramp[composite.R], ramp[composite.G], ramp[composite.B]);
                            // ReSharper disable once AccessToDisposedClosure
                            bitmap.SetPixel(x, y, linear);
                        }
                    });
            }

            return (Bitmap)source;
        }
 private static void PutPixel(FastBitmap bmp, int index, int color, BluRaySupPalette palette)
 {
     int x = index % bmp.Width;
     int y = index / bmp.Width;
     if (x < bmp.Width && y < bmp.Height)
         bmp.SetPixel(x, y, Color.FromArgb(palette.GetArgb(color)));
 }
        /// <summary>
        /// Applies the oil painting filter. 
        /// </summary>
        /// <param name="source">
        /// The source.
        /// </param>
        /// <returns>
        /// The <see cref="Bitmap"/>.
        /// </returns>
        public Bitmap ApplyFilter(Bitmap source)
        {
            // TODO: Make this class implement an interface?
            int width = source.Width;
            int height = source.Height;

            int radius = this.brushSize >> 1;

            Bitmap destination = new Bitmap(width, height, PixelFormat.Format32bppPArgb);
            destination.SetResolution(source.HorizontalResolution, source.VerticalResolution);
            using (FastBitmap sourceBitmap = new FastBitmap(source))
            {
                using (FastBitmap destinationBitmap = new FastBitmap(destination))
                {
                    Parallel.For(
                        0,
                        height,
                        y =>
                        {
                            for (int x = 0; x < width; x++)
                            {
                                int maxIntensity = 0;
                                int maxIndex = 0;
                                int[] intensityBin = new int[this.levels];
                                int[] blueBin = new int[this.levels];
                                int[] greenBin = new int[this.levels];
                                int[] redBin = new int[this.levels];
                                byte sourceAlpha = 255;

                                for (int i = 0; i <= radius; i++)
                                {
                                    int ir = i - radius;
                                    int offsetY = y + ir;

                                    // Skip the current row
                                    if (offsetY < 0)
                                    {
                                        continue;
                                    }

                                    // Outwith the current bounds so break.
                                    if (offsetY >= height)
                                    {
                                        break;
                                    }

                                    for (int fx = 0; fx <= radius; fx++)
                                    {
                                        int jr = fx - radius;
                                        int offsetX = x + jr;

                                        // Skip the column
                                        if (offsetX < 0)
                                        {
                                            continue;
                                        }

                                        if (offsetX < width)
                                        {
                                            // ReSharper disable once AccessToDisposedClosure
                                            Color color = sourceBitmap.GetPixel(offsetX, offsetY);

                                            byte sourceBlue = color.B;
                                            byte sourceGreen = color.G;
                                            byte sourceRed = color.R;
                                            sourceAlpha = color.A;

                                            int currentIntensity = (int)Math.Round(((sourceBlue + sourceGreen + sourceRed) / 3.0 * (this.levels - 1)) / 255.0);

                                            intensityBin[currentIntensity] += 1;
                                            blueBin[currentIntensity] += sourceBlue;
                                            greenBin[currentIntensity] += sourceGreen;
                                            redBin[currentIntensity] += sourceRed;

                                            if (intensityBin[currentIntensity] > maxIntensity)
                                            {
                                                maxIntensity = intensityBin[currentIntensity];
                                                maxIndex = currentIntensity;
                                            }
                                        }
                                    }
                                }

                                byte blue = Math.Abs(blueBin[maxIndex] / maxIntensity).ToByte();
                                byte green = Math.Abs(greenBin[maxIndex] / maxIntensity).ToByte();
                                byte red = Math.Abs(redBin[maxIndex] / maxIntensity).ToByte();

                                // ReSharper disable once AccessToDisposedClosure
                                destinationBitmap.SetPixel(x, y, Color.FromArgb(sourceAlpha, red, green, blue));
                            }
                        });
                }
            }

            return destination;
        }
        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;
        }
Beispiel #25
0
		public Bitmap GetImageTransparentRgba(int index) {
			if (ImagesRgba == null || ImagesRgba.Count <= index) {
				return null;
			}
			if (IsDrawnRgba(index) == false) {
				DrawRgbaImage(index);
			}

			Bitmap img = ImagesRgba[index].Image.Clone() as Bitmap;
			Color bg = Color.Fuchsia;
			FastBitmap fb = new FastBitmap(img);

			fb.LockImage();
			for (int x = 0; x < img.Width; x++) {
				for (int y = 0; y < img.Height; y++) {
					if (fb.GetPixel(x, y) == bg) {
						fb.SetPixel(x, y, Color.Transparent);
					}
				}
			}
			fb.UnlockImage();

			return img;
		}
Beispiel #26
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");
        }
 private static void PutPixel(FastBitmap bmp, int index, Color color)
 {
     if (color.A > 0)
     {
         int x = index % bmp.Width;
         int y = index / bmp.Width;
         if (x < bmp.Width && y < bmp.Height)
             bmp.SetPixel(x, y, color);
     }
 }
Beispiel #28
0
 private FastBitmap ApplyMask(byte[] mask, FastBitmap img)
 {
     Bitmap result = new Bitmap(img.Width, img.Height);
     FastBitmap fb = new FastBitmap(result);
     fb.LockBits();
     img.LockBits();
     int n = 0;
     for (int j = 0; j < img.Height; j++)
     {
         for (int i = 0; i < img.Width; i++)
         {
             if (mask[n] > VibeModel.BackgroundByte)
             {
                 fb.SetPixel(i, j, img.GetPixel(i, j));
             }
             n++;
         }
     }
     img.UnlockBits();
     fb.UnlockBits();
     return fb;
 }