次の問題の解決策を探しています:Bitmap
のサイズを固定サイズ(たとえば512x128)に変更する方法。ビットマップコンテンツのアスペクト比を維持する必要があります。
私はそれがこのようなものであるべきだと思います:
空の512x128ビットマップを作成する
アスペクト比を維持しながら、512x128ピクセルに合うように元のビットマップを縮小します
スケーリングされたものを空のビットマップにコピーします(中央)
これを達成するための最も簡単な方法は何ですか?
このすべての理由は、画像のアスペクト比が他と異なる場合、GridView
がレイアウトを台無しにするためです。これがスクリーンショットです(最後の画像を除くすべての画像のアスペクト比は4:1です):
これを試して、比率を計算してから再スケーリングしてください。
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;
}
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;
}
}
私は自分のプロジェクトで同じ問題に何度も遭遇しましたが、そのたびに時間の不足(および怠惰)のために、最適とは言えない解決策に満足するでしょう。しかし最近、私はこの特定の問題を取り締まる時間を見つけました。これが私の解決策であり、それが将来の誰かに役立つことを願っています...
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;
}
dstWidth
とdstHeight
の両方がsrc.getWidth()*scale
とsrc.getHeight()*scale
から取得されていることを確認します。ここで、scale
はスケーリングされたビットマップが512x128内に収まるかどうかを確認する必要があります。
@Coenの答えは、この質問に対する正しい解決策ではないと思います。私もこのような方法が必要でしたが、画像を正方形にしたかったのです。
これが正方形の画像に対する私の解決策です。
public static Bitmap resizeBitmapImageForFitSquare(Bitmap image, int maxResolution) {
if (maxResolution <= 0)
return image;
int width = image.getWidth();
int height = image.getHeight();
float ratio = (width >= height) ? (float)maxResolution/width :(float)maxResolution/height;
int finalWidth = (int) ((float)width * ratio);
int finalHeight = (int) ((float)height * ratio);
image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true);
if (image.getWidth() == image.getHeight())
return image;
else {
//fit height and width
int left = 0;
int top = 0;
if(image.getWidth() != maxResolution)
left = (maxResolution - image.getWidth()) / 2;
if(image.getHeight() != maxResolution)
top = (maxResolution - image.getHeight()) / 2;
Bitmap bitmap = Bitmap.createBitmap(maxResolution, maxResolution, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(image, left, top, null);
canvas.save();
canvas.restore();
return bitmap;
}
}