Beispiel #1
0
        /// <summary>
        /// Adjust brightness and contrast of image
        /// </summary>
        public static unsafe Bitmap AdjustBrightnessContrast(Bitmap image, Rectangle rect, int brightness, int contrast)
        {
            int multiply;
            int divide;

            byte[] rgbTable = new byte[65536];

            if (contrast < 0)
            {
                multiply = contrast + 100;
                divide   = 100;
            }
            else if (contrast > 0)
            {
                multiply = 100;
                divide   = 100 - contrast;
            }
            else
            {
                multiply = 1;
                divide   = 1;
            }

            if (divide == 0)
            {
                for (int intensity = 0; intensity < 256; ++intensity)
                {
                    if (intensity + brightness < 128)
                    {
                        rgbTable[intensity] = 0;
                    }
                    else
                    {
                        rgbTable[intensity] = 255;
                    }
                }
            }
            else if (divide == 100)
            {
                for (int intensity = 0; intensity < 256; ++intensity)
                {
                    int shift = (intensity - 127) * multiply / divide + 127 - intensity + brightness;

                    for (int col = 0; col < 256; ++col)
                    {
                        int index = (intensity * 256) + col;
                        rgbTable[index] = ClampToByte(col + shift);
                    }
                }
            }
            else
            {
                for (int intensity = 0; intensity < 256; ++intensity)
                {
                    int shift = (intensity - 127 + brightness) * multiply / divide + 127 - intensity;

                    for (int col = 0; col < 256; ++col)
                    {
                        int index = (intensity * 256) + col;
                        rgbTable[index] = ClampToByte(col + shift);
                    }
                }
            }

            int        pixelSize = Image.GetPixelFormatSize(image.PixelFormat) / 8;
            Bitmap     dest      = (Bitmap)image.Clone();
            BitmapData imgDat    = dest.LockBits(rect, ImageLockMode.ReadWrite, dest.PixelFormat);

            int startX = rect.Left;
            int startY = rect.Top;
            int stopX  = startX + rect.Width;
            int stopY  = startY + rect.Height;
            int offset = imgDat.Stride - rect.Width * pixelSize;

            RGB rgb = new RGB();

            // do the job
            byte *img = (byte *)imgDat.Scan0;

            // align pointer to the first pixel to process
            img += (startY * imgDat.Stride + startX * pixelSize);

            if (divide == 0)
            {
                // for each row
                for (int y = startY; y < stopY; y++)
                {
                    // for each pixel
                    for (int x = startX; x < stopX; x++, img += pixelSize)
                    {
                        int  i    = (int)((7471 * img[RGB.B] + 38470 * img[RGB.G] + 19595 * img[RGB.R]) >> 16);
                        uint c    = rgbTable[i];
                        uint bgra = (uint)img[RGB.B] + ((uint)img[RGB.G] << 8) + ((uint)img[RGB.R] << 16);
                        bgra = (bgra & 0xff000000) | c | (c << 8) | (c << 16);

                        img[RGB.R] = (byte)(bgra & 0x000000ff);
                        img[RGB.G] = (byte)((bgra & 0x0000ff00) >> 8);
                        img[RGB.B] = (byte)((bgra & 0x00ff0000) >> 16);
                    }
                    img += offset;
                }
            }
            else
            {
                // for each row
                for (int y = startY; y < stopY; y++)
                {
                    // for each pixel
                    for (int x = startX; x < stopX; x++, img += pixelSize)
                    {
                        int i          = (int)((7471 * img[RGB.B] + 38470 * img[RGB.G] + 19595 * img[RGB.R]) >> 16);
                        int shiftIndex = i * 256;
                        img[RGB.R] = rgbTable[shiftIndex + img[RGB.R]];
                        img[RGB.G] = rgbTable[shiftIndex + img[RGB.G]];
                        img[RGB.B] = rgbTable[shiftIndex + img[RGB.B]];
                    }
                    img += offset;
                }
            }

            dest.UnlockBits(imgDat);

            return(dest);
        }
