public void Render(Image image, Drawable drawable, bool preview) { int size = GetValue<int>("size"); image.UndoGroupStart(); var procedure = new Procedure("plug_in_pixelize"); procedure.Run(image, drawable, size); var palette = new MinisteckPalette(); image.ConvertIndexed(ConvertDitherType.No, ConvertPaletteType.Custom, 0, false, false, "Ministeck"); palette.Delete(); image.ConvertRgb(); image.UndoGroupEnd(); // And finally calculate the Ministeck pieces using (var painter = new Painter(drawable, size, GetValue<RGB>("color"))) { Shape.Painter = painter; int width = drawable.Width / size; int height = drawable.Height / size; var A = new BoolMatrix(width, height); // Fill in shapes bool limit = GetValue<bool>("limit"); var shapes = new ShapeSet(); shapes.Add((limit) ? 2 : 1, new TwoByTwoShape()); shapes.Add((limit) ? 8 : 1, new ThreeByOneShape()); shapes.Add((limit) ? 3 : 1, new TwoByOneShape()); shapes.Add((limit) ? 2 : 1, new CornerShape()); shapes.Add((limit) ? 1 : 1, new OneByOneShape()); Action<int> update = null; if (!preview) { var progress = new Progress(_("Ministeck...")); update = y => progress.Update((double) y / height); } var generator = new CoordinateGenerator(new Rectangle(0, 0, width, height), update); generator.ForEach(c => {if (!A.Get(c)) shapes.Fits(A, c);}); } drawable.Flush(); drawable.Update(); }
public void Render(Image image, Drawable drawable, Progress progress) { var dimensions = image.Dimensions; Tile.CacheDefault(drawable); var pf = new PixelFetcher(drawable, false); var iter = new RgnIterator(drawable, RunMode.Interactive); iter.IterateSrcDest(src => src); int dropSize = GetValue<int>("drop_size"); int fishEye = GetValue<int>("fish_eye"); int number = GetValue<int>("number"); var factory = new RaindropFactory(dropSize, fishEye, dimensions); for (int numBlurs = 0; numBlurs <= number; numBlurs++) { var raindrop = factory.Create(); if (raindrop == null) { if (progress != null) progress.Update(1.0); break; } raindrop.Render(factory.BoolMatrix, pf, drawable); if (progress != null) progress.Update((double) numBlurs / number); } pf.Dispose(); drawable.Flush(); drawable.Update(); }
protected override void Render(Image image, Drawable drawable) { var progress = new Progress(_("Colorizing...")); var rectangle = drawable.MaskIntersect; // Fix me: replace with x1, y1, x2, y2 int i = rectangle.X1; int j = rectangle.Y1; int ii = rectangle.X2; int jj = rectangle.Y2; bool hasSel = (rectangle != null); if (!hasSel || _useEntireImage) { j = i = 0; jj = image.Width; ii = image.Height; } Drawable sel = null; int threshGuc = (int) (_thresh * 255); PixelRgn selRgn = null; if (hasSel) { sel = image.Selection; selRgn = new PixelRgn(sel, rectangle, false, false); } var srcRgn = new PixelRgn(drawable, rectangle, false, false); var dstRgn = new PixelRgn(drawable, rectangle, true, true); var markRgn = new PixelRgn(_marked, rectangle, false, false); int h = srcRgn.H; int w = srcRgn.W; var A = new double[WindowPixels, h * w]; var AI = new int[WindowPixels * h * w]; var AJ = new int[WindowPixels * h * w]; var Y = new double[h, w]; var I = new double[h, w]; var Q = new double[h, w]; double[,] inI = null; double[,] inQ = null; if (_useChroma) { inI = new double[h, w]; inQ = new double[h, w]; } bool[,] mask = new bool[h, w]; Tile.CacheDefault(drawable); if (sel != null) { // Retarded check for selections, because gimp doesn't // _REALLY_ return FALSE when there's no selection. if (j == 0 && i == 0 && jj == drawable.Width && ii == drawable.Height) { bool goodSelection = false; foreach (var pixel in new ReadPixelIterator(sel, RunMode.Noninteractive)) { if (pixel[0] != 0) { goodSelection = true; break; } } if (!goodSelection) { sel.Detach(); sel = null; } } } Pixel[] selRow = null; var whitePixel = new Pixel(255, 255, 255); for (i = 0; i < h; i++) { var imgRow = srcRgn.GetRow(srcRgn.X, srcRgn.Y + i, w); var markRow = markRgn.GetRow(markRgn.X, markRgn.Y + i, w); if (sel != null) { selRow = selRgn.GetRow(selRgn.X, selRgn.Y + i, w); } for (j = 0; j < w; j++) { var imgPixel = imgRow[j]; var markPixel = markRow[j]; int selIdx = (sel != null) ? j : 0; double iY, iI, iQ; double mY; rgb2yiq(imgPixel, out iY, out iI, out iQ); if (_useChroma) { inI[i, j] = iI; inQ[i, j] = iQ; } if (_includeOriginal) { var diff = imgPixel - markPixel;; int delta = Math.Abs(diff.Red) + Math.Abs(diff.Green) + Math.Abs(diff.Blue); } // big dirty if statement if (_pureWhite && markPixel.IsSameColor(whitePixel)) { mask[i, j] = true; } else if ((_includeOriginal && !imgPixel.IsSameColor(markPixel)) || (!_includeOriginal && markPixel.Alpha >= threshGuc)) { mask[i, j] = true; rgb2yiq(markPixel, out mY, out iI, out iQ); } else if (sel != null && selRow[selIdx].Red < threshGuc) { mask[i, j] = true; } else { mask[i, j] = false; iI = iQ = 0; } Y[i, j] = iY; I[i, j] = iI; Q[i, j] = iQ; } } if (sel != null) { sel.Detach(); } progress.Update(0.1); int n = 0; for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { if (!mask[i, j]) { int min_ii = Math.Max(0, i - WindowRadius); int max_ii = Math.Min(h - 1, i + WindowRadius); int min_jj = Math.Max(0, j - WindowRadius); int max_jj = Math.Min(w - 1, j + WindowRadius); var vary = new int[WindowPixels]; var varx = new int[WindowPixels]; var var = new double[WindowPixels]; int count = 0; double sum_sq = 0; double sum = 0; double min_variance = 1.0; for (ii = min_ii; ii <= max_ii; ii++) { for (jj = min_jj; jj <= max_jj; jj++) { double val = Y[ii, jj]; sum += val; sum_sq += val * val; if (ii == i && jj == j) continue; vary[count] = i * w + j; varx[count] = ii * w + jj; var[count] = val - Y[i, j]; var[count] *= var[count]; if (_useChroma) { val = inI[ii, jj] - inI[i, j]; var[count] += val * val; val = inQ[ii, jj] - inQ[i, j]; var[count] += val * val; } if (var[count] < min_variance) min_variance = var[count]; ++count; } } double sigma = (sum_sq - (sum * sum)/(double)(count + 1)) / (double)count; if (sigma < 0.000002) sigma = 0.000002; else if (sigma < (min_variance / LN_100)) sigma = min_variance / LN_100; sum = 0; for (ii = 0; ii < count; ii++) { var[ii] = Math.Exp(-var[ii] / sigma); sum += var[ii]; } for (ii = 0; ii < count; ii++) { AI[n] = vary[ii]; AJ[n] = varx[ii]; // Fix me: just A[i, j]? A[n / (h * w) , n % (h * w)] = -var[ii] / sum; ++n; } } AI[n] = AJ[n] = i * w + j; // Fix me: just A[i, j]? A[n / (h * w), n % (h * w)] = 1.0; ++n; } } UmfPack umf = new UmfPack(); umf.Defaults(); var Ax = new double[WindowPixels, h * w]; var Ap = new int[h * w + 1]; var Ai = new int[WindowPixels * h * w]; var Map = new int[WindowPixels * h * w]; umf.TripletToCol(h * w, h * w, n, AI, AJ, A, Ap, Ai, Ax, Map); umf.Symbolic(h * w, h * w, Ap, Ai, Ax); umf.Numeric(Ap, Ai, Ax); umf.FreeSymbolic(); progress.Update(0.3); var outI = new double[h, w]; var outQ = new double[h, w]; umf.Solve(Ap, Ai, Ax, outI, I); progress.Update(0.6); umf.Solve(Ap, Ai, Ax, outQ, Q); umf.FreeNumeric(); progress.Update(0.9); for (i = 0; i < h; i++) { // FIXME: This is only for the alpha channel.. var imgRow = srcRgn.GetRow(srcRgn.X, srcRgn.Y + i, w); for (j = 0; j < w; j++) { yiq2rgb(Y[i, j], outI[i, j], outQ[i, j], imgRow[j]); } dstRgn.SetRow(imgRow, dstRgn.X, dstRgn.Y + i); } drawable.Flush(); drawable.MergeShadow(true); drawable.Update(dstRgn.X, dstRgn.Y, dstRgn.W, dstRgn.H); progress.Update(1.0); }