title: Trying to convert Bilinear Interpolation code from Java to C/C++ on Android
body: <h2>Background</h2>
  
  <p>I've made a tiny Android library for handling bitmaps using JNI (link <a href="https://github.com/AndroidDeveloperLB/AndroidJniBitmapOperations" rel="nofollow noreferrer"><strong>here</strong></a>)</p>
  
  <p>In the long past, I've made some code of Bilinear Interpolation as a possible algorithm for scaling of images. The algorithm is a bit complex and uses pixels around to form the target pixel.</p>
  
  <h2>The problem</h2>
  
  <p>Even though there are no errors (no compilation errors and no runtime errors), the output image look like this (scaled the width by x2) :</p>
  
  <p><img src="https://i.stack.imgur.com/kglWQ.png" alt="enter image description here"></p>
  
  <h2>The code</h2>
  
  <p>Basically the original Java code used SWT and supported only RGB, but it's the same for the Alpha channel. It worked before just perfectly (though now that I look at it, it seems to create a lot of objects on the way) .</p>
  
  <p>Here's the Java code:</p>
  
  <pre><code>/** class for resizing imageData using the Bilinear Interpolation method */
  public class BilinearInterpolation
    {
    /** the method for resizing the imageData using the Bilinear Interpolation algorithm */
    public static void resize(final ImageData inputImageData,final ImageData newImageData,final int oldWidth,final int oldHeight,final int newWidth,final int newHeight)
      {
      // position of the top left pixel of the 4 pixels to use interpolation on
      int xTopLeft,yTopLeft;
      int x,y,lastTopLefty;
      final float xRatio=(float)newWidth/(float)oldWidth,yratio=(float)newHeight/(float)oldHeight;
      // Y color ratio to use on left and right pixels for interpolation
      float ycRatio2=0,ycRatio1=0;
      // pixel target in the src
      float xt,yt;
      // X color ratio to use on left and right pixels for interpolation
      float xcRatio2=0,xcratio1=0;
      // copy data from source image to RGB values:
      RGB rgbTopLeft,rgbTopRight,rgbBottomLeft=null,rgbBottomRight=null,rgbTopMiddle=null,rgbBottomMiddle=null;
      RGB[][] startingImageData;
      startingImageData=new RGB[oldWidth][oldHeight];
      for(x=0;x&lt;oldWidth;++x)
        for(y=0;y&lt;oldHeight;++y)
          {
          rgbTopLeft=inputImageData.palette.getRGB(inputImageData.getPixel(x,y));
          startingImageData[x][y]=new RGB(rgbTopLeft.red,rgbTopLeft.green,rgbTopLeft.blue);
          }
      // do the resizing:
      for(x=0;x&lt;newWidth;x++)
        {
        xTopLeft=(int)(xt=x/xRatio);
        // when meeting the most right edge, move left a little
        if(xTopLeft&gt;=oldWidth-1)
          xTopLeft--;
        if(xt&lt;=xTopLeft+1)
          {
          // we are between the left and right pixel
          xcratio1=xt-xTopLeft;
          // color ratio in favor of the right pixel color
          xcRatio2=1-xcratio1;
          }
        for(y=0,lastTopLefty=Integer.MIN_VALUE;y&lt;newHeight;y++)
          {
          yTopLeft=(int)(yt=y/yratio);
          // when meeting the most bottom edge, move up a little
          if(yTopLeft&gt;=oldHeight-1)
            yTopLeft--;
          // we went down only one rectangle
          if(lastTopLefty==yTopLeft-1)
            {
            rgbTopLeft=rgbBottomLeft;
            rgbTopRight=rgbBottomRight;
            rgbTopMiddle=rgbBottomMiddle;
            rgbBottomLeft=startingImageData[xTopLeft][yTopLeft+1];
            rgbBottomRight=startingImageData[xTopLeft+1][yTopLeft+1];
            rgbBottomMiddle=new RGB((int)(rgbBottomLeft.red*xcRatio2+rgbBottomRight.red*xcratio1),(int)(rgbBottomLeft.green*xcRatio2+rgbBottomRight.green*xcratio1),(int)(rgbBottomLeft.blue*xcRatio2+rgbBottomRight.blue*xcratio1));
            }
          else if(lastTopLefty!=yTopLeft)
            {
            // we went to a totally different rectangle (happens in every loop start,and might happen more when making the picture smaller)
            rgbTopLeft=startingImageData[xTopLeft][yTopLeft];
            rgbTopRight=startingImageData[xTopLeft+1][yTopLeft];
            rgbTopMiddle=new RGB((int)(rgbTopLeft.red*xcRatio2+rgbTopRight.red*xcratio1),(int)(rgbTopLeft.green*xcRatio2+rgbTopRight.green*xcratio1),(int)(rgbTopLeft.blue*xcRatio2+rgbTopRight.blue*xcratio1));
            rgbBottomLeft=startingImageData[xTopLeft][yTopLeft+1];
            rgbBottomRight=startingImageData[xTopLeft+1][yTopLeft+1];
            rgbBottomMiddle=new RGB((int)(rgbBottomLeft.red*xcRatio2+rgbBottomRight.red*xcratio1),(int)(rgbBottomLeft.green*xcRatio2+rgbBottomRight.green*xcratio1),(int)(rgbBottomLeft.blue*xcRatio2+rgbBottomRight.blue*xcratio1));
            }
          lastTopLefty=yTopLeft;
          if(yt&lt;=yTopLeft+1)
            {
            // color ratio in favor of the bottom pixel color
            ycRatio1=yt-yTopLeft;
            ycRatio2=1-ycRatio1;
            }
          // prepared all pixels to look at, so finally set the new pixel data
          newImageData.setPixel(x,y,inputImageData.palette.getPixel(new RGB((int)(rgbTopMiddle.red*ycRatio2+rgbBottomMiddle.red*ycRatio1),(int)(rgbTopMiddle.green*ycRatio2+rgbBottomMiddle.green*ycRatio1),(int)(rgbTopMiddle.blue*ycRatio2+rgbBottomMiddle.blue*ycRatio1))));
          }
        }
      }
    }
  </code></pre>
  
  <p>And here's the C/C++ code I've tried to make from it:</p>
  
  <pre><code>typedef struct
      {
      uint8_t alpha, red, green, blue;
      } ARGB;
  
  int32_t convertArgbToInt(ARGB argb)
      {
      return (argb.alpha) | (argb.red &lt;&lt; 16) | (argb.green &lt;&lt; 8)
          | (argb.blue &lt;&lt; 24);
      }
  
  void convertIntToArgb(uint32_t pixel, ARGB* argb)
      {
      argb-&gt;red = ((pixel &gt;&gt; 24) &amp; 0xff);
      argb-&gt;green = ((pixel &gt;&gt; 16) &amp; 0xff);
      argb-&gt;blue = ((pixel &gt;&gt; 8) &amp; 0xff);
      argb-&gt;alpha = (pixel &amp; 0xff);
      }
  
  ...
  
  /**scales the image using a high-quality algorithm called "Bilinear Interpolation" */ //
  JNIEXPORT void JNICALL Java_com_jni_bitmap_1operations_JniBitmapHolder_jniScaleBIBitmap(
      JNIEnv * env, jobject obj, jobject handle, uint32_t newWidth,
      uint32_t newHeight)
      {
      JniBitmap* jniBitmap = (JniBitmap*) env-&gt;GetDirectBufferAddress(handle);
      if (jniBitmap-&gt;_storedBitmapPixels == NULL)
      return;
      uint32_t oldWidth = jniBitmap-&gt;_bitmapInfo.width;
      uint32_t oldHeight = jniBitmap-&gt;_bitmapInfo.height;
      uint32_t* previousData = jniBitmap-&gt;_storedBitmapPixels;
      uint32_t* newBitmapPixels = new uint32_t[newWidth * newHeight];
      // position of the top left pixel of the 4 pixels to use interpolation on
      int xTopLeft, yTopLeft;
      int x, y, lastTopLefty;
      float xRatio = (float) newWidth / (float) oldWidth, yratio =
          (float) newHeight / (float) oldHeight;
      // Y color ratio to use on left and right pixels for interpolation
      float ycRatio2 = 0, ycRatio1 = 0;
      // pixel target in the src
      float xt, yt;
      // X color ratio to use on left and right pixels for interpolation
      float xcRatio2 = 0, xcratio1 = 0;
      ARGB rgbTopLeft, rgbTopRight, rgbBottomLeft, rgbBottomRight, rgbTopMiddle,
          rgbBottomMiddle, result;
      for (x = 0; x &lt; newWidth; ++x)
      {
      xTopLeft = (int) (xt = x / xRatio);
      // when meeting the most right edge, move left a little
      if (xTopLeft &gt;= oldWidth - 1)
          xTopLeft--;
      if (xt &lt;= xTopLeft + 1)
          {
          // we are between the left and right pixel
          xcratio1 = xt - xTopLeft;
          // color ratio in favor of the right pixel color
          xcRatio2 = 1 - xcratio1;
          }
      for (y = 0, lastTopLefty = -30000; y &lt; newHeight; ++y)
          {
          yTopLeft = (int) (yt = y / yratio);
          // when meeting the most bottom edge, move up a little
          if (yTopLeft &gt;= oldHeight - 1)
          --yTopLeft;
          if (lastTopLefty == yTopLeft - 1)
          {
          // we went down only one rectangle
          rgbTopLeft = rgbBottomLeft;
          rgbTopRight = rgbBottomRight;
          rgbTopMiddle = rgbBottomMiddle;
          //rgbBottomLeft=startingImageData[xTopLeft][yTopLeft+1];
          convertIntToArgb(
              previousData[((yTopLeft + 1) * oldWidth) + xTopLeft],
              &amp;rgbBottomLeft);
          //rgbBottomRight=startingImageData[xTopLeft+1][yTopLeft+1];
          convertIntToArgb(
              previousData[((yTopLeft + 1) * oldWidth)
                  + (xTopLeft + 1)], &amp;rgbBottomRight);
          rgbBottomMiddle.alpha = rgbBottomLeft.alpha * xcRatio2
              + rgbBottomRight.alpha * xcratio1;
          rgbBottomMiddle.red = rgbBottomLeft.red * xcRatio2
              + rgbBottomRight.red * xcratio1;
          rgbBottomMiddle.green = rgbBottomLeft.green * xcRatio2
              + rgbBottomRight.green * xcratio1;
          rgbBottomMiddle.blue = rgbBottomLeft.blue * xcRatio2
              + rgbBottomRight.blue * xcratio1;
          }
          else if (lastTopLefty != yTopLeft)
          {
          // we went to a totally different rectangle (happens in every loop start,and might happen more when making the picture smaller)
          //rgbTopLeft=startingImageData[xTopLeft][yTopLeft];
          convertIntToArgb(previousData[(yTopLeft * oldWidth) + xTopLeft],
              &amp;rgbTopLeft);
          //rgbTopRight=startingImageData[xTopLeft+1][yTopLeft];
          convertIntToArgb(
              previousData[((yTopLeft + 1) * oldWidth) + xTopLeft],
              &amp;rgbTopRight);
          rgbTopMiddle.alpha = rgbTopLeft.alpha * xcRatio2
              + rgbTopRight.alpha * xcratio1;
          rgbTopMiddle.red = rgbTopLeft.red * xcRatio2
              + rgbTopRight.red * xcratio1;
          rgbTopMiddle.green = rgbTopLeft.green * xcRatio2
              + rgbTopRight.green * xcratio1;
          rgbTopMiddle.blue = rgbTopLeft.blue * xcRatio2
              + rgbTopRight.blue * xcratio1;
          //rgbBottomLeft=startingImageData[xTopLeft][yTopLeft+1];
          convertIntToArgb(
              previousData[((yTopLeft + 1) * oldWidth) + xTopLeft],
              &amp;rgbBottomLeft);
          //rgbBottomRight=startingImageData[xTopLeft+1][yTopLeft+1];
          convertIntToArgb(
              previousData[((yTopLeft + 1) * oldWidth)
                  + (xTopLeft + 1)], &amp;rgbBottomRight);
          rgbBottomMiddle.alpha = rgbBottomLeft.alpha * xcRatio2
              + rgbBottomRight.alpha * xcratio1;
          rgbBottomMiddle.red = rgbBottomLeft.red * xcRatio2
              + rgbBottomRight.red * xcratio1;
          rgbBottomMiddle.green = rgbBottomLeft.green * xcRatio2
              + rgbBottomRight.green * xcratio1;
          rgbBottomMiddle.blue = rgbBottomLeft.blue * xcRatio2
              + rgbBottomRight.blue * xcratio1;
          }
          lastTopLefty = yTopLeft;
          if (yt &lt;= yTopLeft + 1)
          {
          // color ratio in favor of the bottom pixel color
          ycRatio1 = yt - yTopLeft;
          ycRatio2 = 1 - ycRatio1;
          }
          // prepared all pixels to look at, so finally set the new pixel data
          result.alpha = rgbTopMiddle.alpha * ycRatio2
              + rgbBottomMiddle.alpha * ycRatio1;
          result.blue = rgbTopMiddle.blue * ycRatio2
              + rgbBottomMiddle.blue * ycRatio1;
          result.red = rgbTopMiddle.red * ycRatio2
              + rgbBottomMiddle.red * ycRatio1;
          result.green = rgbTopMiddle.green * ycRatio2
              + rgbBottomMiddle.green * ycRatio1;
          newBitmapPixels[(y * newWidth) + x] = convertArgbToInt(result);
          }
      }
      //get rid of old data, and replace it with new one
      delete[] previousData;
      jniBitmap-&gt;_storedBitmapPixels = newBitmapPixels;
      jniBitmap-&gt;_bitmapInfo.width = newWidth;
      jniBitmap-&gt;_bitmapInfo.height = newHeight;
      }
  </code></pre>
  
  <h2>The question</h2>
  
  <p>What am I doing wrong?</p>
  
  <p>Is it also possible to make the code a bit more readable? I'm a bit rusty on C/C++ and I was more of a C developer than a C++ developer.</p>
  
  <p>EDIT: now it works fine. I've edited and fixed the code.</p>
  
  <p>Only thing that you guys can help is giving tips about how to make it better.</p>