private void AdditiveMultiplicativeFilter(Bitmap source, Bitmap destination, double[] matrix)
        {
            var initData   = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, source.PixelFormat);
            var destData   = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, source.PixelFormat);
            int byteLength = 4;

            if (source.PixelFormat.ToString().Contains("24"))
            {
                byteLength = 3;
            }


            var pixelCount = 3;

            unsafe
            {
                byte *sourcePtr = (byte *)initData.Scan0.ToPointer();
                byte *destPtr   = (byte *)destData.Scan0.ToPointer();

                int pixelOffset = pixelCount / 2;
                int byteOffset  = pixelOffset * byteLength;
                for (int i = byteOffset; i < (initData.Stride - byteOffset); i += byteLength)
                {
                    for (int j = pixelOffset; j < source.Height - pixelOffset; j++)
                    {
                        byte[][] window = PixelOperations.GetWindowOfPixels(sourcePtr, initData.Stride, i, j, byteLength, pixelCount);
                        byte[]   pixel  = GetAdditiveMultiplicatedPixel(Transform2Dto1DArray(window, byteLength * pixelCount * pixelCount), byteLength, matrix);
                        PixelOperations.SetPixelUnsafe(destPtr, pixel, initData.Stride, i, j, byteLength);
                    }
                }
            }

            source.UnlockBits(initData);
            destination.UnlockBits(destData);
        }
        public Bitmap TransformImage(Image source, Image destination)
        {
            unsafe
            {
                var        bitMap         = new Bitmap(source);
                BitmapData bitmapData     = bitMap.LockBits(new Rectangle(0, 0, bitMap.Width, bitMap.Height), ImageLockMode.ReadWrite, bitMap.PixelFormat);
                int        bytesPerPixel  = Bitmap.GetPixelFormatSize(bitMap.PixelFormat) / 8;
                int        heightInPixels = bitmapData.Height;
                int        widthInBytes   = bitmapData.Width * bytesPerPixel;
                byte *     PtrFirstPixel  = (byte *)bitmapData.Scan0;

                Parallel.For(0, heightInPixels, y =>
                {
                    byte *currentLine = PtrFirstPixel + (y * bitmapData.Stride);
                    for (int x = 0; x < widthInBytes; x = x + bytesPerPixel)
                    {
                        var newPixel = PixelOperations.Sepia(Color.FromArgb(currentLine[x],
                                                                            currentLine[x + 1], currentLine[x + 2]));
                        currentLine[x + 2] = newPixel.R;
                        currentLine[x + 1] = newPixel.G;
                        currentLine[x]     = newPixel.B;
                    }
                });
                bitMap.UnlockBits(bitmapData);
                return(bitMap);
            }
        }
            internal static void FromVector4 <TPixel>(
                Configuration configuration,
                PixelOperations <TPixel> pixelOperations,
                ReadOnlySpan <Vector4> sourceVectors,
                Span <TPixel> destPixels,
                bool scaled)
                where TPixel : struct, IPixel <TPixel>
            {
                Guard.NotNull(configuration, nameof(configuration));
                Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels));

                int count = sourceVectors.Length;

                // Not worth for small buffers:
                if (count < Vector4ConversionThreshold)
                {
                    FromVector4Fallback(sourceVectors, destPixels, scaled);

                    return;
                }

                // For the opposite direction it's not easy to implement the trick used in RunRgba32CompatibleToVector4Conversion,
                // so let's allocate a temporary buffer as usually:
                using (IMemoryOwner <Rgba32> tempBuffer = configuration.MemoryAllocator.Allocate <Rgba32>(count))
                {
                    Span <Rgba32> tempSpan = tempBuffer.Memory.Span;

                    SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows(
                        MemoryMarshal.Cast <Vector4, float>(sourceVectors),
                        MemoryMarshal.Cast <Rgba32, byte>(tempSpan));

                    pixelOperations.FromRgba32(configuration, tempSpan, destPixels);
                }
            }