Beispiel #2
0
        /// <summary>
        /// Adjust hue saturation lightness of image
        /// </summary>
        public static unsafe Bitmap AdjustHSL(Bitmap image, Rectangle rect, int hue, int saturation, int lightness)
        {
            int        pixelSize = Image.GetPixelFormatSize(image.PixelFormat) / 8;
            Bitmap     dest      = (Bitmap)image.Clone();
            BitmapData imgDat    = dest.LockBits(rect, ImageLockMode.ReadWrite, dest.PixelFormat);

            int startX = rect.Left;
            int startY = rect.Top;
            int stopX  = startX + rect.Width;
            int stopY  = startY + rect.Height;
            int offset = imgDat.Stride - rect.Width * pixelSize;

            RGB rgb = new RGB();
            HSL hsl = new HSL();

            // do the job
            byte *img = (byte *)imgDat.Scan0;

            // align pointer to the first pixel to process
            img += (startY * imgDat.Stride + startX * pixelSize);

            int intensity;
            int a, invA;
            RGB blendColor;

            if (lightness > 0)
            {
                a          = (int)((lightness * 255) / 100);
                blendColor = new RGB(255, 255, 255);
            }
            else
            {
                a          = (int)((-lightness * 255) / 100);
                blendColor = new RGB(0, 0, 0);
            }
            invA = 255 - a;

            if (lightness == 0)
            {
                // for each row
                for (int y = startY; y < stopY; y++)
                {
                    // for each pixel
                    for (int x = startX; x < stopX; x++, img += pixelSize)
                    {
                        // adjust saturation
                        intensity = (int)((7471 * img[RGB.B] + 38470 * img[RGB.G] + 19595 * img[RGB.R]) >> 16);
                        rgb.Red   = ClampToByte((intensity * 1024 + (img[RGB.R] - intensity) * saturation) >> 10);
                        rgb.Green = ClampToByte((intensity * 1024 + (img[RGB.G] - intensity) * saturation) >> 10);
                        rgb.Blue  = ClampToByte((intensity * 1024 + (img[RGB.B] - intensity) * saturation) >> 10);

                        // adjust hue
                        hsl      = HSL.FromRGB(rgb);
                        hsl.Hue += hue;
                        if (hsl.Hue < 0)
                        {
                            hsl.Hue += 360;
                        }
                        else if (hsl.Hue > 360)
                        {
                            hsl.Hue -= 360;
                        }
                        rgb = hsl.ToRGB();

                        img[RGB.R] = rgb.Red;
                        img[RGB.G] = rgb.Green;
                        img[RGB.B] = rgb.Blue;
                    }
                    img += offset;
                }
            }
            else
            {
                // for each row
                for (int y = startY; y < stopY; y++)
                {
                    // for each pixel
                    for (int x = startX; x < stopX; x++, img += pixelSize)
                    {
                        // adjust saturation
                        intensity = (int)((7471 * img[RGB.B] + 38470 * img[RGB.G] + 19595 * img[RGB.R]) >> 16);
                        rgb.Red   = ClampToByte((intensity * 1024 + (img[RGB.R] - intensity) * saturation) >> 10);
                        rgb.Green = ClampToByte((intensity * 1024 + (img[RGB.G] - intensity) * saturation) >> 10);
                        rgb.Blue  = ClampToByte((intensity * 1024 + (img[RGB.B] - intensity) * saturation) >> 10);

                        // adjust hue
                        hsl      = HSL.FromRGB(rgb);
                        hsl.Hue += hue;
                        if (hsl.Hue < 0)
                        {
                            hsl.Hue += 360;
                        }
                        else if (hsl.Hue > 360)
                        {
                            hsl.Hue -= 360;
                        }
                        rgb = hsl.ToRGB();

                        // adjust lightness
                        img[RGB.R] = (byte)(((rgb.Red * invA) + (blendColor.Red * a)) / 256);
                        img[RGB.G] = (byte)(((rgb.Green * invA) + (blendColor.Green * a)) / 256);
                        img[RGB.B] = (byte)(((rgb.Blue * invA) + (blendColor.Blue * a)) / 256);
                    }
                    img += offset;
                }
            }

            dest.UnlockBits(imgDat);

            return(dest);
        }
