Подтвердить что ты не робот

Изменение размера растрового изображения на фиксированное значение, но без изменения соотношения сторон

Я ищу решение для следующей проблемы: как изменить размер Bitmap на фиксированный размер (например, 512x128). Соотношение сторон содержимого растрового изображения должно быть сохранено.

Я думаю, что это должно быть примерно так:

  • создать пустую растровую карту 512x128

  • масштабируйте исходное растровое изображение до 512x128 пикселей с сохранением формата изображения

  • скопируйте масштаб в пустое растровое изображение (в центре)

Каков самый простой способ достичь этого?

Причиной всего этого является то, что GridView испортит компоновку, когда соотношение сторон изображения отличается от другого. Вот скриншот (все изображения, кроме последнего, имеют соотношение сторон 4: 1):

скриншот

4b9b3361

Ответ 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;
    }
}