Изменение размера растрового изображения на фиксированное значение, но без изменения соотношения сторон
Я ищу решение для следующей проблемы: как изменить размер Bitmap
на фиксированный размер (например, 512x128). Соотношение сторон содержимого растрового изображения должно быть сохранено.
Я думаю, что это должно быть примерно так:
-
создать пустую растровую карту 512x128
-
масштабируйте исходное растровое изображение до 512x128 пикселей с сохранением формата изображения
-
скопируйте масштаб в пустое растровое изображение (в центре)
Каков самый простой способ достичь этого?
Причиной всего этого является то, что GridView
испортит компоновку, когда соотношение сторон изображения отличается от другого. Вот скриншот (все изображения, кроме последнего, имеют соотношение сторон 4: 1):
скриншот
Ответы
Ответ 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;
}
Ответ 2
Ответ Коэна Дамена не всегда учитывает максимальную высоту и максимальную ширину.
Вот ответ, который делает:
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;
}
}
Ответ 3
Я неоднократно сталкивался с той же проблемой несколько раз в своих проектах, и каждый раз из-за нехватки времени (и лени) я был бы удовлетворен менее оптимальным решением. Но недавно я нашел некоторое время, чтобы решить эту проблему. Вот мое решение, и я надеюсь, что это поможет кому-то по очереди...
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;
}
Ответ 4
https://developer.android.com/reference/android/graphics/Bitmap.html#createScaledBitmap (android.graphics.Bitmap, int, int, булево)
и убедитесь, что как dstWidth
, так и dstHeight
получены из src.getWidth()*scale
и src.getHeight()*scale
, где scale
- это значение, которое необходимо определить, чтобы убедиться, что масштабированный растровый рисунок помещается внутри 512x128.
Ответ 5
Я думаю, что ответ @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;
}
}