@Override
   // Supports in place resampling
   public void superSample(int[] input, int[] output)
   {
      final int st = this.stride;
      final int dw = this.width * this.factor;
      final int dw2 = dw + dw;
      final int dh = this.height * this.factor;
      final int sh = this.height;
      final int sw = this.width;
      int iOffs = st * (sh - 1) + this.offset;
      int oOffs = dw * (dh - this.factor);

      if (this.factor == 2)
      {
         // Last 2 lines, only horizontal interpolation
         for (int i=sw-1; i>=0; i--)
         {
            final int valA = input[iOffs+i];
            final int valB = (i == sw-1) ? valA : input[iOffs+i+1];
            final int valAB = (valA + valB) >> 1;
            int k = oOffs + (i << 1);
            output[k]    = valA;
            output[k+1]  = valAB;
            k += dw;
            output[k]    = valA;
            output[k+1]  = valAB;
         }

         iOffs -= st;
         oOffs -= dw2;

         // Grid (lower case: interpolated pixels, upper case: copied pixels)
         //  A a B
         //  b c .
         //  C . D
         for (int j=sh-2; j>=0; j--)
         {
            // Last pixels of the line, only vertical interpolation
            int valB = input[iOffs+sw-1];
            int valD = input[iOffs+st+sw-1];
            int k = oOffs + dw;
            output[k-2] = valB;
            output[k-1] = valB;
            k += dw;
            output[k-2] = (valB + valD) >> 1;
            output[k-1] = (valB + valD) >> 1;

            for (int i=sw-2; i>=0; i--)
            {
               k = oOffs + (i << 1);
               final int valA = input[iOffs+i];
               final int valC = input[iOffs+st+i];
               output[k]   = valA;
               output[k+1] = (valA + valB) >> 1; // a
               k += dw;
               output[k]   = (valA + valC) >> 1; // b
               output[k+1] = (valA + valB + valC + valD + 2) >> 2; // c
               valB = valA;
               valD = valC;
            }

            iOffs -= st;
            oOffs -= dw2;
         }
      }
      else // factor = 4
      {
         final int dw4 = dw2 + dw2;
          
         // Last 4 lines, only horizontal interpolation
         for (int i=sw-1; i>=0; i--)
         {
            final int valA = input[iOffs+i];
            final int valB = (i == sw-1) ? valA : input[iOffs+i+1];
            final int val3AB = (valA + valA + valA + valB + 2) >> 2;
            final int valA3B = (valA + valB + valB + valB + 2) >> 2;
            int k = oOffs + (i << 2);
            output[k]    = valA;
            output[k+1]  = val3AB;
            output[k+2]  = valA3B;
            output[k+3]  = valB;
            k += dw;
            output[k]    = valA;
            output[k+1]  = val3AB;
            output[k+2]  = valA3B;
            output[k+3]  = valB;
            k += dw;
            output[k]   = valA;
            output[k+1] = val3AB;
            output[k+2] = valA3B;
            output[k+3] = valB;
            k += dw;
            output[k]   = valA;
            output[k+1] = val3AB;
            output[k+2] = valA3B;
            output[k+3] = valB;
         }

         iOffs -= st;
         oOffs -= dw4;

         // Grid (lower case: interpolated pixels, upper case: copied pixels)
         //  A a b c B
         //  d e f g .
         //  h i j k .
         //  l m n o .
         //  C . . . D
         for (int j=sh-2; j>=0; j--)
         {
            // Last pixels of the line, only vertical interpolation
            int valB = input[iOffs+sw-1];
            int valD = input[iOffs+st+sw-1];
            int val3B = (valB << 1) + valB;
            int val3D = (valD << 1) + valD;
            int k = oOffs + dw;
            output[k-4] = valB;
            output[k-3] = valB;
            output[k-2] = valB;
            output[k-1] = valB;
            k += dw;
            output[k-4] = (val3B + valD + 2) >> 2;
            output[k-3] = (val3B + valD + 2) >> 2;
            output[k-2] = (val3B + valD + 2) >> 2;
            output[k-1] = (val3B + valD + 2) >> 2;
            k += dw;
            output[k-4] = (valB + val3D + 2) >> 2;
            output[k-3] = (valB + val3D + 2) >> 2;
            output[k-2] = (valB + val3D + 2) >> 2;
            output[k-1] = (valB + val3D + 2) >> 2;
            k += dw;
            output[k-4] = valD;
            output[k-3] = valD;
            output[k-2] = valD;
            output[k-1] = valD;

            for (int i=sw-2; i>=0; i--)
            {
               k = oOffs + (i << 2);
               final int valA = input[iOffs+i];
               final int valC = input[iOffs+st+i];
               final int val3A = (valA << 1) + valA;
               final int val3C = (valC << 1) + valC;
               output[k]   = valA;
               output[k+1] = (val3A + valB + 2) >> 2; // a
               output[k+2] = (valA + valB) >> 1; // b
               output[k+3] = (valA + val3B + 2) >> 2; // c
               k += dw;
               output[k]   = (val3A + valC + 2) >> 2; // d
               output[k+1] = (val3A + valB + valB + valC + valC + valD + 4) >> 3; // e
               output[k+2] = (val3A + val3B + valC + valD + 4) >> 3; //f
               output[k+3] = (valA + valA + val3B + valC + valD + valD + 4) >> 3; // g
               k += dw;
               output[k]   = (valA + valC) >> 1; // h
               output[k+1] = (val3A + valB + val3C + valD + 4) >> 3; // i
               output[k+2] = (valA + valB + valC + valD + 2) >> 2; // j
               output[k+3] = (valA + val3B + valC + val3D + 4) >> 3; //k
               k += dw;
               output[k]   = (valA + val3C + 2) >> 2; // l
               output[k+1] = (valA + valA + valB + val3C + valD + valD + 4) >> 3; // m
               output[k+2] = (valA + valB + val3C + val3D + 4) >> 3; // n
               output[k+3] = (valA + valB + valB + valC + valC + val3D + 4) >> 3; // o
               valB = valA;
               valD = valC;
               val3B = val3A;
               val3D = val3C;
            }

            iOffs -= st;
            oOffs -= dw4;
         }
      }
   }