public override ColorBgra Apply(ColorBgra color) { byte lumi = color.GetIntensityByte(); int diff = Curve[lumi] - lumi; return(ColorBgra.FromBgraClamped( color.B + diff, color.G + diff, color.R + diff, color.A)); }
/// <summary> /// Return the final colour after error diffusion has been applied /// </summary> /// <param name="x">Current pixel position in the row</param> /// <param name="original">Original colour value</param> /// <param name="map">Colour value mapper</param> /// <returns></returns> public ColorBgra GetFinalColour(int x, ColorBgra original, Func <ColorBgra, ColorBgra> map) { var b = (int)(original.B + errorRed[0][x] + 0.5f); var g = (int)(original.G + errorGreen[0][x] + 0.5f); var r = (int)(original.R + errorRed[0][x] + 0.5f); var mapped = map(ColorBgra.FromBgraClamped(b, g, r, original.A)); var errB = original.B - mapped.B; var errG = original.G - mapped.G; var errR = original.R - mapped.R; SpreadErrorRight(x, errB, errG, errR); SpreadErrorDown(x, errB, errG, errR); return(mapped); }
public unsafe override ColorBgra Apply(ColorBgra src, int area, int *hb, int *hg, int *hr, int *ha) { int b = 0; int g = 0; int r = 0; int a = 0; for (int i = 1; i < 256; ++i) { b += i * hb[i]; g += i * hg[i]; r += i * hr[i]; a += i * ha[i]; } ColorBgra c = ColorBgra.FromBgraClamped(b / area, g / area, r / area, a / area); return(c); }
private static ColorBgra AddColor(ColorBgra original, ColorBgra addition) { if (original.A == 255) { return(original); } if (original.A == 0) { return(addition); } byte addition_alpha = Math.Min(addition.A, (byte)(255 - original.A)); int total_alpha = original.A + addition_alpha; double orig_frac = original.A / (double)total_alpha; double add_frac = addition_alpha / (double)total_alpha; return(ColorBgra.FromBgraClamped( (int)(original.B * orig_frac + addition.B * add_frac), (int)(original.G * orig_frac + addition.G * add_frac), (int)(original.R * orig_frac + addition.R * add_frac), total_alpha)); }
public unsafe override ColorBgra ApplyWithAlpha(ColorBgra src, int area, int sum, int *hb, int *hg, int *hr) { //each slot of the histgram can contain up to area * 255. This will overflow an int when area > 32k if (area < 32768) { int b = 0; int g = 0; int r = 0; for (int i = 1; i < 256; ++i) { b += i * hb[i]; g += i * hg[i]; r += i * hr[i]; } int alpha = sum / area; int div = area * 255; return(ColorBgra.FromBgraClamped(b / div, g / div, r / div, alpha)); } else //use a long if an int will overflow. { long b = 0; long g = 0; long r = 0; for (long i = 1; i < 256; ++i) { b += i * hb[i]; g += i * hg[i]; r += i * hr[i]; } int alpha = sum / area; int div = area * 255; return(ColorBgra.FromBgraClamped(b / div, g / div, r / div, alpha)); } }
public override ColorBgra Apply(ColorBgra color) { int i = 0; int h, s, v, delta; switch (InputMode) { case Channel.A: i = Curve[color.A]; break; case Channel.R: i = Curve[color.R]; break; case Channel.G: i = Curve[color.G]; break; case Channel.B: i = Curve[color.B]; break; case Channel.C: i = 255 - color.R; i -= Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B); i = Curve[i]; break; case Channel.M: i = 255 - color.G; i -= Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B); i = Curve[i]; break; case Channel.Y: i = 255 - color.B; i -= Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B); i = Curve[i]; break; case Channel.K: i = Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B); i = Curve[i]; break; case Channel.H: s = 0; v = (color.R > color.G) ? color.R : color.G; delta = 0; if (color.B > v) { v = color.B; } if (v == 0) { s = 0; } else { int min = (color.R < color.G) ? color.R : color.G; if (color.B < min) { min = color.B; } delta = v - min; if (delta > 0) { s = CommonUtil.IntDiv(255 * delta, v); } } if (s == 0) { i = 0; } else { if (color.R == v) // Between Yellow and Magenta { i = CommonUtil.IntDiv(255 * (color.G - color.B), delta); } else if (color.G == v) // Between Cyan and Yellow { i = 512 + CommonUtil.IntDiv(255 * (color.B - color.R), delta); } else // Between Magenta and Cyan { i = 1024 + CommonUtil.IntDiv(255 * (color.R - color.G), delta); } if (i < 0) { i += 1536; } i = CommonUtil.IntDiv(i, 6); } i = Curve[i]; break; case Channel.S: v = (color.R > color.G) ? color.R : color.G; if (color.B > v) { v = color.B; } if (v == 0) { i = 0; } else { int min = (color.R < color.G) ? color.R : color.G; if (color.B < min) { min = color.B; } delta = v - min; if (delta > 0) { i = CommonUtil.IntDiv(255 * delta, v); } } i = Curve[i]; break; case Channel.V: i = (color.R > color.G) ? color.R : color.G; if (color.B > i) { i = color.B; } i = Curve[i]; break; case Channel.L: i = color.GetIntensityByte(); i = Curve[i]; break; default: throw new Exception(); } switch (OutputMode) { case Channel.A: return(ColorBgra.FromBgra( color.B, color.G, color.R, (byte)i)); case Channel.R: return(ColorBgra.FromBgra( color.B, color.G, (byte)i, color.A)); case Channel.G: return(ColorBgra.FromBgra( color.B, (byte)i, color.R, color.A)); case Channel.B: return(ColorBgra.FromBgra( (byte)i, color.G, color.R, color.A)); case Channel.C: i = (byte)(i + Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B)).Clamp(0, 255); return(ColorBgra.FromBgra( color.B, color.G, (byte)(255 - i), color.A)); case Channel.M: i = (byte)(i + Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B)).Clamp(0, 255); return(ColorBgra.FromBgra( color.B, (byte)(255 - i), color.R, color.A)); case Channel.Y: i = (byte)(i + Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B)).Clamp(0, 255); return(ColorBgra.FromBgra( (byte)(255 - i), color.G, color.R, color.A)); case Channel.K: int C = 255 - color.R; int M = 255 - color.G; int Y = 255 - color.B; int K = Math.Min(Math.Min(C, M), Y); return(ColorBgra.FromBgraClamped( 255 - (Y - K + i), 255 - (M - K + i), 255 - (C - K + i), color.A)); case Channel.H: s = 0; v = (color.R > color.G) ? color.R : color.G; delta = 0; if (color.B > v) { v = color.B; } if (v == 0) { s = 0; } else { int min = (color.R < color.G) ? color.R : color.G; if (color.B < min) { min = color.B; } delta = v - min; if (delta > 0) { s = CommonUtil.IntDiv(255 * delta, v); } } i *= 6; int fSector = (i & 0xff); int sNumber = (i >> 8); switch (sNumber) { case 0: int tmp0 = ((s * (255 - fSector)) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - s)) + 128) >> 8), (byte)(((v * (255 - tmp0)) + 128) >> 8), (byte)v, color.A)); case 1: int tmp1 = ((s * fSector) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - s)) + 128) >> 8), (byte)v, (byte)(((v * (255 - tmp1)) + 128) >> 8), color.A)); case 2: int tmp2 = ((s * (255 - fSector)) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - tmp2)) + 128) >> 8), (byte)v, (byte)(((v * (255 - s)) + 128) >> 8), color.A)); case 3: int tmp3 = ((s * fSector) + 128) >> 8; return(ColorBgra.FromBgra( (byte)v, (byte)(((v * (255 - tmp3)) + 128) >> 8), (byte)(((v * (255 - s)) + 128) >> 8), color.A)); case 4: int tmp4 = ((s * (255 - fSector)) + 128) >> 8; return(ColorBgra.FromBgra( (byte)v, (byte)(((v * (255 - s)) + 128) >> 8), (byte)(((v * (255 - tmp4)) + 128) >> 8), color.A)); case 5: int tmp5 = ((s * fSector) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - tmp5)) + 128) >> 8), (byte)(((v * (255 - s)) + 128) >> 8), (byte)v, color.A)); default: return(new ColorBgra()); } case Channel.S: s = 0; v = (color.R > color.G) ? color.R : color.G; delta = 0; if (color.B > v) { v = color.B; } if (v == 0) { s = 0; } else { int min = (color.R < color.G) ? color.R : color.G; if (color.B < min) { min = color.B; } delta = v - min; if (delta > 0) { s = CommonUtil.IntDiv(255 * delta, v); } } if (s == 0) { h = 0; } else { if (color.R == v) // Between Yellow and Magenta { h = CommonUtil.IntDiv(255 * (color.G - color.B), delta); } else if (color.G == v) // Between Cyan and Yellow { h = 512 + CommonUtil.IntDiv(255 * (color.B - color.R), delta); } else // Between Magenta and Cyan { h = 1024 + CommonUtil.IntDiv(255 * (color.R - color.G), delta); } if (h < 0) { h += 1536; } } int fs = (h & 0xff); int sn = (h >> 8); switch (sn) { case 0: int tmp0 = ((i * (255 - fs)) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - i)) + 128) >> 8), (byte)(((v * (255 - tmp0)) + 128) >> 8), (byte)v, color.A)); case 1: int tmp1 = ((i * fs) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - i)) + 128) >> 8), (byte)v, (byte)(((v * (255 - tmp1)) + 128) >> 8), color.A)); case 2: int tmp2 = ((i * (255 - fs)) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - tmp2)) + 128) >> 8), (byte)v, (byte)(((v * (255 - i)) + 128) >> 8), color.A)); case 3: int tmp3 = ((i * fs) + 128) >> 8; return(ColorBgra.FromBgra( (byte)v, (byte)(((v * (255 - tmp3)) + 128) >> 8), (byte)(((v * (255 - i)) + 128) >> 8), color.A)); case 4: int tmp4 = ((i * (255 - fs)) + 128) >> 8; return(ColorBgra.FromBgra( (byte)v, (byte)(((v * (255 - i)) + 128) >> 8), (byte)(((v * (255 - tmp4)) + 128) >> 8), color.A)); case 5: int tmp5 = ((i * fs) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - tmp5)) + 128) >> 8), (byte)(((v * (255 - i)) + 128) >> 8), (byte)v, color.A)); default: return(new ColorBgra()); } case Channel.V: int max = (color.R > color.G) ? color.R : color.G; if (color.B > max) { max = color.B; } return(ColorBgra.FromBgra( (byte)CommonUtil.IntDiv(color.B * i, max), (byte)CommonUtil.IntDiv(color.G * i, max), (byte)CommonUtil.IntDiv(color.R * i, max), color.A )); case Channel.L: return(ColorBgra.FromBgraClamped( color.B + i - color.GetIntensityByte(), color.G + i - color.GetIntensityByte(), color.R + i - color.GetIntensityByte(), color.A)); default: throw new Exception(); } }
private void Render(Rectangle rect, Surface srcSurface, Surface dstSurface) #endif { ArgusPaintNet.Shared.Matrix kernel = this.Token.Kernel; float factor = this.Token.Factor * kernel.GetNormalizationFactor(); int kWidth = kernel.ColumnCount; int kHeight = kernel.RowCount; Rectangle srcBounds = this.EnvironmentParameters.SourceSurface.Bounds; for (int y = rect.Top; y < rect.Bottom; y++) { if (this.IsCancelRequested) { return; } #if UNSAFE ColorBgra *[] pointers = new ColorBgra *[kHeight]; for (int row = 0; row < kHeight; row++) { int sy = y + row - kHeight / 2; if (sy < 0 || sy >= srcBounds.Height) { pointers[row] = null; continue; } pointers[row] = srcSurface.GetPointAddress(0, sy); } #endif #if UNSAFE for (int x = 0; x < rect.Width; x++) #else for (int x = rect.Left; x < rect.Right; x++) #endif { float r = 0; float g = 0; float b = 0; for (int col = 0; col < kWidth; col++) { int sx = x + col - kWidth / 2; if (sx < 0 || sx >= srcBounds.Width) { continue; } for (int row = 0; row < kHeight; row++) { #if UNSAFE if (pointers[row] == null) { continue; } ColorBgra px = pointers[row][sx]; #else int sy = y + row - kHeight / 2; if (sy < 0 || sy >= srcBounds.Height) { continue; } ColorBgra px = srcSurface[sx, sy]; #endif r += kernel[row, col] * px.R * factor; g += kernel[row, col] * px.G * factor; b += kernel[row, col] * px.B * factor; } } dstSurface[x, y] = ColorBgra.FromBgraClamped(Math.Abs(b), Math.Abs(g), Math.Abs(r), 255); } } }