Beispiel #4
0
        /// <summary>
        /// This method pre-seeds the PixelOperations engine for the AoT compiler on iOS.
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        private static void AotCompilePixelOperations <TPixel>()
            where TPixel : struct, IPixel <TPixel>
        {
            var pixelOp = new PixelOperations <TPixel>();

            pixelOp.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.Clear);
        }
        private void MonohromeFilter(Bitmap source, Bitmap destination, Color firstColor, Color secondColor, int coefficient)
        {
            var initData   = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, source.PixelFormat);
            var destData   = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, source.PixelFormat);
            int byteLength = 4;

            if (source.PixelFormat.ToString().Contains("24"))
            {
                byteLength = 3;
            }

            unsafe
            {
                byte *sourcePtr = (byte *)initData.Scan0.ToPointer();
                byte *destPtr   = (byte *)destData.Scan0.ToPointer();

                for (int i = 0; i < initData.Stride; i += byteLength)
                {
                    for (int j = 0; j < source.Height; j++)
                    {
                        var pixel = PixelOperations.GetPixelUnsafe(sourcePtr, initData.Stride, i, j, byteLength);
                        pixel = GetMonohromePixel(pixel, byteLength, coefficient);
                        PixelOperations.SetPixelUnsafe(destPtr, pixel, initData.Stride, i, j, byteLength);
                    }
                }
            }

            source.UnlockBits(initData);
            destination.UnlockBits(destData);
        }
        private byte[] GetAdditiveMultiplicatedPixel(byte[] values, int byteLength, double[] matrix)
        {
            var RGBColors = PixelOperations.TransformPixelArrayToColorArray(values, byteLength);

            double red   = 0;
            double green = 0;
            double blue  = 0;
            double sum   = 0;

            for (int i = 0; i < 9; i++)
            {
                red   += RGBColors[i].R * matrix[i];
                green += RGBColors[i].G * matrix[i];
                blue  += RGBColors[i].B * matrix[i];
                sum   += matrix[i];
            }

            if (sum <= 0)
            {
                sum = 1;
            }

            red /= sum;
            if (red < 0)
            {
                red = 0;
            }
            if (red > 255)
            {
                red = 255;
            }

            green /= sum;
            if (green < 0)
            {
                green = 0;
            }
            if (green > 255)
            {
                green = 255;
            }

            blue /= sum;
            if (blue < 0)
            {
                blue = 0;
            }
            if (blue > 255)
            {
                blue = 255;
            }

            Color color = Color.FromArgb(RGBColors[4].A, (int)red, (int)green, (int)blue);

            byte[] pixel = PixelOperations.TransformColorToPixel(color, byteLength);
            return(pixel);
        }
        private byte[] GetMedian(byte[] values, int byteLength, int pixelCount)
        {
            List <Color> RGBColors = PixelOperations.TransformPixelArrayToColorArray(values, byteLength).ToList();

            RGBColors.Sort((x, y) => x.GetBrightness().CompareTo(y.GetBrightness()));
            Color color = RGBColors[pixelCount * pixelCount / 2];

            byte[] pixel = PixelOperations.TransformColorToPixel(color, byteLength);
            return(pixel);
        }
Beispiel #8
0
        /// <summary>
        /// Performs a vertical fast box blur on the collection of colors.
        /// <see href="http://blog.ivank.net/fastest-gaussian-blur.html"/>
        /// </summary>
        /// <param name="sourceColors">The source colors.</param>
        /// <param name="radius">The radius to which to blur.</param>
        /// <param name="fixGamma">Whether to blur the colors using the linear color space.</param>
        /// <returns>
        /// The <see cref="T:Color[,]"/>.
        /// </returns>
        private static Color[,] BoxBlurVertical(Color[,] sourceColors, int radius, bool fixGamma)
        {
            int width  = sourceColors.GetLength(0);
            int height = sourceColors.GetLength(1);

            Color[,] destination = new Color[width, height];

            // For each column
            for (int y = 0; y < height; y++)
            {
                // For each row
                for (int x = 0; x < width; x++)
                {
                    int fy    = Math.Max(0, y - radius);
                    int ty    = Math.Min(width, y + radius + 1);
                    int red   = 0;
                    int green = 0;
                    int blue  = 0;
                    int alpha = 0;

                    for (int yy = fy; yy < ty; yy++)
                    {
                        Color sourceColor = sourceColors[x, yy];

                        if (fixGamma)
                        {
                            sourceColor = PixelOperations.ToLinear(sourceColor);
                        }

                        red   += sourceColor.R;
                        green += sourceColor.G;
                        blue  += sourceColor.B;
                        alpha += sourceColor.A;
                    }

                    int divider = ty - fy;

                    red   /= divider;
                    green /= divider;
                    blue  /= divider;
                    alpha /= divider;

                    Color destinationColor = Color.FromArgb(alpha, red, green, blue);

                    if (fixGamma)
                    {
                        destinationColor = PixelOperations.ToSRGB(destinationColor);
                    }

                    destination[x, y] = destinationColor;
                }
            }

            return(destination);
        }
Beispiel #9
0
        private Bitmap RotateImage(Bitmap source, double angle)
        {
            double radAngle = angle * Math.PI / 180;
            var    cos      = Math.Cos(radAngle);
            var    sin      = Math.Sin(radAngle);

            var widthAndHeight = CalculateNewBoundaries(bitmap.Width, bitmap.Height, radAngle);
            int newWidth       = widthAndHeight.width;
            int newHeight      = widthAndHeight.height;

            Bitmap destination = new Bitmap((int)newWidth, (int)newHeight);

            var SrcData  = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, source.PixelFormat);
            var DestData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, source.PixelFormat);

            int bytelength = 4;

            if (source.PixelFormat.ToString().Contains("24"))
            {
                bytelength = 3;
            }

            int x0 = (int)(newWidth / 2.0);
            int y0 = (int)(newHeight / 2.0);

            unsafe
            {
                byte *SrcPtr  = (byte *)SrcData.Scan0.ToPointer();
                byte *DestPtr = (byte *)DestData.Scan0.ToPointer();

                var offset = GetOffsets(source.Width, source.Height, cos, sin, x0, y0, angle);

                for (double x = 0; x < source.Width; x += 1)
                {
                    for (int y = 0; y < source.Height; y++)
                    {
                        var X = CalculateNewX((int)x, y, cos, sin, x0, y0);
                        var Y = CalculateNewY((int)x, y, cos, sin, x0, y0);
                        X += offset.xOffset;
                        Y += offset.yOffset;

                        if (Y >= 0 && Y < newHeight && X >= 0 && X < newWidth)
                        {
                            var pixel = PixelOperations.GetPixelUnsafe(SrcPtr, SrcData.Stride, (int)Math.Round(x * 4), y, bytelength);
                            PixelOperations.SetPixelUnsafe(DestPtr, pixel, DestData.Stride, X * 4, Y, bytelength);
                            PixelOperations.SetPixelUnsafe(DestPtr, pixel, DestData.Stride, (X + 1) * 4, Y, bytelength);
                        }
                    }
                }
            }
            source.UnlockBits(SrcData);
            destination.UnlockBits(DestData);
            return(destination);
        }
