public static bool TwoValued2(Bitmap bmp24, Color BKcolor, out Bitmap bmp1) { bmp1 = null; if (bmp24.PixelFormat != PixelFormat.Format24bppRgb) return false; int w = bmp24.Width; int h = bmp24.Height; byte r = BKcolor.R; byte g = BKcolor.G; byte b = BKcolor.B; bmp1 = new Bitmap(w, h, PixelFormat.Format1bppIndexed); int ir; BmpProc24 src = new BmpProc24(bmp24); BmpProc1 dst = new BmpProc1(bmp1); for (int y = 0; y < h; ++y) for (int x = 0; x < w; ++x) { ir = src.IndexR(x, y); // current dst[x, y] = ((src[ir] == r) && (src[ir - 1] == g) && (src[ir - 2] == b)); } CallDispose(dst, src); return true; }
public static bool OrderedDither(Bitmap bmp, DitherPattern dp, ErrorDiffusion ed, bool fStretch, Color dark, Color bright, out Bitmap bmp1) { bmp1 = null; if (bmp.PixelFormat != PixelFormat.Format24bppRgb) return false; int w = bmp.Width; int h = bmp.Height; Bitmap tmp = (Bitmap)bmp.Clone(); ImageUtils.GrayScale(ref tmp); if (fStretch) ImageUtils.HistoStretch(ref tmp); byte[,] od22 = { { 51, 204}, {153, 102} }; byte[,] od33 = { {131, 182, 105}, {157, 236, 26}, { 79, 210, 52} }; byte[,] od332 = { { 64, 128, 64}, {128, 196, 128}, { 64, 128, 64} }; byte[,] od44 = { { 15, 195, 60, 240}, {135, 75, 180, 120}, { 45, 225, 30, 210}, {165, 105, 150, 90} }; byte[,] od442 = { { 51, 102, 204, 153}, { 204, 153, 51, 102}, { 153, 204, 102, 51}, { 102, 51, 153, 204} }; byte[,] od443 = { { 51, 102, 204, 153}, { 204, 153, 51, 102}, { 102, 51, 153, 204}, { 153, 204, 102, 51} }; byte[,] msk = od22; switch (dp) { case DitherPattern.od22: msk = od22; break; case DitherPattern.od33: msk = od33; break; case DitherPattern.od332: msk = od332; break; case DitherPattern.od44: msk = od44; break; case DitherPattern.od442: msk = od442; break; case DitherPattern.od443: msk = od443; break; } double[,] fs = { { -1, -1, 7.0/16.0}, { 3.0/16.0, 5.0/16.0, 1.0/16.0} }; double[,] st = { {-1, -1, -1, 8.0/42.0, 4.0/42.0}, {2.0/42.0, 4.0/42.0, 8.0/42.0, 4.0/42.0, 2.0/42.0}, {1.0/42.0, 2.0/42.0, 4.0/42.0, 2.0/42.0, 1.0/42.0} }; double[,] sr = { {-1, -1, -1, 5.0/32.0, 3.0/32.0}, {2.0/32.0, 4.0/32.0, 5.0/32.0, 4.0/32.0, 2.0/32.0}, {-1, 2.0/32.0, 3.0/32.0, 2.0/32.0, -1} }; double[,] jjn = { {-1, -1, -1, 7.0/48.0, 5.0/48.0}, {3.0/48.0, 5.0/48.0, 7.0/48.0, 5.0/48.0, 3.0/48.0}, {1.0/48.0, 3.0/48.0, 5.0/48.0, 3.0/48.0, 1.0/48.0} }; double[,] df = st; switch (ed) { case ErrorDiffusion.FloydSteinberg: df = fs; break; case ErrorDiffusion.Stucci: df = st; break; case ErrorDiffusion.Sierra: df = sr; break; case ErrorDiffusion.JaJuNi: df = jjn; break; } byte d8; bool d; double err; int xx, yy; int row = df.GetLength(0); int col = df.GetLength(1); int xrange = (col - 1) / 2; bmp1 = new Bitmap(w, h, PixelFormat.Format1bppIndexed); int dm = msk.GetLength(0); BmpProc8 src = new BmpProc8(tmp); BmpProc1 dst = new BmpProc1(bmp1); for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) { d8 = src[x, y]; d = (d8 > msk[y % dm, x % dm]); dst[x, y] = d; if (d) { err = d8 - 255; } else { err = d8; } for (int iy = 0; iy < row; iy++) for (int ix = -xrange; ix <= xrange; ix++) { xx = x + ix; if ((xx < 0) | (xx > w - 1)) continue; yy = y + iy; if (yy > h - 1) continue; if (df[iy, ix + xrange] < 0) continue; src[xx, yy] = ImageUtils.AdjustByte(src[xx, yy] + err * df[iy, ix + xrange]); } } CallDispose(dst, src, tmp); ColorPalette cp = bmp1.Palette; cp.Entries[0] = dark; cp.Entries[1] = bright; bmp1.Palette = cp; return true; }
public static bool TwoValued1(Bitmap bmp24, int threshold, out Bitmap bmp1) { bmp1 = null; if (bmp24.PixelFormat != PixelFormat.Format24bppRgb) return false; int w = bmp24.Width; int h = bmp24.Height; bmp1 = new Bitmap(w, h, PixelFormat.Format1bppIndexed); int srcR; BmpProc24 src = new BmpProc24(bmp24); BmpProc1 dst = new BmpProc1(bmp1); for (int y = 0; y < h; ++y) for (int x = 0; x < w; ++x) { srcR = src.IndexR(x, y); // current dst[x, y] = ((src[srcR] * 0.299 + src[srcR - 1] * 0.587 + src[srcR - 2] * 0.114) > threshold); } CallDispose(dst, src); return true; }
public static bool ErrorDiffusionDither(Bitmap bmp, ErrorDiffusion ed, bool fStretch, Color dark, Color bright, byte randomness, out Bitmap bmp1) { bmp1 = null; if (bmp.PixelFormat != PixelFormat.Format24bppRgb) return false; if ((randomness < 0) | (randomness > 30)) return false; int w = bmp.Width; int h = bmp.Height; Bitmap tmp = (Bitmap)bmp.Clone(); GrayScale(ref tmp); if (fStretch) HistoStretch(ref tmp); double[,] fs = { { -1, -1, 7.0/16.0}, { 3.0/16.0, 5.0/16.0, 1.0/16.0} }; double[,] st = { {-1, -1, -1, 8.0/42.0, 4.0/42.0}, {2.0/42.0, 4.0/42.0, 8.0/42.0, 4.0/42.0, 2.0/42.0}, {1.0/42.0, 2.0/42.0, 4.0/42.0, 2.0/42.0, 1.0/42.0} }; double[,] sr = { {-1, -1, -1, 5.0/32.0, 3.0/32.0}, {2.0/32.0, 4.0/32.0, 5.0/32.0, 4.0/32.0, 2.0/32.0}, {-1, 2.0/32.0, 3.0/32.0, 2.0/32.0, -1} }; double[,] jjn = { {-1, -1, -1, 7.0/48.0, 5.0/48.0}, {3.0/48.0, 5.0/48.0, 7.0/48.0, 5.0/48.0, 3.0/48.0}, {1.0/48.0, 3.0/48.0, 5.0/48.0, 3.0/48.0, 1.0/48.0} }; bmp1 = new Bitmap(w, h, PixelFormat.Format1bppIndexed); byte d8; bool d; double err; int xx, yy; byte threshold = 127; Random rnd = new Random(); byte randn = (byte)(randomness * 2 + 1); double[,] df; df = st; switch (ed) { case ErrorDiffusion.FloydSteinberg: df = fs; break; case ErrorDiffusion.Stucci: df = st; break; case ErrorDiffusion.Sierra: df = sr; break; case ErrorDiffusion.JaJuNi: df = jjn; break; } int row = df.GetLength(0); int col = df.GetLength(1); int xrange = (col - 1) / 2; BmpProc8 src = new BmpProc8(tmp); BmpProc1 dst = new BmpProc1(bmp1); for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) { if (randomness > 0) threshold = (byte)(127 + rnd.Next(randn) - randomness); d8 = src[x, y]; d = (d8 > threshold); dst[x, y] = d; if (d) { err = d8 - 255; } else { err = d8; } for (int iy = 0; iy < row; iy++) for (int ix = -xrange; ix <= xrange; ix++) { xx = x + ix; if ((xx < 0) | (xx > w - 1)) continue; yy = y + iy; if (yy > h - 1) continue; if (df[iy, ix + xrange] < 0) continue; src[xx, yy] = AdjustByte(src[xx, yy] + err * df[iy, ix + xrange]); } } CallDispose(dst, src, tmp); ColorPalette cp = bmp1.Palette; cp.Entries[0] = dark; cp.Entries[1] = bright; bmp1.Palette = cp; return true; }