/*
         * input kernel area naming convention:
         * -------------
         | A | B | C |
         | ----|---|---|
         | D | E | F | //input pixel is at position E
         | ----|---|---|
         | G | H | I |
         | -------------
         */

        private static void _ScalePixel(
            IScaler scaler,
            RotationDegree rotDeg,
            Kernel_3X3 ker,
            sPixel[] trg,
            int trgi,
            int trgWidth,
            byte blendInfo,      //result of preprocessing all four corners of pixel "e"
            IColorEq scalePixelColorEq,
            IColorDist scalePixelColorDist,
            OutputMatrix outputMatrix
            )
        {
            //int a = kernel._[Rot._[(0 << 2) + rotDeg]];
            var b = ker._[Rot._[(1 << 2) + (int)rotDeg]];
            var c = ker._[Rot._[(2 << 2) + (int)rotDeg]];
            var d = ker._[Rot._[(3 << 2) + (int)rotDeg]];
            var e = ker._[Rot._[(4 << 2) + (int)rotDeg]];
            var f = ker._[Rot._[(5 << 2) + (int)rotDeg]];
            var g = ker._[Rot._[(6 << 2) + (int)rotDeg]];
            var h = ker._[Rot._[(7 << 2) + (int)rotDeg]];
            var i = ker._[Rot._[(8 << 2) + (int)rotDeg]];

            var blend = BlendInfo.Rotate(blendInfo, rotDeg);

            if (BlendInfo.GetBottomR(blend) == BlendType.BlendNone)
            {
                return;
            }

            var eq   = scalePixelColorEq;
            var dist = scalePixelColorDist;

            bool doLineBlend;

            if (BlendInfo.GetBottomR(blend) >= BlendType.BlendDominant)
            {
                doLineBlend = true;
            }

            //make sure there is no second blending in an adjacent
            //rotation for this pixel: handles insular pixels, mario eyes
            //but support double-blending for 90? corners
            else if (BlendInfo.GetTopR(blend) != BlendType.BlendNone && !eq._(e, g))
            {
                doLineBlend = false;
            }

            else if (BlendInfo.GetBottomL(blend) != BlendType.BlendNone && !eq._(e, c))
            {
                doLineBlend = false;
            }

            //no full blending for L-shapes; blend corner only (handles "mario mushroom eyes")
            else if (eq._(g, h) && eq._(h, i) && eq._(i, f) && eq._(f, c) && !eq._(e, i))
            {
                doLineBlend = false;
            }

            else
            {
                doLineBlend = true;
            }

            //choose most similar color
            var px = dist._(e, f) <= dist._(e, h) ? f : h;

            var output = outputMatrix;

            output.Move(rotDeg, trgi);

            if (!doLineBlend)
            {
                scaler.BlendCorner(px, output);
                return;
            }

            //test sample: 70% of values max(fg, hc) / min(fg, hc)
            //are between 1.1 and 3.7 with median being 1.9
            var fg = dist._(f, g);
            var hc = dist._(h, c);

            var haveShallowLine = _CONFIGURATION.steepDirectionThreshold * fg <= hc && e != g && d != g;
            var haveSteepLine   = _CONFIGURATION.steepDirectionThreshold * hc <= fg && e != c && b != c;

            if (haveShallowLine)
            {
                if (haveSteepLine)
                {
                    scaler.BlendLineSteepAndShallow(px, output);
                }
                else
                {
                    scaler.BlendLineShallow(px, output);
                }
            }
            else
            {
                if (haveSteepLine)
                {
                    scaler.BlendLineSteep(px, output);
                }
                else
                {
                    scaler.BlendLineDiagonal(px, output);
                }
            }
        }