Beispiel #10
0
        private void zielonyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            savedBitmap.Push(new Bitmap(picture));
            if (savedBitmap.Count() >= 0)
            {
                button1.Enabled = true;
            }
            PixelOperations pixelmod = new PixelOperations();

            Picture = pixelmod.grayscale3(new Bitmap(picture));
        }
Beispiel #11
0
        public Image ProcessImage(ImageFactory factory)
        {
            Bitmap newImage  = null;
            Image  image     = factory.Image;
            int    parameter = DynamicParameter;

            if (parameter > 100 || parameter < 0)
            {
                throw new ArgumentOutOfRangeException();
            }
            var bitMap = new Bitmap(image);

            try
            {
                using (Graphics graphics = Graphics.FromImage(image))
                {
                    using (ImageAttributes attributes = new ImageAttributes())
                    {
                        unsafe
                        {
                            BitmapData bitmapData = bitMap.LockBits(new Rectangle(0, 0, bitMap.Width, bitMap.Height), ImageLockMode.ReadWrite, bitMap.PixelFormat);

                            int   bytesPerPixel  = System.Drawing.Bitmap.GetPixelFormatSize(bitMap.PixelFormat) / 8;
                            int   heightInPixels = bitmapData.Height;
                            int   widthInBytes   = bitmapData.Width * bytesPerPixel;
                            byte *PtrFirstPixel  = (byte *)bitmapData.Scan0;

                            Parallel.For(0, heightInPixels, y =>
                            {
                                byte *currentLine = PtrFirstPixel + (y * bitmapData.Stride);
                                for (int x = 0; x < widthInBytes; x = x + bytesPerPixel)
                                {
                                    var newPixel = PixelOperations.Threshold(Color.FromArgb(currentLine[x],
                                                                                            currentLine[x + 1], currentLine[x + 2]), parameter);
                                    currentLine[x]     = newPixel.R;
                                    currentLine[x + 1] = newPixel.G;
                                    currentLine[x + 2] = newPixel.B;
                                }
                            });
                            bitMap.UnlockBits(bitmapData);
                            image = bitMap;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                newImage?.Dispose();

                throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex);
            }

            return(image);
        }
        private Color SetNewColor(Color color, Color drawingColor)
        {
            var   b           = drawingColor.B;
            var   g           = drawingColor.G;
            var   r           = drawingColor.R;
            Color newColor    = Color.FromArgb(r, g, b);
            var   newColorHSV = PixelOperations.ColorToHSV(newColor);

            newColorHSV.value = color.GetBrightness();
            newColor          = PixelOperations.ColorFromHSV(newColorHSV.hue, newColorHSV.saturation, newColorHSV.value);
            return(newColor);
        }
        private byte[] GetMonohromePixel(byte[] pixel, int byteLength, int coefficient)
        {
            Color color = PixelOperations.TransformPixelToColor(pixel, byteLength);
            Color newColor;

            if ((color.B + color.G + color.R) / 3 < coefficient)
            {
                newColor = SetNewColor(color, secondColor);
            }
            else
            {
                newColor = SetNewColor(color, firstColor);
            }
            pixel = PixelOperations.TransformColorToPixel(newColor, byteLength);
            return(pixel);
        }
        private void ZoomPicture(Bitmap source, Bitmap destination, double xZoom, double yZoom)
        {
            var initData   = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, source.PixelFormat);
            var destData   = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, source.PixelFormat);
            int byteLength = 4;

            if (source.PixelFormat.ToString().Contains("24"))
            {
                byteLength = 3;
            }
            else if (source.PixelFormat.ToString().Contains("16"))
            {
                byteLength = 2;
            }
            // Get the address of the first line
            IntPtr ptr1 = initData.Scan0;
            IntPtr ptr2 = destData.Scan0;

            unsafe
            {
                byte *sourcePtr = (byte *)ptr1.ToPointer();
                byte *destPtr   = (byte *)ptr2.ToPointer();

                for (int i = 0; i < destData.Stride; i += 4)
                {
                    for (int j = 0; j < destination.Height; j++)
                    {
                        int newX = (int)(i / xZoom);
                        int newY = (int)(j / yZoom);
                        if (newX % byteLength != 0)
                        {
                            newX -= newX % byteLength;                         //offset to the first byte of four
                        }
                        var pixel = PixelOperations.GetPixelUnsafe(sourcePtr, initData.Stride, newX, newY, byteLength);
                        PixelOperations.SetPixelUnsafe(destPtr, pixel, destData.Stride, i, j, byteLength);
                    }
                }
            }

            source.UnlockBits(initData);
            destination.UnlockBits(destData);
        }
            internal static void ToVector4 <TPixel>(
                Configuration configuration,
                PixelOperations <TPixel> pixelOperations,
                ReadOnlySpan <TPixel> sourcePixels,
                Span <Vector4> destVectors,
                PixelConversionModifiers modifiers)
                where TPixel : struct, IPixel <TPixel>
            {
                Guard.NotNull(configuration, nameof(configuration));
                Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors));

                int count = sourcePixels.Length;

                // Not worth for small buffers:
                if (count < Vector4ConversionThreshold)
                {
                    Default.UnsafeToVector4(sourcePixels, destVectors, modifiers);

                    return;
                }

                // Using the last quarter of 'destVectors' as a temporary buffer to avoid allocation:
                int countWithoutLastItem                      = count - 1;
                ReadOnlySpan <TPixel> reducedSource           = sourcePixels.Slice(0, countWithoutLastItem);
                Span <Rgba32>         lastQuarterOfDestBuffer = MemoryMarshal.Cast <Vector4, Rgba32>(destVectors).Slice((3 * count) + 1, countWithoutLastItem);

                pixelOperations.ToRgba32(configuration, reducedSource, lastQuarterOfDestBuffer);

                // 'destVectors' and 'lastQuarterOfDestBuffer' are overlapping buffers,
                // but we are always reading/writing at different positions:
                SimdUtils.BulkConvertByteToNormalizedFloat(
                    MemoryMarshal.Cast <Rgba32, byte>(lastQuarterOfDestBuffer),
                    MemoryMarshal.Cast <Vector4, float>(destVectors.Slice(0, countWithoutLastItem)));

                destVectors[countWithoutLastItem] = sourcePixels[countWithoutLastItem].ToVector4();

                // TODO: Investigate optimized 1-pass approach!
                ApplyForwardConversionModifiers(destVectors, modifiers);
            }
            internal static void FromVector4 <TPixel>(
                Configuration configuration,
                PixelOperations <TPixel> pixelOperations,
                Span <Vector4> sourceVectors,
                Span <TPixel> destPixels,
                PixelConversionModifiers modifiers)
                where TPixel : unmanaged, IPixel <TPixel>
            {
                Guard.NotNull(configuration, nameof(configuration));
                Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels));

                int count = sourceVectors.Length;

                // Not worth for small buffers:
                if (count < Vector4ConversionThreshold)
                {
                    Default.UnsafeFromVector4(sourceVectors, destPixels, modifiers);

                    return;
                }

                // TODO: Investigate optimized 1-pass approach!
                ApplyBackwardConversionModifiers(sourceVectors, modifiers);

                // For the opposite direction it's not easy to implement the trick used in RunRgba32CompatibleToVector4Conversion,
                // so let's allocate a temporary buffer as usually:
                using (IMemoryOwner <Rgba32> tempBuffer = configuration.MemoryAllocator.Allocate <Rgba32>(count))
                {
                    Span <Rgba32> tempSpan = tempBuffer.Memory.Span;

                    SimdUtils.NormalizedFloatToByteSaturate(
                        MemoryMarshal.Cast <Vector4, float>(sourceVectors),
                        MemoryMarshal.Cast <Rgba32, byte>(tempSpan));

                    pixelOperations.FromRgba32(configuration, tempSpan, destPixels);
                }
            }
