comment faire pivoter un bitmap de 90 degrés

123

Il y a une déclaration dans Android canvas.drawBitmap(visiblePage, 0, 0, paint);

Quand j'ajoute canvas.rotate(90), il n'y a aucun effet. Mais si j'écris

canvas.rotate(90)
canvas.drawBitmap(visiblePage, 0, 0, paint);

Je n'obtiens aucun bitmap dessiné. Alors qu'est-ce que je ne fais pas bien?

Murli
la source
J'ai répondu à ceci ici: stackoverflow.com/questions/8608734/…
EyalBellisha

Réponses:

254

Vous pouvez également essayer celui-ci

Matrix matrix = new Matrix();

matrix.postRotate(90);

Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmapOrg, width, height, true);

Bitmap rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);

Ensuite, vous pouvez utiliser l'image pivotée pour définir dans votre imageview via

imageView.setImageBitmap(rotatedBitmap);
aryen
la source
1
Je pense que pour le scaledBitmap que vous voulez (bitmapOrg, width, height, true)
Jameo
2
Quelle matrice importer? android.graphics ou android.opengl?
Poutrathor
6
Importation android.graphics
kirtan403
4
cela utilise beaucoup de mémoire. Pour les bitmaps volumineux, cela peut créer des problèmes en raison des multiples copies de bitmaps en mémoire.
Moritz Both
1
Si vous n'avez pas besoin du bitmap d'origine, appelez bitmap.recycle()pour en être certain.
Nick Bedford
174
public static Bitmap RotateBitmap(Bitmap source, float angle)
{
      Matrix matrix = new Matrix();
      matrix.postRotate(angle);
      return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}

Pour obtenir Bitmap à partir des ressources:

Bitmap source = BitmapFactory.decodeResource(this.getResources(), R.drawable.your_img);
Arvis
la source
1
Je suis nouveau avec Android. Je me demande simplement si je fais Bitmap newBitmap = RotateBitmap (oldBitmap, 90), mon 'bitmap décodé' a-t-il deux blocs de mémoire (pour l'ancien et le nouveau) ou font-ils référence à la même mémoire, mais l'un n'a pas de rotation, l'autre a une rotation ? .... Ma préoccupation est que si je décode R.drawable.picture en oldBitmap, si cela suppose 2 Mo de mémoire (Heap je suppose?), NewBitmap prendra-t-il 2 Mo supplémentaires de mémoire (c'est-à-dire 2 + 2 = 4 Mo au total)? ou le newBitmap fera-t-il uniquement référence à oldBitmap (et donc aucun 2 Mo supplémentaire n'est requis)? ......... Je veux éviter à tout prix l'erreur outOfMemory!
Shishir Gupta
4
@ShishirGupta Non testé mais par des documents Android:If the source bitmap is immutable and the requested subset is the same as the source bitmap itself, then the source bitmap is returned and no new bitmap is created.
Arvis
1
@Arvis Hey arvis J'ai essayé votre suggestion et cela fonctionne pour l'orientation, mais maintenant j'obtiens une image centrée sur le portrait beaucoup plus petite. Des idées ?
Doug Ray
44

Extension courte pour Kotlin

fun Bitmap.rotate(degrees: Float): Bitmap {
    val matrix = Matrix().apply { postRotate(degrees) }
    return Bitmap.createBitmap(this, 0, 0, width, height, matrix, true)
}

Et l'utilisation:

val rotatedBitmap = bitmap.rotate(90F) // value must be float
Pavel Shorokhov
la source
13

Vous trouverez ci-dessous le code pour faire pivoter ou redimensionner votre image dans Android

public class bitmaptest extends Activity {
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        LinearLayout linLayout = new LinearLayout(this);

        // load the origial BitMap (500 x 500 px)
        Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),
               R.drawable.android);

        int width = bitmapOrg.width();
        int height = bitmapOrg.height();
        int newWidth = 200;
        int newHeight = 200;

        // calculate the scale - in this case = 0.4f
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;

        // createa matrix for the manipulation
        Matrix matrix = new Matrix();
        // resize the bit map
        matrix.postScale(scaleWidth, scaleHeight);
        // rotate the Bitmap
        matrix.postRotate(45);

        // recreate the new Bitmap
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
                          width, height, matrix, true);

        // make a Drawable from Bitmap to allow to set the BitMap
        // to the ImageView, ImageButton or what ever
        BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);

        ImageView imageView = new ImageView(this);

        // set the Drawable on the ImageView
        imageView.setImageDrawable(bmd);

        // center the Image
        imageView.setScaleType(ScaleType.CENTER);

        // add ImageView to the Layout
        linLayout.addView(imageView,
                new LinearLayout.LayoutParams(
                      LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT
                )
        );

        // set LinearLayout as ContentView
        setContentView(linLayout);
    }
}

