71

Bitmapアスペクト比が維持され、Bitmap幅全体を塗りつぶし、画像を垂直方向に中央揃えにして、余分な部分をトリミングするか、ギャップを0アルファピクセルで埋める、実行時に依存する幅と高さにaをスケーリングしたいと思います。

私は現在Bitmap、すべての0アルファピクセルを作成してそのBitmap上に画像を描画し、指定された正確な幅にスケーリングしてアスペクト比を維持することでビットマップを自分で再描画していますが、ピクセルデータが失われたりねじれたりしてしまいます。

これが私がそれをしている方法です:

Bitmap background = Bitmap.createBitmap((int)width, (int)height, Config.ARGB_8888);
float originalWidth = originalImage.getWidth(), originalHeight = originalImage.getHeight();
Canvas canvas = new Canvas(background);
float scale = width/originalWidth;
float xTranslation = 0.0f, yTranslation = (height - originalHeight * scale)/2.0f;
Matrix transformation = new Matrix();
transformation.postTranslate(xTranslation, yTranslation);
transformation.preScale(scale, scale);
canvas.drawBitmap(originalImage, transformation, null);
return background;

そこにライブラリがありますか、またはこれをより良くすることができるいくつかのより良いコードがありますか?できるだけ鮮明な画像にしたいのですが、自分の機能ではうまくいかないことはわかっていました。

フロートスケーリングの代わりに整数スケーリングを使用することで画像を正常に保つことができることはわかっていますが、幅を100%塗りつぶす必要があります。

ImageViewまた、の機能については知っていGravity.CENTER_CROPますが、整数スケーリングも使用するため、画像の幅を切り落とす必要があります。

4

13 に答える 13

122

これは、maxWidth と maxHeight を考慮します。つまり、結果のビットマップのサイズが次のサイズよりも大きくなることはありません。

 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 > ratioBitmap) {
            finalWidth = (int) ((float)maxHeight * ratioBitmap);
        } else {
            finalHeight = (int) ((float)maxWidth / ratioBitmap);
        }
        image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true);
        return image;
    } else {
        return image;
    }
}
于 2015-02-06T13:49:18.600 に答える
75

これはどうですか:

Bitmap background = Bitmap.createBitmap((int)width, (int)height, Config.ARGB_8888);

float originalWidth = originalImage.getWidth(); 
float originalHeight = originalImage.getHeight();

Canvas canvas = new Canvas(background);

float scale = width / originalWidth;

float xTranslation = 0.0f;
float yTranslation = (height - originalHeight * scale) / 2.0f;

Matrix transformation = new Matrix();
transformation.postTranslate(xTranslation, yTranslation);
transformation.preScale(scale, scale);

Paint paint = new Paint();
paint.setFilterBitmap(true);

canvas.drawBitmap(originalImage, transformation, paint);

return background;

paintスケーリングされたビットマップをフィルター処理するために を追加しました。

于 2013-03-15T20:12:57.330 に答える
25

ここでは、ビットマップ ファイルからスケーリングされたビットマップを作成するテスト済みのソリューションを示します。

    int scaleSize =1024;

    public Bitmap resizeImageForImageView(Bitmap bitmap) {
        Bitmap resizedBitmap = null;
        int originalWidth = bitmap.getWidth();
        int originalHeight = bitmap.getHeight();
        int newWidth = -1;
        int newHeight = -1;
        float multFactor = -1.0F;
        if(originalHeight > originalWidth) {
            newHeight = scaleSize ;
            multFactor = (float) originalWidth/(float) originalHeight;
            newWidth = (int) (newHeight*multFactor);
        } else if(originalWidth > originalHeight) {
            newWidth = scaleSize ;
            multFactor = (float) originalHeight/ (float)originalWidth;
            newHeight = (int) (newWidth*multFactor);
        } else if(originalHeight == originalWidth) {
            newHeight = scaleSize ;
            newWidth = scaleSize ;
        }
        resizedBitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, false);
        return resizedBitmap;
    }

最大サイズが 4096x4096 ピクセルのスケーリングされたビットマップが必要ですが、サイズ変更中にアスペクト比を維持する必要があることに注意してください。幅または高さに他の値が必要な場合は、値「4096」を置き換えてください。

これはCoenの回答への単なる追加ですが、彼のコードの問題は、比率を計算する行です. 2 つの整数を除算すると整数が得られ、結果が 1 未満の場合は 0 に丸められます。そのため、「ゼロ除算」例外がスローされます。

于 2014-07-25T07:31:51.300 に答える
8

上記の答えはどれもうまくいきませんでした。空の領域を黒く塗りつぶして、すべての寸法を目的の寸法に設定する方法を作成しました。これが私の方法です:

/**
 * Scale the image preserving the ratio
 * @param imageToScale Image to be scaled
 * @param destinationWidth Destination width after scaling
 * @param destinationHeight Destination height after scaling
 * @return New scaled bitmap preserving the ratio
 */