Beispiel #17
0
        /// <summary>
        /// Processes the image.
        /// </summary>
        /// <param name="factory">
        /// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class containing
        /// the image to process.
        /// </param>
        /// <returns>
        /// The processed image from the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class.
        /// </returns>
        public Image ProcessImage(ImageFactory factory)
        {
            Bitmap newImage = null;
            Image  image    = factory.Image;

            try
            {
                Tuple <Color, Color, int> parameters = this.DynamicParameter;
                Color original    = parameters.Item1;
                Color replacement = parameters.Item2;

                // Ensure that color comparison takes any gamma adjustments into consideration.
                if (factory.FixGamma || Math.Abs(factory.CurrentGamma) > 0)
                {
                    original    = PixelOperations.Gamma(original, factory.CurrentGamma);
                    replacement = PixelOperations.Gamma(replacement, factory.CurrentGamma);
                }

                byte originalR = original.R;
                byte originalG = original.G;
                byte originalB = original.B;
                byte originalA = original.A;

                byte replacementR = replacement.R;
                byte replacementG = replacement.G;
                byte replacementB = replacement.B;
                byte replacementA = replacement.A;

                int fuzziness = parameters.Item3;

                byte minR = (originalR - fuzziness).ToByte();
                byte minG = (originalG - fuzziness).ToByte();
                byte minB = (originalB - fuzziness).ToByte();

                byte maxR = (originalR + fuzziness).ToByte();
                byte maxG = (originalG + fuzziness).ToByte();
                byte maxB = (originalB + fuzziness).ToByte();

                newImage = new Bitmap(image);
                int width  = image.Width;
                int height = image.Height;

                using (FastBitmap fastBitmap = new FastBitmap(newImage))
                {
                    Parallel.For(
                        0,
                        height,
                        y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            // Get the pixel color.
                            // ReSharper disable once AccessToDisposedClosure
                            Color currentColor = fastBitmap.GetPixel(x, y);
                            byte currentR      = currentColor.R;
                            byte currentG      = currentColor.G;
                            byte currentB      = currentColor.B;
                            byte currentA      = currentColor.A;

                            // Test whether it is in the expected range.
                            if (ImageMaths.InRange(currentR, minR, maxR))
                            {
                                if (ImageMaths.InRange(currentG, minG, maxG))
                                {
                                    if (ImageMaths.InRange(currentB, minB, maxB))
                                    {
                                        // Ensure the values are within an acceptable byte range
                                        // and set the new value.
                                        byte r = (originalR - currentR + replacementR).ToByte();
                                        byte g = (originalG - currentG + replacementG).ToByte();
                                        byte b = (originalB - currentB + replacementB).ToByte();

                                        // Allow replacement with transparent color.
                                        byte a = currentA;
                                        if (originalA != replacementA)
                                        {
                                            a = replacementA;
                                        }

                                        // ReSharper disable once AccessToDisposedClosure
                                        fastBitmap.SetPixel(x, y, Color.FromArgb(a, r, g, b));
                                    }
                                }
                            }
                        }
                    });
                }

                image.Dispose();
                image = newImage;
            }
            catch (Exception ex)
            {
                if (newImage != null)
                {
                    newImage.Dispose();
                }

                throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex);
            }

            return(image);
        }
