cómo rotar un mapa de bits 90 grados

123

Hay una declaración en Android canvas.drawBitmap(visiblePage, 0, 0, paint);

Cuando agrego canvas.rotate(90), no hay efecto. Pero si escribo

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

No obtengo ningún mapa de bits dibujado. Entonces, ¿qué no estoy haciendo bien?

murli
fuente
He respondido esto aquí: stackoverflow.com/questions/8608734/…
EyalBellisha

Respuestas:

254

También puedes probar este

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);

Luego puede usar la imagen rotada para configurar su vista de imagen

imageView.setImageBitmap(rotatedBitmap);
ario
fuente
1
Creo que para el mapa de bits escalado que desea (bitmapOrg, ancho, alto, verdadero)
Jameo
2
¿Qué matriz importa? android.graphics o android.opengl?
Poutrathor
6
Importar android.graphics
kirtan403
4
esto usa mucha memoria. Para mapas de bits grandes, puede crear problemas debido a las múltiples copias de mapas de bits en la memoria.
Moritz Both
1
En caso de que no necesite el mapa de bits original, llame bitmap.recycle()para estar seguro.
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);
}

Para obtener mapa de bits de los recursos:

Bitmap source = BitmapFactory.decodeResource(this.getResources(), R.drawable.your_img);
Arvis
fuente
1
Soy nuevo con Android. Solo me pregunto si hago Bitmap newBitmap = RotateBitmap (oldBitmap, 90), ¿mi 'mapa de bits decodificado' tiene dos bloques de memoria (para el antiguo y el nuevo) o se refieren a la misma memoria, pero uno no tiene rotación, el otro tiene rotación ? .... Mi preocupación es, si decodifico R.drawable.picture en oldBitmap, si se supone que ocupa 2 MB de memoria (¿Heap, supongo?), NewBitmap tomará 2 MB adicionales de memoria (es decir, 2 + 2 = 4 MB en total)? ¿O el newBitmap solo se referirá a oldBitmap (y por lo tanto no se requieren 2 MB adicionales)? ......... ¡Quiero evitar el error outOfMemory a toda costa!
Shishir Gupta
4
@ShishirGupta No probado pero con documentos de 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 Hola arvis Probé tu sugerencia y funciona para la orientación, sin embargo, ahora obtengo una imagen centrada en un retrato mucho más pequeña. Algunas ideas ?
Doug Ray
44

Extensión corta para Kotlin

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

Y uso:

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

A continuación se muestra el código para rotar o cambiar el tamaño de su imagen en 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);
    }
}

También puede consultar este enlace para obtener más detalles: http://www.anddev.org/resize_and_rotate_image_-_example-t621.html

Arslan Anwar
fuente
6

Por defecto, el punto de rotación es el punto (0,0) del lienzo, y supongo que es posible que desee rotarlo alrededor del centro. Yo lo hice:

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();
    }
}
Hageo
fuente
4

Me simplificar comm1x 's función de extensión Kotlin aún más:

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

Usando el createBitmap()método Java puedes pasar los grados.

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
fuente
1

Si gira el mapa de bits, 90 180 270 360 está bien, pero para otros grados, el lienzo dibujará un mapa de bits con un tamaño diferente.

Entonces, la mejor manera es

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

En caso de que su objetivo sea tener una imagen rotada en un imageView o archivo, puede usar Exif para lograrlo. La biblioteca de soporte ahora ofrece eso: https://android-developers.googleblog.com/2016/12/introducing-the-exifinterface-support-library.html

A continuación se muestra su uso, pero para lograr su objetivo, debe verificar la documentación de la API de la biblioteca para eso. Solo quería dar una pista de que rotar el mapa de bits no siempre es la mejor manera.

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

dependencia

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

Ultimo_m
fuente
0

Solo tenga cuidado con el tipo de mapa de bits de la llamada a la plataforma Java, como las respuestas de comm1x y Gnzlt , porque podría devolver un valor nulo. Creo que también es más flexible si el parámetro puede ser cualquier Número y usar infijo para legibilidad, depende de su estilo de codificación.

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

¿Cómo utilizar?

bitmap rotate 90
// or
bitmap.rotate(90)
HendraWD
fuente