web-dev-qa-db-fra.com

Redimensionner un bitmap en valeur fixe mais sans changer le rapport de format

Je cherche une solution au problème suivant: comment modifier la taille d'une variable Bitmap en une taille fixe (par exemple, 512x128). Le rapport hauteur/largeur du contenu bitmap doit être préservé.

Je pense que ça devrait être quelque chose comme ça:

  • créer un bitmap vide de 512x128

  • redimensionne le bitmap d'origine pour l'adapter aux 512x128 pixels tout en conservant le rapport hauteur/largeur

  • copier la mise à l'échelle dans le bitmap vide (centré)

Quel est le moyen le plus simple d'y parvenir?

La raison de tout cela est que la GridView perturbe la mise en page lorsque le format de l'image diffère de celui de l'autre. Voici une capture d'écran (toutes les images sauf la dernière ont un rapport d'aspect de 4: 1):

capture d'écran

14
Dark.Rider

Essayez ceci, calculez le rapport puis redimensionnez.

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

La réponse de Coen Damen ne respecte pas toujours la hauteur maximale et la largeur maximale. Voici une réponse qui:

 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

Je suis tombé sur le même problème à plusieurs reprises dans mes projets et à chaque fois, faute de temps (et de paresse), je me contenterais d'une solution moins qu'optimale. Mais récemment, j'ai trouvé un peu de temps pour lutter contre ce problème particulier. Voici ma solution et j'espère que cela aidera quelqu'un en bout de ligne ...

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)

et assurez-vous que les variables dstWidth et dstHeight sont obtenues à partir de src.getWidth()*scale et src.getHeight()*scale, où scale est une valeur que vous devez déterminer pour vous assurer que l'image bitmap redimensionnée convient à 512x128.

1
Streets Of Boston

Je pense que la réponse de @ Coen n’est pas la bonne solution pour cette question. J'avais aussi besoin d'une méthode comme celle-ci mais je voulais une image carrée. 

Voici ma solution pour l'image carrée;

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