Beispiel #18
0
        private void DrawSegment(int x0, int x1, int y0, int y1, Color color1, Color color2)
        {
            var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            unsafe
            {
                byte *ptr = (byte *)data.Scan0.ToPointer();


                int dx = (x1 > x0) ? (x1 - x0) : (x0 - x1);
                int dy = (y1 > y0) ? (y1 - y0) : (y0 - y1);
                //Направление приращения
                int sx = (x1 >= x0) ? (1) : (-1);
                int sy = (y1 >= y0) ? (1) : (-1);

                if (dy < dx)
                {
                    int   d     = (dy << 1) - dx;
                    int   d1    = dy << 1;
                    int   d2    = (dy - dx) << 1;
                    Color color = GetInterpolateColor(color1, color2, 0);
                    PixelOperations.SetPixelUnsafe(ptr, new byte[] { color.B, color.G, color.R, 255 }, data.Stride, x0 * 4, y0, 4);
                    int x = x0 + sx;
                    int y = y0;
                    for (int i = 1; i <= dx; i++)
                    {
                        if (d > 0)
                        {
                            d += d2;
                            y += sy;
                        }
                        else
                        {
                            d += d1;
                        }
                        color = GetInterpolateColor(color1, color2, (i * 1.0 / dx));
                        PixelOperations.SetPixelUnsafe(ptr, new byte[] { color.B, color.G, color.R, 255 }, data.Stride, x * 4, y, 4);
                        x += sx;
                    }
                }
                else
                {
                    int   d     = (dx << 1) - dy;
                    int   d1    = dx << 1;
                    int   d2    = (dx - dy) << 1;
                    Color color = GetInterpolateColor(color1, color2, 0);
                    PixelOperations.SetPixelUnsafe(ptr, new byte[] { color.B, color.G, color.R, 255 }, data.Stride, x0 * 4, y0, 4);
                    int x = x0;
                    int y = y0 + sy;
                    for (int i = 1; i <= dy; i++)
                    {
                        if (d > 0)
                        {
                            d += d2;
                            x += sx;
                        }
                        else
                        {
                            d += d1;
                        }
                        color = GetInterpolateColor(color1, color2, (i * 1.0 / dy));
                        PixelOperations.SetPixelUnsafe(ptr, new byte[] { color.B, color.G, color.R, 255 }, data.Stride, x * 4, y, 4);
                        y += sy;
                    }
                }
            }

            bitmap.UnlockBits(data);
            pictureBox1.Image = bitmap;
        }
Beispiel #19
0
        public static Bitmap ResizeBilinear(Bitmap source, int width, int height, Rectangle destinationRectangle, bool fixGamma)
        {
            int sourceWidth  = source.Width;
            int sourceHeight = source.Height;
            int startX       = destinationRectangle.X;
            int startY       = destinationRectangle.Y;
            int endX         = destinationRectangle.Width + startX;
            int endY         = destinationRectangle.Height + startY;

            // Scaling factors
            double widthFactor  = sourceWidth / (double)destinationRectangle.Width;
            double heightFactor = sourceHeight / (double)destinationRectangle.Height;

            // Width and height decreased by 1
            int maxHeight = sourceHeight - 1;
            int maxWidth  = sourceWidth - 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))
                {
                    // For each column
                    Parallel.For(
                        startY,
                        endY,
                        y =>
                    {
                        if (y >= 0 && y < height)
                        {
                            // Y coordinates of source points
                            double originY = (y - startY) * heightFactor;
                            int originY1   = (int)originY;
                            int originY2   = (originY1 == maxHeight) ? originY1 : originY1 + 1;
                            double dy1     = originY - originY1;
                            double dy2     = 1.0 - dy1;

                            // Get temp pointers
                            int temp1 = originY1;
                            int temp2 = originY2;

                            // For every column.
                            for (int x = startX; x < endX; x++)
                            {
                                if (x >= 0 && x < width)
                                {
                                    // X coordinates of source points
                                    double originX = (x - startX) * widthFactor;
                                    int originX1   = (int)originX;
                                    int originX2   = (originX1 == maxWidth) ? originX1 : originX1 + 1;
                                    double dx1     = originX - originX1;
                                    double dx2     = 1.0 - dx1;

                                    // Get four pixels to sample from.
                                    Color sourceColor1 = sourceBitmap.GetPixel(originX1, temp1);
                                    Color sourceColor2 = sourceBitmap.GetPixel(originX2, temp1);
                                    Color sourceColor3 = sourceBitmap.GetPixel(originX1, temp2);
                                    Color sourceColor4 = sourceBitmap.GetPixel(originX2, temp2);

                                    if (fixGamma)
                                    {
                                        sourceColor1 = PixelOperations.ToLinear(sourceColor1);
                                        sourceColor2 = PixelOperations.ToLinear(sourceColor2);
                                        sourceColor3 = PixelOperations.ToLinear(sourceColor3);
                                        sourceColor4 = PixelOperations.ToLinear(sourceColor4);
                                    }

                                    // Get four points in red channel.
                                    int p1 = sourceColor1.R;
                                    int p2 = sourceColor2.R;
                                    int p3 = sourceColor3.R;
                                    int p4 = sourceColor4.R;

                                    int r = (int)((dy2 * ((dx2 * p1) + (dx1 * p2))) + (dy1 * ((dx2 * p3) + (dx1 * p4))));

                                    // Get four points in green channel.
                                    p1 = sourceColor1.G;
                                    p2 = sourceColor2.G;
                                    p3 = sourceColor3.G;
                                    p4 = sourceColor4.G;

                                    int g = (int)((dy2 * ((dx2 * p1) + (dx1 * p2))) + (dy1 * ((dx2 * p3) + (dx1 * p4))));

                                    // Get four points in blue channel
                                    p1 = sourceColor1.B;
                                    p2 = sourceColor2.B;
                                    p3 = sourceColor3.B;
                                    p4 = sourceColor4.B;

                                    int b = (int)((dy2 * ((dx2 * p1) + (dx1 * p2))) + (dy1 * ((dx2 * p3) + (dx1 * p4))));

                                    // Get four points in alpha channel
                                    p1 = sourceColor1.A;
                                    p2 = sourceColor2.A;
                                    p3 = sourceColor3.A;
                                    p4 = sourceColor4.A;

                                    int a = (int)((dy2 * ((dx2 * p1) + (dx1 * p2))) + (dy1 * ((dx2 * p3) + (dx1 * p4))));

                                    Color destinationColor = Color.FromArgb(
                                        a.ToByte(),
                                        r.ToByte(),
                                        g.ToByte(),
                                        b.ToByte());

                                    if (fixGamma)
                                    {
                                        destinationColor = PixelOperations.ToSRGB(destinationColor);
                                    }

                                    destinationBitmap.SetPixel(x, y, destinationColor);
                                }
                            }
                        }
                    });
                }
            }

            source.Dispose();
            return(destination);
        }