Beispiel #3
0
        /// <summary>
        /// Stretch HSV histogram to create new image
        /// </summary>
        public static unsafe Bitmap HistogramStretchHSV(Bitmap image, Rectangle rect)
        {
            Bitmap     dest   = (Bitmap)image.Clone();
            BitmapData srcDat = image.LockBits(rect, ImageLockMode.ReadOnly, image.PixelFormat);
            BitmapData dstDat = dest.LockBits(rect, ImageLockMode.ReadWrite, dest.PixelFormat);

            int width  = rect.Width;
            int height = rect.Height;
            int stride = srcDat.Stride;

            // get pixel size
            int pixelSize = (image.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;

            int offset = stride - width * pixelSize;

            // do the job
            byte *src = (byte *)srcDat.Scan0.ToPointer();
            byte *dst = (byte *)dstDat.Scan0.ToPointer();

            int pix_num = width * height;           //縦×横

            int[] num_b = new int[512];
            int   min_per, max_per;
            int   per1  = pix_num / 100;
            int   per99 = pix_num / 100 * 99;

            int[] aryH = new int[pix_num];
            int[] aryS = new int[pix_num];
            int[] aryV = new int[pix_num];
            int   maxH, maxS, maxV;
            int   minV;

            maxH = maxS = maxV = 0;
            minV = 255;

            int    tmp_pix, last_pix;
            double ratio;
            int    pos;
            int    count_i = 0;
            int    sum     = 0;

            RGB rgb = new RGB();
            HSV hsv = new HSV();

            // RGB histograms
            // for each row
            for (int y = 0; y < height; y++)
            {
                // for each pixel
                for (int x = 0; x < width; x++, src += pixelSize)
                {
                    rgb.Red   = src[RGB.R];
                    rgb.Green = src[RGB.G];
                    rgb.Blue  = src[RGB.B];
                    hsv       = HSV.FromRGB(rgb);

                    pos       = y * width + x;
                    aryH[pos] = hsv.Hue;
                    aryS[pos] = hsv.Saturation;
                    aryV[pos] = hsv.Value;

                    if (hsv.Hue > maxH)
                    {
                        maxH = hsv.Hue;
                    }
                    if (hsv.Saturation > maxS)
                    {
                        maxS = hsv.Saturation;
                    }
                    if (hsv.Value > maxV)
                    {
                        maxV = hsv.Value;
                    }
                    if (hsv.Value < minV)
                    {
                        minV = hsv.Value;
                    }
                }
                src += offset;
            }

            // histogram
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++, src += pixelSize)
                {
                    num_b[aryV[y * width + x]]++;
                }
            }

            do
            {
                sum += num_b[count_i++];
            } while (sum < per1);
            min_per = count_i - 1;

            do
            {
                sum += num_b[count_i++];
            } while (sum < per99);
            max_per = count_i - 1;
            ratio   = (double)(511.0 / (max_per - min_per));

            // stretch histogram
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++, src += pixelSize)
                {
                    pos     = y * width + x;
                    tmp_pix = aryV[pos];

                    if (tmp_pix <= min_per)
                    {
                        last_pix = 0;
                    }
                    else if (tmp_pix >= max_per)
                    {
                        last_pix = 511;
                    }
                    else
                    {
                        last_pix = (int)((tmp_pix - min_per) * ratio);
                    }

                    if (last_pix < 0)
                    {
                        aryV[pos] = 0;
                    }
                    else if (last_pix >= 511)
                    {
                        aryV[pos] = 511;
                    }
                    else
                    {
                        aryV[pos] = last_pix;
                    }
                }
            }

            // for each row
            for (int y = 0; y < height; y++)
            {
                // for each pixel
                for (int x = 0; x < width; x++, src += pixelSize, dst += pixelSize)
                {
                    pos            = y * width + x;
                    hsv.Hue        = aryH[pos];
                    hsv.Saturation = aryS[pos];
                    hsv.Value      = aryV[pos];

                    HSV.ToRGB(hsv, rgb);

                    dst[RGB.R] = rgb.Red;
                    dst[RGB.G] = rgb.Green;
                    dst[RGB.B] = rgb.Blue;
                }
                src += offset;
                dst += offset;
            }

            image.UnlockBits(srcDat);
            dest.UnlockBits(dstDat);

            return(dest);
        }