コード例 #1
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);
        }