android - एंड्रॉइड पर बैलिनेयर इंटरपोलेशन कोड को जावा से सी/सी++ कन्वर्ट करने की कोशिश कर रहा है



c++ image-processing (1)

ठीक है, यह सब रंगों के खराब रूपांतरण के साथ शुरू हुआ, फिर यह पॉइंटर्स के उपयोग के लिए चला गया, और फिर पिक्सेल को कहां रखा गया

मैंने लिखा है कि कोड ठीक काम करता है (सभी आवश्यक सुधारों को जोड़ा गया)

जल्द ही आप सभी Github प्रोजेक्ट पर नए कोड का उपयोग करने में सक्षम होंगे।

पृष्ठभूमि

मैंने जेएनआई का उपयोग करके बिटमैप्स को संभालने के लिए एक छोटे एंड्रॉइड लाइब्रेरी बनाई है ( यहां लिंक)

लंबे अतीत में, मैंने बिलीयनर इंटरपोलेशन के कुछ कोड को छवियों के स्केलिंग के संभावित एल्गोरिथ्म के रूप में बनाया है। एल्गोरिथ्म थोड़ा जटिल है और लक्ष्य पिक्सेल बनाने के लिए लगभग पिक्सल का उपयोग करता है।

समस्या

भले ही कोई त्रुटियां नहीं हैं (कोई संकलन त्रुटियां और कोई रनटाइम त्रुटियां नहीं हैं), आउटपुट छवि इस तरह दिखती है (चौड़ाई x2 से बढ़ाई गई है):

कोड

असल में मूल जावा कोड SWT का इस्तेमाल किया और केवल आरजीबी का समर्थन किया, लेकिन यह अल्फा चैनल के लिए समान है। यह पूरी तरह से पहले काम किया था (हालांकि अब जब मैं इसे देखता हूं, तो रास्ते में कई ऑब्जेक्ट बनाने लगता है)।

यहां जावा कोड है:

/** 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<oldWidth;++x)
      for(y=0;y<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<newWidth;x++)
      {
      xTopLeft=(int)(xt=x/xRatio);
      // when meeting the most right edge, move left a little
      if(xTopLeft>=oldWidth-1)
        xTopLeft--;
      if(xt<=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<newHeight;y++)
        {
        yTopLeft=(int)(yt=y/yratio);
        // when meeting the most bottom edge, move up a little
        if(yTopLeft>=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<=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))));
        }
      }
    }
  }

और यहाँ सी / सी ++ कोड है जिसे मैंने इसे बनाने की कोशिश की है:

typedef struct
    {
    uint8_t alpha, red, green, blue;
    } ARGB;

int32_t convertArgbToInt(ARGB argb)
    {
    return (argb.alpha) | (argb.red << 16) | (argb.green << 8)
        | (argb.blue << 24);
    }

void convertIntToArgb(uint32_t pixel, ARGB* argb)
    {
    argb->red = ((pixel >> 24) & 0xff);
    argb->green = ((pixel >> 16) & 0xff);
    argb->blue = ((pixel >> 8) & 0xff);
    argb->alpha = (pixel & 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->GetDirectBufferAddress(handle);
    if (jniBitmap->_storedBitmapPixels == NULL)
    return;
    uint32_t oldWidth = jniBitmap->_bitmapInfo.width;
    uint32_t oldHeight = jniBitmap->_bitmapInfo.height;
    uint32_t* previousData = jniBitmap->_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 < newWidth; ++x)
    {
    xTopLeft = (int) (xt = x / xRatio);
    // when meeting the most right edge, move left a little
    if (xTopLeft >= oldWidth - 1)
        xTopLeft--;
    if (xt <= 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 < newHeight; ++y)
        {
        yTopLeft = (int) (yt = y / yratio);
        // when meeting the most bottom edge, move up a little
        if (yTopLeft >= 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],
            &rgbBottomLeft);
        //rgbBottomRight=startingImageData[xTopLeft+1][yTopLeft+1];
        convertIntToArgb(
            previousData[((yTopLeft + 1) * oldWidth)
                + (xTopLeft + 1)], &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],
            &rgbTopLeft);
        //rgbTopRight=startingImageData[xTopLeft+1][yTopLeft];
        convertIntToArgb(
            previousData[((yTopLeft + 1) * oldWidth) + xTopLeft],
            &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],
            &rgbBottomLeft);
        //rgbBottomRight=startingImageData[xTopLeft+1][yTopLeft+1];
        convertIntToArgb(
            previousData[((yTopLeft + 1) * oldWidth)
                + (xTopLeft + 1)], &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 <= 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->_storedBitmapPixels = newBitmapPixels;
    jniBitmap->_bitmapInfo.width = newWidth;
    jniBitmap->_bitmapInfo.height = newHeight;
    }

प्रश्न

मैं क्या गलत कर रहा हूं?

क्या कोड को थोड़ा और पठनीय बनाने के लिए भी संभव है? मैं सी / सी ++ पर थोड़ी सी जंगली हूँ और मैं सी + + डेवलपर की तुलना में सी डेवलपर का अधिक था।

संपादित करें: अब यह ठीक काम करता है। मैंने कोड को संपादित और तय किया है

केवल एक चीज है कि आप लोग मदद कर सकते हैं कि इसे बेहतर बनाने के बारे में सुझाव दे रहे हैं






argb