예제 #1
0
        override protected 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);
        }
예제 #2
0
        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);
        }