/// <summary> /// Selection based on pixel similarity in LAB color space /// </summary> public static unsafe Bitmap Similiar_LAB(Bitmap image, Rectangle rect, List <LAB> labs, int similarity) { Bitmap dest = (Bitmap)image.Clone(); if (labs.Count == 0) { return(dest); } 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(); //L = 0~255 //A = -255~255 = 0~511 //B = -255~255 = 0~511 const int LAB_num = 256 + 512 + 512; int[] table_mix = new int[LAB_num]; for (int i = 0; i < LAB_num; i++) { table_mix[i] = -1; } int total_l; foreach (LAB lab in labs) { total_l = (int)(lab.Lightness + lab.A + lab.B + 510); for (int i = 0; i < similarity / 2; i++) { if ((total_l + i) < LAB_num) { table_mix[total_l + i] = 1; } if ((total_l - i) >= 0) { table_mix[total_l - i] = 1; } } } int koba; // for each row for (int y = 0; y < height; y++) { // for each pixel for (int x = 0; x < width; x++, src += pixelSize, dst += pixelSize) { LAB lab = LAB.FromRGB(new RGB(src[RGB.R], src[RGB.G], src[RGB.B])); koba = (int)(lab.Lightness + lab.A + lab.B + 510); if (table_mix[koba] == 1) { dst[RGB.R] = dst[RGB.G] = dst[RGB.B] = 0; } else { dst[RGB.R] = dst[RGB.G] = dst[RGB.B] = 255; } } src += offset; dst += offset; } image.UnlockBits(srcDat); dest.UnlockBits(dstDat); return(dest); }
/// <summary> /// Selection based on pixel similarity in LAB color space /// </summary> public static unsafe Bitmap Similiar_LABAver(Bitmap image, Rectangle rect, List <LAB> labs, int similarity) { Bitmap dest = (Bitmap)image.Clone(); if (labs.Count == 0) { return(dest); } 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(); //L = 0~255 //A = -255~255 //B = -255~255 int sumL, sumA, sumB; int averL, averA, averB; int minL, minA, minB; int maxL, maxA, maxB; sumL = sumA = sumB = 0; foreach (LAB lab in labs) { sumL += lab.Lightness; sumA += lab.A; sumB += lab.B; } averL = sumL / labs.Count; averA = sumA / labs.Count; averB = sumB / labs.Count; minL = Math.Max(averL - similarity / 2, 0); minA = Math.Max(averA - similarity / 2, -255); minB = Math.Max(averB - similarity / 2, -255); maxL = Math.Min(averL + similarity / 2, 255); maxA = Math.Min(averA + similarity / 2, 255); maxB = Math.Min(averB + similarity / 2, 255); // for each row for (int y = 0; y < height; y++) { // for each pixel for (int x = 0; x < width; x++, src += pixelSize, dst += pixelSize) { LAB lab = LAB.FromRGB(new RGB(src[RGB.R], src[RGB.G], src[RGB.B])); if (lab.Lightness >= minL && lab.Lightness <= maxL && lab.A >= minA && lab.A <= maxA && lab.B >= minB && lab.B <= maxB) { dst[RGB.R] = dst[RGB.G] = dst[RGB.B] = 0; } else { dst[RGB.R] = dst[RGB.G] = dst[RGB.B] = 255; } } src += offset; dst += offset; } image.UnlockBits(srcDat); dest.UnlockBits(dstDat); return(dest); }