Beispiel #20
0
        internal static Bitmap ResizeLanczos(Bitmap source, int width, int height, Rectangle destinationRectangle, bool fixGamma = true)
        {
            int sourceWidth  = source.Width;
            int sourceHeight = source.Height;
            int startX       = destinationRectangle.X;
            int startY       = destinationRectangle.Y;
            int endX         = destinationRectangle.Width + startX;
            int endY         = destinationRectangle.Height + startY;

            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))
                {
                    // Scaling factors
                    double widthFactor  = sourceWidth / (double)destinationRectangle.Width;
                    double heightFactor = sourceHeight / (double)destinationRectangle.Height;

                    // Width and height decreased by 1
                    int maxHeight = sourceHeight - 1;
                    int maxWidth  = sourceWidth - 1;

                    // For each column
                    Parallel.For(
                        startY,
                        endY,
                        y =>
                    {
                        if (y >= 0 && y < height)
                        {
                            // Y coordinates of source points.
                            double originY = ((y - startY) * heightFactor) - 0.5;
                            int originY1   = (int)originY;
                            double dy      = originY - originY1;

                            // For each row.
                            for (int x = startX; x < endX; x++)
                            {
                                if (x >= 0 && x < width)
                                {
                                    // X coordinates of source points.
                                    double originX = ((x - startX) * widthFactor) - 0.5f;
                                    int originX1   = (int)originX;
                                    double dx      = originX - originX1;

                                    // Destination color components
                                    double r = 0;
                                    double g = 0;
                                    double b = 0;
                                    double a = 0;

                                    for (int n = -3; n < 6; n++)
                                    {
                                        // Get Y cooefficient
                                        double k1 = Interpolation.LanczosKernel3(dy - n);

                                        int originY2 = originY1 + n;
                                        if (originY2 < 0)
                                        {
                                            originY2 = 0;
                                        }

                                        if (originY2 > maxHeight)
                                        {
                                            originY2 = maxHeight;
                                        }

                                        for (int m = -3; m < 6; m++)
                                        {
                                            // Get X cooefficient
                                            double k2 = k1 * Interpolation.LanczosKernel3(m - dx);

                                            int originX2 = originX1 + m;
                                            if (originX2 < 0)
                                            {
                                                originX2 = 0;
                                            }

                                            if (originX2 > maxWidth)
                                            {
                                                originX2 = maxWidth;
                                            }

                                            // ReSharper disable once AccessToDisposedClosure
                                            Color sourceColor = sourceBitmap.GetPixel(originX2, originY2);

                                            if (fixGamma)
                                            {
                                                sourceColor = PixelOperations.ToLinear(sourceColor);
                                            }

                                            r += k2 * sourceColor.R;
                                            g += k2 * sourceColor.G;
                                            b += k2 * sourceColor.B;
                                            a += k2 * sourceColor.A;
                                        }
                                    }

                                    Color destinationColor = Color.FromArgb(
                                        a.ToByte(),
                                        r.ToByte(),
                                        g.ToByte(),
                                        b.ToByte());

                                    if (fixGamma)
                                    {
                                        destinationColor = PixelOperations.ToSRGB(destinationColor);
                                    }

                                    // ReSharper disable once AccessToDisposedClosure
                                    destinationBitmap.SetPixel(x, y, destinationColor);
                                }
                            }
                        }
                    });
                }
            }

            source.Dispose();
            return(destination);
        }
