在Android中使用双线性算法调整位图大小时花费太多时间

时间:2015-12-22 14:59:30

标签: android algorithm bitmap

我正在开发一个将大型位图加载到ImageView中的应用程序。在这里,我使用Bi线性算法来重新调整图像大小并且它工作正常,但它需要花费太多时间来调整大小(双线性算法)。我在下面添加一些代码。

这是代码:

mutableBitmap = biLinear(mutableBitmap, outWidth,outHeight);// Bi-Linear code 
mutableBitmap = Bitmap.createBitmap(mutableBitmap, 0, 0, mutableBitmap.getWidth(),
                mutableBitmap.getHeight(), m, true); 

双线性算法方法:

 public static Bitmap biLinear(final Bitmap input,int outWidth,int outHeight)
  {
  final int oldHeight=input.getHeight(),oldWidth=input.getWidth();
  final int newHeight=outHeight,newWidth=outWidth;

  Bitmap output =Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);

  // 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;
  int rgbTopLeft=0,rgbTopRight=0,rgbBottomLeft=0,rgbBottomRight=0,rgbTopMiddle=0,rgbBottomMiddle=0;
  // 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=input.getPixel(xTopLeft,yTopLeft+1);
        rgbBottomRight=input.getPixel(xTopLeft+1,yTopLeft+1);
        rgbBottomMiddle=Color.argb((int)(Color.alpha(rgbBottomLeft)*xcRatio2+Color.alpha(rgbBottomRight)*xcratio1),//
            (int)(Color.red(rgbBottomLeft)*xcRatio2+Color.red(rgbBottomRight)*xcratio1),//
            (int)(Color.green(rgbBottomLeft)*xcRatio2+Color.green(rgbBottomRight)*xcratio1),//
            (int)(Color.blue(rgbBottomLeft)*xcRatio2+Color.blue(rgbBottomRight)*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=input.getPixel(xTopLeft,yTopLeft);
        rgbTopRight=input.getPixel(xTopLeft+1,yTopLeft);
        rgbTopMiddle=Color.argb((int)(Color.alpha(rgbTopLeft)*xcRatio2+Color.alpha(rgbTopRight)*xcratio1),//
            (int)(Color.red(rgbTopLeft)*xcRatio2+Color.red(rgbTopRight)*xcratio1),//
            (int)(Color.green(rgbTopLeft)*xcRatio2+Color.green(rgbTopRight)*xcratio1),//
            (int)(Color.blue(rgbTopLeft)*xcRatio2+Color.blue(rgbTopRight)*xcratio1));
        rgbBottomLeft=input.getPixel(xTopLeft,yTopLeft+1);
        rgbBottomRight=input.getPixel(xTopLeft+1,yTopLeft+1);
        rgbBottomMiddle=Color.argb((int)(Color.alpha(rgbBottomLeft)*xcRatio2+Color.alpha(rgbBottomRight)*xcratio1),//
            (int)(Color.red(rgbBottomLeft)*xcRatio2+Color.red(rgbBottomRight)*xcratio1),//
            (int)(Color.green(rgbBottomLeft)*xcRatio2+Color.green(rgbBottomRight)*xcratio1),//
            (int)(Color.blue(rgbBottomLeft)*xcRatio2+Color.blue(rgbBottomRight)*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
      output.setPixel(x,y,Color.argb(//
          (int)(Color.alpha(rgbTopMiddle)*ycRatio2+Color.alpha(rgbBottomMiddle)*ycRatio1),//
          (int)(Color.red(rgbTopMiddle)*ycRatio2+Color.red(rgbBottomMiddle)*ycRatio1),//
          (int)(Color.green(rgbTopMiddle)*ycRatio2+Color.green(rgbBottomMiddle)*ycRatio1),//
          (int)(Color.blue(rgbTopMiddle)*ycRatio2+Color.blue(rgbBottomRight)*ycRatio1)));
      }
    }
  return output;
  }

此算法需要将近15-20秒来加载图像

是否有可能减少加载时间

如果有人有意,请帮帮我

先谢谢。

1 个答案:

答案 0 :(得分:3)

每个像素调用getPixel / setPixel方法可能需要很长时间。 我建议你改用copyPixelsToBuffer / copyPixelsFromBuffer方法。

e.g:

    public static Bitmap biLinear(final Bitmap input,int outWidth,int outHeight) {

    if(input.getConfig() != Bitmap.Config.ARGB_8888) {
        // this example assumes that input bitmap configuration is Bitmap.Config.ARGB_8888
        throw new RuntimeException();
    }


    final int oldHeight=input.getHeight(),oldWidth=input.getWidth();
    final int newHeight=outHeight,newWidth=outWidth;

    IntBuffer inputBuffer = IntBuffer.allocate(oldWidth * oldHeight);
    IntBuffer outputBuffer = IntBuffer.allocate(newWidth * newHeight);

    Bitmap output = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);

    input.copyPixelsToBuffer(inputBuffer);

    // 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;
    int rgbTopLeft=0,rgbTopRight=0,rgbBottomLeft=0,rgbBottomRight=0,rgbTopMiddle=0,rgbBottomMiddle=0;
    // 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=inputBuffer.get(xTopLeft + (oldWidth * (yTopLeft+1)));
                rgbBottomRight=inputBuffer.get(xTopLeft+1 + (oldWidth * (yTopLeft+1)));
                rgbBottomMiddle=Color.argb((int)(Color.alpha(rgbBottomLeft)*xcRatio2+Color.alpha(rgbBottomRight)*xcratio1),//
                        (int)(Color.red(rgbBottomLeft)*xcRatio2+Color.red(rgbBottomRight)*xcratio1),//
                        (int)(Color.green(rgbBottomLeft)*xcRatio2+Color.green(rgbBottomRight)*xcratio1),//
                        (int)(Color.blue(rgbBottomLeft)*xcRatio2+Color.blue(rgbBottomRight)*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=inputBuffer.get(xTopLeft + (oldWidth * yTopLeft));
                rgbTopRight=inputBuffer.get(xTopLeft+1 + (oldWidth * yTopLeft));
                rgbTopMiddle=Color.argb((int)(Color.alpha(rgbTopLeft)*xcRatio2+Color.alpha(rgbTopRight)*xcratio1),//
                        (int)(Color.red(rgbTopLeft)*xcRatio2+Color.red(rgbTopRight)*xcratio1),//
                        (int)(Color.green(rgbTopLeft)*xcRatio2+Color.green(rgbTopRight)*xcratio1),//
                        (int)(Color.blue(rgbTopLeft)*xcRatio2+Color.blue(rgbTopRight)*xcratio1));
                rgbBottomLeft=inputBuffer.get(xTopLeft + (oldWidth * (yTopLeft+1)));
                rgbBottomRight=inputBuffer.get(xTopLeft+1+(oldWidth * (yTopLeft+1)));
                rgbBottomMiddle=Color.argb((int)(Color.alpha(rgbBottomLeft)*xcRatio2+Color.alpha(rgbBottomRight)*xcratio1),//
                        (int)(Color.red(rgbBottomLeft)*xcRatio2+Color.red(rgbBottomRight)*xcratio1),//
                        (int)(Color.green(rgbBottomLeft)*xcRatio2+Color.green(rgbBottomRight)*xcratio1),//
                        (int)(Color.blue(rgbBottomLeft)*xcRatio2+Color.blue(rgbBottomRight)*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
            outputBuffer.put(x + outWidth * y,Color.argb(//
                    (int)(Color.alpha(rgbTopMiddle)*ycRatio2+Color.alpha(rgbBottomMiddle)*ycRatio1),//
                    (int)(Color.red(rgbTopMiddle)*ycRatio2+Color.red(rgbBottomMiddle)*ycRatio1),//
                    (int)(Color.green(rgbTopMiddle)*ycRatio2+Color.green(rgbBottomMiddle)*ycRatio1),//
                    (int)(Color.blue(rgbTopMiddle)*ycRatio2+Color.blue(rgbBottomRight)*ycRatio1)));
        }
    }

    output.copyPixelsFromBuffer(outputBuffer);
    return output;
}