Vous pouvez également consulter ce lien pour plus de détails: http://www.anddev.org/resize_and_rotate_image_-_example-t621.html

Arslan Anwar
la source
6

Par défaut, le point de rotation est le point (0,0) du canevas, et je suppose que vous voudrez peut-être le faire pivoter autour du centre. Je l'ai fait:

protected void renderImage(Canvas canvas)
{
    Rect dest,drawRect ;

    drawRect = new Rect(0,0, mImage.getWidth(), mImage.getHeight());
    dest = new Rect((int) (canvas.getWidth() / 2 - mImage.getWidth() * mImageResize / 2), // left
                    (int) (canvas.getHeight()/ 2 - mImage.getHeight()* mImageResize / 2), // top
                    (int) (canvas.getWidth() / 2 + mImage.getWidth() * mImageResize / 2), //right
                    (int) (canvas.getWidth() / 2 + mImage.getHeight()* mImageResize / 2));// bottom

    if(!mRotate) {
        canvas.drawBitmap(mImage, drawRect, dest, null);
    } else {
        canvas.save(Canvas.MATRIX_SAVE_FLAG); //Saving the canvas and later restoring it so only this image will be rotated.
        canvas.rotate(90,canvas.getWidth() / 2, canvas.getHeight()/ 2);
        canvas.drawBitmap(mImage, drawRect, dest, null);
        canvas.restore();
    }
}
Aggée
la source
4

Je simplifierait comm1x de fonction d'extension Kotlin encore plus:

fun Bitmap.rotate(degrees: Float) =
    Bitmap.createBitmap(this, 0, 0, width, height, Matrix().apply { postRotate(degrees) }, true)
Gnzlt
la source
4

En utilisant la createBitmap()méthode Java , vous pouvez passer les degrés.

Bitmap bInput /*your input bitmap*/, bOutput;
float degrees = 45; //rotation degree
Matrix matrix = new Matrix();
matrix.setRotate(degrees);
bOutput = Bitmap.createBitmap(bInput, 0, 0, bInput.getWidth(), bInput.getHeight(), matrix, true);
Googlian
la source
1

Si vous faites pivoter le bitmap, 90180270360 est correct, mais pour les autres degrés, le canevas dessinera un bitmap de taille différente.

Donc, le meilleur moyen est

canvas.rotate(degree,rotateCenterPoint.x,rotateCenterPoint.y);  
canvas.drawBitmap(...);
canvas.rotate(-degree,rotateCenterPoint.x,rotateCenterPoint.y);//rotate back
王怡飞
la source
0

Si votre objectif est d'avoir une image pivotée dans une imageView ou un fichier, vous pouvez utiliser Exif pour y parvenir. La bibliothèque de support propose désormais cela: https://android-developers.googleblog.com/2016/12/introducing-the-exifinterface-support-library.html

Vous trouverez ci-dessous son utilisation, mais pour atteindre votre objectif, vous devez consulter la documentation de l'API de la bibliothèque pour cela. Je voulais juste donner un indice que la rotation du bitmap n'est pas toujours la meilleure façon.

Uri uri; // the URI you've received from the other app
InputStream in;
try {
  in = getContentResolver().openInputStream(uri);
  ExifInterface exifInterface = new ExifInterface(in);
  // Now you can extract any Exif tag you want
  // Assuming the image is a JPEG or supported raw format
} catch (IOException e) {
  // Handle any errors
} finally {
  if (in != null) {
    try {
      in.close();
    } catch (IOException ignored) {}
  }
}

int rotation = 0;
int orientation = exifInterface.getAttributeInt(
    ExifInterface.TAG_ORIENTATION,
    ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
  case ExifInterface.ORIENTATION_ROTATE_90:
    rotation = 90;
    break;
  case ExifInterface.ORIENTATION_ROTATE_180:
    rotation = 180;
    break;
  case ExifInterface.ORIENTATION_ROTATE_270:
    rotation = 270;
    break;
}

dépendance

compilez "com.android.support:exifinterface:25.1.0"

Ultimo_m
la source
0

Faites juste attention au type Bitmap de l'appel de la plate-forme Java comme à partir des réponses de comm1x et de Gnzlt , car il peut renvoyer null. Je pense qu'il est également plus flexible si le paramètre peut être n'importe quel nombre et utiliser un infixe pour la lisibilité, cela dépend de votre style de codage.

infix fun Bitmap.rotate(degrees: Number): Bitmap? {
    return Bitmap.createBitmap(
        this,
        0,
        0,
        width,
        height,
        Matrix().apply { postRotate(degrees.toFloat()) },
        true
    )
}

Comment utiliser?

bitmap rotate 90
// or
bitmap.rotate(90)
HendraWD
la source