public Bitmap FloydSteinberg() { RGBint oldPixel, qErr = new RGBint(); Color newPixel; RGBint[,] arr = new RGBint[bmp.Height, bmp.Width]; for (int i = 0; i < bmp.Height; i++) { for (int j = 0; j < bmp.Width; j++) { arr[i, j] = new RGBint(bmp.GetPixel(j, i).R, bmp.GetPixel(j, i).G, bmp.GetPixel(j, i).B); } } for (int i = 0; i < bmp.Height; i++) { for (int j = 0; j < bmp.Width; j++) { oldPixel = arr[i, j]; newPixel = FindColorFromPal((int)oldPixel.Rint, (int)oldPixel.Gint, (int)oldPixel.Bint); bmp.SetPixel(j, i, newPixel); qErr.Set(oldPixel.Rint - newPixel.R, oldPixel.Gint - newPixel.G, oldPixel.Bint - newPixel.B); if (j < bmp.Width - 1) { arr[i, j + 1].Set(arr[i, j + 1].Rint + qErr.Rint * 7 / 16, arr[i, j + 1].Gint + qErr.Gint * 7 / 16, arr[i, j + 1].Bint + qErr.Bint * 7 / 16); if (i < bmp.Height - 1) { arr[i + 1, j + 1].Set(arr[i + 1, j + 1].Rint + qErr.Rint * 1 / 16, arr[i + 1, j + 1].Gint + qErr.Gint * 1 / 16, arr[i + 1, j + 1].Bint + qErr.Bint * 1 / 16); } } if (i < bmp.Height - 1) { arr[i + 1, j].Set(arr[i + 1, j].Rint + qErr.Rint * 5 / 16, arr[i + 1, j].Gint + qErr.Gint * 5 / 16, arr[i + 1, j].Bint + qErr.Bint * 5 / 16); if (j > 0) { arr[i + 1, j - 1].Set(arr[i + 1, j - 1].Rint + qErr.Rint * 3 / 16, arr[i + 1, j - 1].Gint + qErr.Gint * 3 / 16, arr[i + 1, j - 1].Bint + qErr.Bint * 3 / 16); } } } } return(bmp); }
public Bitmap FloydSteinberg() { RGBint old = new RGBint(), qErr = new RGBint(); Color c; //Locks the bitmap bits Rectangle rect = new Rectangle(new Point(0, 0), bmp.Size); BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat); //Adress of the first line. IntPtr ptr = bmpData.Scan0; //Declare array to hold the values. int bpp = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8; int bmpWidth = bmp.Width, bmpHeight = bmp.Height; int stride = Math.Abs(bmpData.Stride); int bytes = stride * bmp.Height; byte[] rgbValues = new byte[bytes]; //Copy values to array. Marshal.Copy(ptr, rgbValues, 0, bytes); //Create copy with float type. double[] rgbValuesFloat = Array.ConvertAll <byte, double>(rgbValues, new Converter <byte, double>(ByteToDouble)); for (int i = 0; i < bmp.Height; i++) { for (int j = 0; j < Math.Ceiling((double)stride / bpp); j++) { if (j < bmpWidth) { int currentRowCol = i * stride + j * bpp; old.Set(rgbValuesFloat[currentRowCol + 2], rgbValuesFloat[currentRowCol + 1], rgbValuesFloat[currentRowCol]); c = FindColorFromPal((int)old.Rint, (int)old.Gint, (int)old.Bint); //Set new pixel value. rgbValuesFloat[currentRowCol + 2] = c.R; rgbValuesFloat[currentRowCol + 1] = c.G; rgbValuesFloat[currentRowCol] = c.B; qErr.Set(old.Rint - c.R, old.Gint - c.G, old.Bint - c.B); if (j < bmpWidth - 1) { rgbValuesFloat[currentRowCol + bpp + 2] = rgbValuesFloat[currentRowCol + bpp + 2] + qErr.Rint * 7 / 16; rgbValuesFloat[currentRowCol + bpp + 1] = rgbValuesFloat[currentRowCol + bpp + 1] + qErr.Gint * 7 / 16; rgbValuesFloat[currentRowCol + bpp] = rgbValuesFloat[currentRowCol + bpp] + qErr.Bint * 7 / 16; if (i < bmpHeight - 1) { rgbValuesFloat[currentRowCol + stride + bpp + 2] = rgbValuesFloat[currentRowCol + stride + bpp + 2] + qErr.Rint * 1 / 16; rgbValuesFloat[currentRowCol + stride + bpp + 1] = rgbValuesFloat[currentRowCol + stride + bpp + 1] + qErr.Gint * 1 / 16; rgbValuesFloat[currentRowCol + stride + bpp] = rgbValuesFloat[currentRowCol + stride + bpp] + qErr.Bint * 1 / 16; } } if (i < bmpHeight - 1) { rgbValuesFloat[currentRowCol + stride + 2] = rgbValuesFloat[currentRowCol + stride + 2] + qErr.Rint * 5 / 16; rgbValuesFloat[currentRowCol + stride + 1] = rgbValuesFloat[currentRowCol + stride + 1] + qErr.Gint * 5 / 16; rgbValuesFloat[currentRowCol + stride] = rgbValuesFloat[currentRowCol + stride] + qErr.Bint * 5 / 16; if (j > 0) { rgbValuesFloat[currentRowCol + stride - bpp + 2] = rgbValuesFloat[currentRowCol + stride - bpp + 2] + qErr.Rint * 3 / 16; rgbValuesFloat[currentRowCol + stride - bpp + 1] = rgbValuesFloat[currentRowCol + stride - bpp + 1] + qErr.Gint * 3 / 16; rgbValuesFloat[currentRowCol + stride - bpp] = rgbValuesFloat[currentRowCol + stride - bpp] + qErr.Bint * 3 / 16; } } } } } //Convert back. rgbValues = Array.ConvertAll <double, byte>(rgbValuesFloat, new Converter <double, byte>(DoubleToByte)); //Copy them back. Marshal.Copy(rgbValues, 0, ptr, bytes); //Unlock the bits. bmp.UnlockBits(bmpData); return(bmp); }