Beispiel #21
0
        /// <summary>
        /// Processes the given kernel to produce an array of pixels representing a bitmap.
        /// </summary>
        /// <param name="source">The image to process.</param>
        /// <param name="kernel">The Gaussian kernel to use when performing the method</param>
        /// <param name="fixGamma">Whether to process the image using the linear color space.</param>
        /// <returns>A processed bitmap.</returns>
        public Bitmap ProcessKernel(Bitmap source, double[,] kernel, bool fixGamma)
        {
            int    width       = source.Width;
            int    height      = source.Height;
            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))
                {
                    int kernelLength = kernel.GetLength(0);
                    int radius       = kernelLength >> 1;
                    int kernelSize   = kernelLength * kernelLength;
                    int threshold    = this.Threshold;

                    // For each line
                    Parallel.For(
                        0,
                        height,
                        y =>
                    {
                        // For each pixel
                        for (int x = 0; x < width; x++)
                        {
                            // The number of kernel elements taken into account
                            int processedKernelSize;

                            // Colour sums
                            double blue;
                            double alpha;
                            double divider;
                            double green;
                            double red = green = blue = alpha = divider = processedKernelSize = 0;

                            // For each kernel row
                            for (int i = 0; i < kernelLength; 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 each kernel column
                                for (int j = 0; j < kernelLength; j++)
                                {
                                    int jr      = j - radius;
                                    int offsetX = x + jr;

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

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

                                        if (fixGamma)
                                        {
                                            sourceColor = PixelOperations.ToLinear(sourceColor);
                                        }

                                        double k = kernel[i, j];
                                        divider += k;

                                        red   += k * sourceColor.R;
                                        green += k * sourceColor.G;
                                        blue  += k * sourceColor.B;
                                        alpha += k * sourceColor.A;

                                        processedKernelSize++;
                                    }
                                }
                            }

                            // Check to see if all kernel elements were processed
                            if (processedKernelSize == kernelSize)
                            {
                                // All kernel elements are processed; we are not on the edge.
                                divider = this.Divider;
                            }
                            else
                            {
                                // We are on an edge; do we need to use dynamic divider or not?
                                if (!this.UseDynamicDividerForEdges)
                                {
                                    // Apply the set divider.
                                    divider = this.Divider;
                                }
                            }

                            // Check and apply the divider
                            if ((long)divider != 0)
                            {
                                red   /= divider;
                                green /= divider;
                                blue  /= divider;
                                alpha /= divider;
                            }

                            // Add any applicable threshold.
                            red   += threshold;
                            green += threshold;
                            blue  += threshold;
                            alpha += threshold;

                            Color destinationColor = Color.FromArgb(alpha.ToByte(), red.ToByte(), green.ToByte(), blue.ToByte());

                            if (fixGamma)
                            {
                                destinationColor = PixelOperations.ToSRGB(destinationColor);
                            }

                            // ReSharper disable once AccessToDisposedClosure
                            destinationBitmap.SetPixel(x, y, destinationColor);
                        }
                    });
                }
            }

            source.Dispose();
            return(destination);
        }
Beispiel #22
0
        /// <summary>
        /// Processes the given kernel to produce an array of pixels representing a bitmap.
        /// </summary>
        /// <param name="source">The image to process.</param>
        /// <param name="kernel">The Gaussian kernel to use when performing the method</param>
        /// <param name="fixGamma">Whether to process the image using the linear color space.</param>
        /// <returns>A processed bitmap.</returns>
        public Color[,] ProcessKernel(Color[,] source, double[,] kernel, bool fixGamma)
        {
            var width  = source.GetLength(0);
            var height = source.GetLength(1);

            var kernelLength = kernel.GetLength(0);
            var radius       = kernelLength >> 1;
            var kernelSize   = kernelLength * kernelLength;
            var threshold    = Threshold;

            var destination = new Color[width, height];

            // For each line
            Parallel.For(
                0,
                height,
                y =>
            {
                // For each pixel
                for (var x = 0; x < width; x++)
                {
                    // The number of kernel elements taken into account
                    int processedKernelSize;

                    // Colour sums
                    double blue;
                    double alpha;
                    double divider;
                    double green;
                    var red = green = blue = alpha = divider = processedKernelSize = 0;

                    // For each kernel row
                    for (var i = 0; i < kernelLength; i++)
                    {
                        var ir      = i - radius;
                        var offsetY = y + ir;

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

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

                        // For each kernel column
                        for (var j = 0; j < kernelLength; j++)
                        {
                            var jr      = j - radius;
                            var offsetX = x + jr;

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

                            if (offsetX < width)
                            {
                                // ReSharper disable once AccessToDisposedClosure
                                var sourceColor = source[offsetX, offsetY];

                                if (fixGamma)
                                {
                                    sourceColor = PixelOperations.ToLinear(sourceColor);
                                }

                                var k    = kernel[i, j];
                                divider += k;

                                red   += k * sourceColor.R;
                                green += k * sourceColor.G;
                                blue  += k * sourceColor.B;
                                alpha += k * sourceColor.A;

                                processedKernelSize++;
                            }
                        }
                    }

                    // Check to see if all kernel elements were processed
                    if (processedKernelSize == kernelSize)
                    {
                        // All kernel elements are processed; we are not on the edge.
                        divider = Divider;
                    }
                    else
                    {
                        // We are on an edge; do we need to use dynamic divider or not?
                        if (!UseDynamicDividerForEdges)
                        {
                            // Apply the set divider.
                            divider = Divider;
                        }
                    }

                    // Check and apply the divider
                    if ((long)divider != 0)
                    {
                        red   /= divider;
                        green /= divider;
                        blue  /= divider;
                        alpha /= divider;
                    }

                    // Add any applicable threshold.
                    red   += threshold;
                    green += threshold;
                    blue  += threshold;
                    alpha += threshold;

                    var destinationColor = Color.FromArgb(alpha.ToByte(), red.ToByte(), green.ToByte(), blue.ToByte());

                    if (fixGamma)
                    {
                        destinationColor = PixelOperations.ToSRGB(destinationColor);
                    }

                    destination[x, y] = destinationColor;
                }
            });

            return(destination);
        }
