2013-02-27 82 views
11

我正在为以下问题寻求解决方案:如何将Bitmap的大小更改为固定大小(例如512x128)。位图内容的高宽比必须保留。将位图调整为固定值,但不改变宽高比

我想应该是这样的:

  • 创建一个空的512x128位图

  • 规模原始位下降到与保持宽高比

  • 配合512x128像素将缩放复制到空位图(居中)

实现此目的的最简单方法是什么?

所有这一切的原因是,GridView当图像的宽高比不同时,会使布局紊乱。下面是一个屏幕截图(除了最后一个的所有图像为4的纵横比:1):

screenshot

回答

25

试试这个,计算比率,然后重新调整。

private Bitmap scaleBitmap(Bitmap bm) { 
    int width = bm.getWidth(); 
    int height = bm.getHeight(); 

    Log.v("Pictures", "Width and height are " + width + "--" + height); 

    if (width > height) { 
     // landscape 
     float ratio = (float) width/maxWidth; 
     width = maxWidth; 
     height = (int)(height/ratio); 
    } else if (height > width) { 
     // portrait 
     float ratio = (float) height/maxHeight; 
     height = maxHeight; 
     width = (int)(width/ratio); 
    } else { 
     // square 
     height = maxHeight; 
     width = maxWidth; 
    } 

    Log.v("Pictures", "after scaling Width and height are " + width + "--" + height); 

    bm = Bitmap.createScaledBitmap(bm, width, height, true); 
    return bm; 
} 
+2

加一个简单的解决方案。但我会改变诠释比率浮动/双倍比率,因为int/int可能会产生例外,当它尝试除以0. – 2014-08-05 15:00:48

+0

真棒简单的解决方案!但是使用浮点数来代替整数是必须的。否则结果在大多数情况下可能是错误的(例如,当它应该是1.4时比率变为1)。 – xip 2014-11-10 20:42:51

+0

@Hikaru你是对的,想要做到这一点,但从来没有去过。感谢您的编辑和提醒 - ) – 2014-11-11 08:21:17

0

https://developer.android.com/reference/android/graphics/Bitmap.html#createScaledBitmap(android.graphics.Bitmap, int, int, boolean)

并确保两者dstWidthdstHeightsrc.getWidth()*scalesrc.getHeight()*scale获得,其中scale是您需要确定的值,以确保缩放的位图适合512x128内部。

+0

'createScaledBitmap'不能解决我的问题。这就是我已经使用的。在这个例子中,最后一幅图像已经被缩放了。 – 2013-02-27 23:32:26

+0

如果你已经有一个按比例缩小的位图(宽度小于512或者在你的例子中高度小于128),只需在GridView项目的ImageView中将这些属性设置为android:layout_width =“512dp”和android:layout_height =“128dp “和android:scaleType =”center“或android:scaleType =”centerInside“ – 2013-02-28 00:38:29

+0

根据我的解释,示例中的最后一幅图像已经缩小了,所以它已经是最大值了。 128px高。尽管如此,图像视图显示它比其他图像更大。另外我不想用512x128dp网格的图像视图。 – 2013-02-28 23:14:39

2

我在我的项目中偶然发现过相同的问题,每次都因缺乏时间(和懒惰)而感到满意,我不满足于最佳解决方案。但最近我发现了一些时间来打击这个特殊问题。这里是我的解决方案,我希望它可以帮助别人了线......

Bitmap scaleDownLargeImageWithAspectRatio(Bitmap image) 
      { 
       int imaheVerticalAspectRatio,imageHorizontalAspectRatio; 
       float bestFitScalingFactor=0; 
       float percesionValue=(float) 0.2; 

       //getAspect Ratio of Image 
       int imageHeight=(int) (Math.ceil((double) image.getHeight()/100)*100); 
       int imageWidth=(int) (Math.ceil((double) image.getWidth()/100)*100); 
       int GCD=BigInteger.valueOf(imageHeight).gcd(BigInteger.valueOf(imageWidth)).intValue(); 
       imaheVerticalAspectRatio=imageHeight/GCD; 
       imageHorizontalAspectRatio=imageWidth/GCD; 
       Log.i("scaleDownLargeImageWIthAspectRatio","Image Dimensions(W:H): "+imageWidth+":"+imageHeight); 
       Log.i("scaleDownLargeImageWIthAspectRatio","Image AspectRatio(W:H): "+imageHorizontalAspectRatio+":"+imaheVerticalAspectRatio); 

       //getContainer Dimensions 
       int displayWidth = getWindowManager().getDefaultDisplay().getWidth(); 
       int displayHeight = getWindowManager().getDefaultDisplay().getHeight(); 
       //I wanted to show the image to fit the entire device, as a best case. So my ccontainer dimensions were displayWidth & displayHeight. For your case, you will need to fetch container dimensions at run time or you can pass static values to these two parameters 

       int leftMargin = 0; 
       int rightMargin = 0; 
       int topMargin = 0; 
       int bottomMargin = 0; 
       int containerWidth = displayWidth - (leftMargin + rightMargin); 
       int containerHeight = displayHeight - (topMargin + bottomMargin); 
       Log.i("scaleDownLargeImageWIthAspectRatio","Container dimensions(W:H): "+containerWidth+":"+containerHeight); 

       //iterate to get bestFitScaleFactor per constraints 
       while((imageHorizontalAspectRatio*bestFitScalingFactor <= containerWidth) && 
         (imaheVerticalAspectRatio*bestFitScalingFactor<= containerHeight)) 
       { 
        bestFitScalingFactor+=percesionValue; 
       } 

       //return bestFit bitmap 
       int bestFitHeight=(int) (imaheVerticalAspectRatio*bestFitScalingFactor); 
       int bestFitWidth=(int) (imageHorizontalAspectRatio*bestFitScalingFactor); 
       Log.i("scaleDownLargeImageWIthAspectRatio","bestFitScalingFactor: "+bestFitScalingFactor); 
       Log.i("scaleDownLargeImageWIthAspectRatio","bestFitOutPutDimesions(W:H): "+bestFitWidth+":"+bestFitHeight); 
       image=Bitmap.createScaledBitmap(image, bestFitWidth,bestFitHeight, true); 

       //Position the bitmap centre of the container 
       int leftPadding=(containerWidth-image.getWidth())/2; 
       int topPadding=(containerHeight-image.getHeight())/2; 
       Bitmap backDrop=Bitmap.createBitmap(containerWidth, containerHeight, Bitmap.Config.RGB_565); 
       Canvas can = new Canvas(backDrop); 
       can.drawBitmap(image, leftPadding, topPadding, null); 

       return backDrop; 
      } 
18

Coen Damen的回答并不总是尊重最大高度和最大宽度。 这里的答案是:

private static Bitmap resize(Bitmap image, int maxWidth, int maxHeight) { 
    if (maxHeight > 0 && maxWidth > 0) { 
     int width = image.getWidth(); 
     int height = image.getHeight(); 
     float ratioBitmap = (float) width/(float) height; 
     float ratioMax = (float) maxWidth/(float) maxHeight; 

     int finalWidth = maxWidth; 
     int finalHeight = maxHeight; 
     if (ratioMax > 1) { 
      finalWidth = (int) ((float)maxHeight * ratioBitmap); 
     } else { 
      finalHeight = (int) ((float)maxWidth/ratioBitmap); 
     } 
     image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true); 
     return image; 
    } else { 
     return image; 
    } 
} 
+0

窃取我的答案很好。当然maxWidth和maxHeight是类变量而不是方法参数。 – 2017-01-11 09:36:22

相关问题