Example #2
0
    /*
  input kernel area naming convention:
  -------------
  | A | B | C |
  ----|---|---|
  | D | E | F | //input pixel is at position E
  ----|---|---|
  | G | H | I |
  -------------
  */

    private static void _ScalePixel(
      IScaler scaler,
      RotationDegree rotDeg,
      Kernel_3X3 ker,
      sPixel[] trg,
      int trgi,
      int trgWidth,
      byte blendInfo,//result of preprocessing all four corners of pixel "e"
      IColorEq scalePixelColorEq,
      IColorDist scalePixelColorDist,
      OutputMatrix outputMatrix
      ) {
      //int a = kernel._[Rot._[(0 << 2) + rotDeg]];
      var b = ker._[Rot._[(1 << 2) + (int)rotDeg]];
      var c = ker._[Rot._[(2 << 2) + (int)rotDeg]];
      var d = ker._[Rot._[(3 << 2) + (int)rotDeg]];
      var e = ker._[Rot._[(4 << 2) + (int)rotDeg]];
      var f = ker._[Rot._[(5 << 2) + (int)rotDeg]];
      var g = ker._[Rot._[(6 << 2) + (int)rotDeg]];
      var h = ker._[Rot._[(7 << 2) + (int)rotDeg]];
      var i = ker._[Rot._[(8 << 2) + (int)rotDeg]];

      var blend = BlendInfo.Rotate(blendInfo, rotDeg);

      if (BlendInfo.GetBottomR(blend) == BlendType.BlendNone)
        return;

      var eq = scalePixelColorEq;
      var dist = scalePixelColorDist;

      bool doLineBlend;

      if (BlendInfo.GetBottomR(blend) >= BlendType.BlendDominant)
        doLineBlend = true;

        //make sure there is no second blending in an adjacent
      //rotation for this pixel: handles insular pixels, mario eyes
      //but support double-blending for 90? corners
      else if (BlendInfo.GetTopR(blend) != BlendType.BlendNone && !eq._(e, g))
        doLineBlend = false;

      else if (BlendInfo.GetBottomL(blend) != BlendType.BlendNone && !eq._(e, c))
        doLineBlend = false;

        //no full blending for L-shapes; blend corner only (handles "mario mushroom eyes")
      else if (eq._(g, h) && eq._(h, i) && eq._(i, f) && eq._(f, c) && !eq._(e, i))
        doLineBlend = false;

      else
        doLineBlend = true;

      //choose most similar color
      var px = dist._(e, f) <= dist._(e, h) ? f : h;

      var output = outputMatrix;
      output.Move(rotDeg, trgi);

      if (!doLineBlend) {
        scaler.BlendCorner(px, output);
        return;
      }

      //test sample: 70% of values max(fg, hc) / min(fg, hc)
      //are between 1.1 and 3.7 with median being 1.9
      var fg = dist._(f, g);
      var hc = dist._(h, c);

      var haveShallowLine = _CONFIGURATION.steepDirectionThreshold * fg <= hc && e != g && d != g;
      var haveSteepLine = _CONFIGURATION.steepDirectionThreshold * hc <= fg && e != c && b != c;

      if (haveShallowLine) {
        if (haveSteepLine)
          scaler.BlendLineSteepAndShallow(px, output);
        else
          scaler.BlendLineShallow(px, output);
      } else {
        if (haveSteepLine)
          scaler.BlendLineSteep(px, output);
        else
          scaler.BlendLineDiagonal(px, output);
      }
    }
        /*
         * input kernel area naming convention:
         * -----------------
         | A | B | C | D |
         | ----|---|---|---|
         | E | F | G | H | //evalute the four corners between F, G, J, K
         | ----|---|---|---| //input pixel is at position F
         | I | J | K | L |
         | ----|---|---|---|
         | M | N | O | P |
         | -----------------
         */

        //detect blend direction
        private static void _PreProcessCorners(Kernel_4X4 kernel, BlendResult blendResult, IColorDist preProcessCornersColorDist)
        {
            blendResult.Reset();

            if ((kernel.f == kernel.g && kernel.j == kernel.k) || (kernel.f == kernel.j && kernel.g == kernel.k))
            {
                return;
            }

            var dist = preProcessCornersColorDist;

            var weight = 4;
            var jg     = dist._(kernel.i, kernel.f) + dist._(kernel.f, kernel.c) + dist._(kernel.n, kernel.k) + dist._(kernel.k, kernel.h) + weight * dist._(kernel.j, kernel.g);
            var fk     = dist._(kernel.e, kernel.j) + dist._(kernel.j, kernel.o) + dist._(kernel.b, kernel.g) + dist._(kernel.g, kernel.l) + weight * dist._(kernel.f, kernel.k);

            if (jg < fk)
            {
                var dominantGradient = _CONFIGURATION.dominantDirectionThreshold * jg < fk;
                if (kernel.f != kernel.g && kernel.f != kernel.j)
                {
                    blendResult.f = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal;
                }

                if (kernel.k != kernel.j && kernel.k != kernel.g)
                {
                    blendResult.k = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal;
                }
            }
            else if (fk < jg)
            {
                var dominantGradient = _CONFIGURATION.dominantDirectionThreshold * fk < jg;
                if (kernel.j != kernel.f && kernel.j != kernel.k)
                {
                    blendResult.j = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal;
                }

                if (kernel.g != kernel.f && kernel.g != kernel.k)
                {
                    blendResult.g = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal;
                }
            }
        }
Example #4
0
    /*
  input kernel area naming convention:
  -----------------
  | A | B | C | D |
  ----|---|---|---|
  | E | F | G | H | //evalute the four corners between F, G, J, K
  ----|---|---|---| //input pixel is at position F
  | I | J | K | L |
  ----|---|---|---|
  | M | N | O | P |
  -----------------
  */

    //detect blend direction
    private static void _PreProcessCorners(Kernel_4X4 kernel, BlendResult blendResult, IColorDist preProcessCornersColorDist) {
      blendResult.Reset();

      if ((kernel.f == kernel.g && kernel.j == kernel.k) || (kernel.f == kernel.j && kernel.g == kernel.k))
        return;

      var dist = preProcessCornersColorDist;

      var weight = 4;
      var jg = dist._(kernel.i, kernel.f) + dist._(kernel.f, kernel.c) + dist._(kernel.n, kernel.k) + dist._(kernel.k, kernel.h) + weight * dist._(kernel.j, kernel.g);
      var fk = dist._(kernel.e, kernel.j) + dist._(kernel.j, kernel.o) + dist._(kernel.b, kernel.g) + dist._(kernel.g, kernel.l) + weight * dist._(kernel.f, kernel.k);

      if (jg < fk) {

        var dominantGradient = _CONFIGURATION.dominantDirectionThreshold * jg < fk;
        if (kernel.f != kernel.g && kernel.f != kernel.j)
          blendResult.f = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal;

        if (kernel.k != kernel.j && kernel.k != kernel.g)
          blendResult.k = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal;

      } else if (fk < jg) {

        var dominantGradient = _CONFIGURATION.dominantDirectionThreshold * fk < jg;
        if (kernel.j != kernel.f && kernel.j != kernel.k)
          blendResult.j = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal;

        if (kernel.g != kernel.f && kernel.g != kernel.k)
          blendResult.g = dominantGradient ? BlendType.BlendDominant : BlendType.BlendNormal;

      }
    }