Beispiel #23
0
        public static Bitmap ResizeBicubicHighQuality(Bitmap source, int width, int height, Rectangle destinationRectangle, bool fixGamma)
        {
            int sourceWidth  = source.Width;
            int sourceHeight = source.Height;
            int startX       = destinationRectangle.X;
            int startY       = destinationRectangle.Y;
            int endX         = destinationRectangle.Width + startX;
            int endY         = destinationRectangle.Height + startY;

            // Scaling factors
            double widthFactor  = sourceWidth / (double)destinationRectangle.Width;
            double heightFactor = sourceHeight / (double)destinationRectangle.Height;

            // Width and height decreased by 1
            int maxHeight = sourceHeight - 1;
            int maxWidth  = sourceWidth - 1;

            Bitmap destination = new Bitmap(width, height, PixelFormat.Format32bppPArgb);

            destination.SetResolution(source.HorizontalResolution, source.VerticalResolution);

            // The radius for pre blurring the images.
            // We only apply this for very small images.
            int radius = 0;

            if (width <= 150 && height <= 150)
            {
                radius = 4;
            }

            using (FastBitmap sourceBitmap = new FastBitmap(source))
            {
                using (FastBitmap destinationBitmap = new FastBitmap(destination))
                {
                    // For each column
                    Parallel.For(
                        startY,
                        endY,
                        y =>
                    {
                        if (y >= 0 && y < height)
                        {
                            // Y coordinates of source points.
                            double originY = ((y - startY) * heightFactor) - 0.5;
                            int originY1   = (int)originY;
                            double dy      = originY - originY1;

                            // Houses colors for blurring.
                            Color[,] sourceColors = new Color[4, 4];

                            // For each row.
                            for (int x = startX; x < endX; x++)
                            {
                                if (x >= 0 && x < width)
                                {
                                    // X coordinates of source points.
                                    double originX = ((x - startX) * widthFactor) - 0.5f;
                                    int originX1   = (int)originX;
                                    double dx      = originX - originX1;

                                    // Destination color components
                                    double r = 0;
                                    double g = 0;
                                    double b = 0;
                                    double a = 0;

                                    for (int yy = -1; yy < 3; yy++)
                                    {
                                        int originY2 = originY1 + yy;
                                        if (originY2 < 0)
                                        {
                                            originY2 = 0;
                                        }

                                        if (originY2 > maxHeight)
                                        {
                                            originY2 = maxHeight;
                                        }

                                        for (int xx = -1; xx < 3; xx++)
                                        {
                                            int originX2 = originX1 + xx;
                                            if (originX2 < 0)
                                            {
                                                originX2 = 0;
                                            }

                                            if (originX2 > maxWidth)
                                            {
                                                originX2 = maxWidth;
                                            }

                                            Color sourceColor = sourceBitmap.GetPixel(originX2, originY2);

                                            sourceColors[xx + 1, yy + 1] = sourceColor;
                                        }
                                    }

                                    // Blur the colors.
                                    if (radius > 0)
                                    {
                                        sourceColors = BoxBlur(sourceColors, radius, fixGamma);
                                    }

                                    // Do the resize.
                                    for (int yy = -1; yy < 3; yy++)
                                    {
                                        // Get Y cooefficient
                                        double kernel1 = Interpolation.BiCubicBSplineKernel(dy - yy);

                                        for (int xx = -1; xx < 3; xx++)
                                        {
                                            // Get X cooefficient
                                            double kernel2 = kernel1 * Interpolation.BiCubicBSplineKernel(xx - dx);

                                            Color sourceColor = sourceColors[xx + 1, yy + 1];

                                            if (fixGamma)
                                            {
                                                sourceColor = PixelOperations.ToLinear(sourceColor);
                                            }

                                            r += kernel2 * sourceColor.R;
                                            g += kernel2 * sourceColor.G;
                                            b += kernel2 * sourceColor.B;
                                            a += kernel2 * sourceColor.A;
                                        }
                                    }

                                    Color destinationColor = Color.FromArgb(
                                        a.ToByte(),
                                        r.ToByte(),
                                        g.ToByte(),
                                        b.ToByte());

                                    if (fixGamma)
                                    {
                                        destinationColor = PixelOperations.ToSRGB(destinationColor);
                                    }

                                    destinationBitmap.SetPixel(x, y, destinationColor);
                                }
                            }
                        }
                    });
                }
            }

            source.Dispose();
            return(destination);
        }