web-dev-qa-db-ja.com

ビットマップのサイズを固定値に変更しますが、アスペクト比は変更しません

次の問題の解決策を探しています:Bitmapのサイズを固定サイズ(たとえば512x128)に変更する方法。ビットマップコンテンツのアスペクト比を維持する必要があります。

私はそれがこのようなものであるべきだと思います:

  • 空の512x128ビットマップを作成する

  • アスペクト比を維持しながら、512x128ピクセルに合うように元のビットマップを縮小します

  • スケーリングされたものを空のビットマップにコピーします(中央)

これを達成するための最も簡単な方法は何ですか?

このすべての理由は、画像のアスペクト比が他と異なる場合、GridViewがレイアウトを台無しにするためです。これがスクリーンショットです(最後の画像を除くすべての画像のアスペクト比は4:1です):

スクリーンショット

14
Dark.Rider

これを試して、比率を計算してから再スケーリングしてください。

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;
}
30
Coen Damen

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;
    }
}
19
joaomgcd

私は自分のプロジェクトで同じ問題に何度も遭遇しましたが、そのたびに時間の不足(および怠惰)のために、最適とは言えない解決策に満足するでしょう。しかし最近、私はこの特定の問題を取り締まる時間を見つけました。これが私の解決策であり、それが将来の誰かに役立つことを願っています...

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;
            }
2
Parth Kapoor

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

dstWidthdstHeightの両方がsrc.getWidth()*scalesrc.getHeight()*scaleから取得されていることを確認します。ここで、scaleはスケーリングされたビットマップが512x128内に収まるかどうかを確認する必要があります。

1

@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;
    }
}
0
Savas Adar