Allows fast access to System.Drawing.Bitmap's pixel data.
Наследование: IDisposable
Пример #1
0
 public void ApplyFilter(FastBitmap image)
 {
     for (var i = 0; i < image.Height; ++i)
     {
         for (var j = 0; j < image.Width; ++j)
         {
             var pixel = image.GetPixel(j, i);
             if (pixel.R + pixel.G + pixel.B > 300)
             {
                 image.SetPixel(j, i, System.Drawing.Color.FromArgb(200, 255, 255));
             }
             else
             {
                 image.SetPixel(j, i, System.Drawing.Color.FromArgb(255, 0, 0, 30));
             }
         }
     }
 }
Пример #2
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>
        /// <returns>A processed bitmap.</returns>
        public Bitmap ProcessKernel(Bitmap source, double[,] kernel)
        {
            int    width       = source.Width;
            int    height      = source.Height;
            Bitmap destination = new Bitmap(width, height);

            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 color = sourceBitmap.GetPixel(offsetX, offsetY);
                                        double k    = kernel[i, j];
                                        divider    += k;

                                        red   += k * color.R;
                                        green += k * color.G;
                                        blue  += k * color.B;
                                        alpha += k * color.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;

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

            return(destination);
        }
Пример #3
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);
        }
Пример #4
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);
        }
Пример #5
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);
        }