public static Bitmap scalePreserveRatio(Bitmap imageToScale, int destinationWidth,
        int destinationHeight) {
    if (destinationHeight > 0 && destinationWidth > 0 && imageToScale != null) {
        int width = imageToScale.getWidth();
        int height = imageToScale.getHeight();

        //Calculate the max changing amount and decide which dimension to use
        float widthRatio = (float) destinationWidth / (float) width;
        float heightRatio = (float) destinationHeight / (float) height;

        //Use the ratio that will fit the image into the desired sizes
        int finalWidth = (int)Math.floor(width * widthRatio);
        int finalHeight = (int)Math.floor(height * widthRatio);
        if (finalWidth > destinationWidth || finalHeight > destinationHeight) {
            finalWidth = (int)Math.floor(width * heightRatio);
            finalHeight = (int)Math.floor(height * heightRatio);
        }

        //Scale given bitmap to fit into the desired area
        imageToScale = Bitmap.createScaledBitmap(imageToScale, finalWidth, finalHeight, true);

        //Created a bitmap with desired sizes
        Bitmap scaledImage = Bitmap.createBitmap(destinationWidth, destinationHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(scaledImage);

        //Draw background color
        Paint paint = new Paint();
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);

        //Calculate the ratios and decide which part will have empty areas (width or height)
        float ratioBitmap = (float)finalWidth / (float)finalHeight;
        float destinationRatio = (float) destinationWidth / (float) destinationHeight;
        float left = ratioBitmap >= destinationRatio ? 0 : (float)(destinationWidth - finalWidth) / 2;
        float top = ratioBitmap < destinationRatio ? 0: (float)(destinationHeight - finalHeight) / 2;
        canvas.drawBitmap(imageToScale, left, top, null);

        return scaledImage;
    } else {
        return imageToScale;
    }
}

例えば;

100 x 100 の画像があり、目的のサイズが 300x50 であるとします。このメソッドは、画像を 50 x 50 に変換し、300 x 50 の寸法を持つ新しい画像にペイントします (空のフィールドは黒になります)。 .

別の例: 600 x 1000 の画像があり、希望のサイズが再び 300 x 50 であるとします。この場合、画像は 30 x 50 に変換され、サイズが 300 x 50 の新しく作成された画像にペイントされます。

私はこれがそうあるべきだと思います、ルピー。

于 2015-09-27T16:31:07.003 に答える
7

より簡単な解決策:幅を500ピクセルに設定していることに注意してください

 public void scaleImageKeepAspectRatio()
    {
        int imageWidth = scaledGalleryBitmap.getWidth();
        int imageHeight = scaledGalleryBitmap.getHeight();
        int newHeight = (imageHeight * 500)/imageWidth;
        scaledGalleryBitmap = Bitmap.createScaledBitmap(scaledGalleryBitmap, 500, newHeight, false);

    }
于 2016-01-10T11:04:27.780 に答える
5

It can also be done by calculating the ratio yourself, like this.

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
        int ratio = width / maxWidth;
        width = maxWidth;
        height = height / ratio;
    } else if (height > width) {
        // portrait
        int ratio = height / maxHeight;
        height = maxHeight;
        width = 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;
}
于 2014-04-05T15:19:23.473 に答える
1

私の解決策はこれで、アスペクト比を維持し、1 つのサイズのみを必要とします。 720*1280 になります

public static Bitmap resizeBitmap(final Bitmap temp, final int size) {
        if (size > 0) {
            int width = temp.getWidth();
            int height = temp.getHeight();
            float ratioBitmap = (float) width / (float) height;
            int finalWidth = size;
            int finalHeight = size;
            if (ratioBitmap < 1) {
                finalWidth = (int) ((float) size * ratioBitmap);
            } else {
                finalHeight = (int) ((float) size / ratioBitmap);
            }
            return Bitmap.createScaledBitmap(temp, finalWidth, finalHeight, true);
        } else {
            return temp;
        }
    }
于 2016-12-06T13:36:56.090 に答える
0

画像の再スケーリングには簡単な計算が必要です。次のスニペットを考慮して、次の手順に従ってください。

originalWidth = 720;
wP = 720/100;
/*  wP = 7.20 is a percentage value */
  1. 元の幅から必要な幅を引き、その結果に を掛けwPます。縮小される幅のパーセンテージが得られます。

difference = originalWidth - 420; dP = difference/wP;

ここでdPは 41.66 になります。これは、サイズを 41.66% 縮小していることを意味します。dPしたがって、その画像の比率またはスケールを維持するには、高さを 41.66( ) 減らす必要があります。以下のように高さを計算します。

hP = originalHeight / 100;
//here height percentage will be 1280/100 = 12.80
height = originalHeight - ( hp * dP);
// here 1280 - (12.80 * 41.66) = 746.75

これがフィッティング スケールです。画像/ビットマップのサイズを 420x747 に変更できます。比率/スケールを失うことなく、サイズ変更された画像を返します。

public static Bitmap scaleToFit(Bitmap image, int width, int height, bool isWidthReference) {
    if (isWidthReference) {
        int originalWidth = image.getWidth();
        float wP = width / 100;
        float dP = ( originalWidth - width) / wP;
        int originalHeight = image.getHeight();
        float hP = originalHeight / 100;
        int height = originalHeight - (hP * dP);
        image = Bitmap.createScaledBitmap(image, width, height, true);
    } else {
        int originalHeight = image.getHeight();
        float hP = height / 100;
        float dP = ( originalHeight - height) / hP;
        int originalWidth = image.getWidth();
        float wP = originalWidth / 100;
        int width = originalWidth - (wP * dP);
        image = Bitmap.createScaledBitmap(image, width, height, true);
    }
    return image;
}

ここでは、必要な基準に収まるように、高さまたは幅のパラメーターを参照して画像を単純にスケーリングしています。

于 2019-07-26T18:22:41.253 に答える