pie - android versiones
Android: gira la imagen sin cargarla en la memoria. (5)
Me pregunto si es posible girar una imagen almacenada en una tarjeta SD sin cargarla en la memoria.
La razón es por qué estoy buscando que es famoso OutOfMemoryError. Sé que puedo evitarlo reduciendo el tamaño de una imagen grande, pero en realidad no quiero reducir el tamaño de esa imagen, quiero tener una imagen original, pero girada 90 grados.
Cualquier sugerencia sobre esto es apreciada calurosamente :)
He hecho una solución muy lenta pero amigable con la memoria here .
Estoy seguro de que hay mejores formas y me encantaría saber de ellas.
Le sugeriré que use una biblioteca de terceros que no almacena datos en el montón de proceso mientras opera en mapas de bits. En mi caso usé ffmpeg que ya estaba usando para otro propósito en mi proyecto.
Si tienes que manejar diferentes formatos, entonces será un dolor. Tendrá que ser capaz de entender los diferentes formatos y de leer / escribir / transformarlos, probablemente a través de secuencias. En una PC normal, diría que mire ImageMagick que tiene un soporte de imagen muy grande. Busqué un puerto de Android y se me ocurrió this . Podría valer la pena intentarlo. Sin embargo, parece inacabado, por lo que probablemente tendrías que trabajar para obtener una mejor cobertura de formato.
Debes decodificar decodificar las imágenes usando Bitmap
. debe seguir Cargando imagen grande presentada por google sobre cómo hacerlo ... me ayudó mucho, notará la gran diferencia en el uso de RAM ...
ACTUALIZAR: si todo lo que desea es simplemente girar la imagen, puede usar este código
Matrix matrix = new Matrix();
matrix.setRotate(90);
result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),bitmap.getHeight(), matrix, false);
si solo necesita configurar la orientación de la imagen (por ejemplo, la orientación de la foto cuando se tomó) puede usar
ExifInterface exif = new ExifInterface(filePath);
con el atributo ExifInterface.TAG_ORIENTATION
Espero que esto te ayude
Para las rotaciones de 90 grados, realmente RenderScript que está diseñado exactamente para tratar con mapas de bits y es inesperadamente incluso más rápido que el Bitmap.createBitmap()
predeterminado. El mapa de bits en proceso no se almacena en el montón de Java, por lo tanto, no lo OutOfMemoryError
en OutOfMemoryError
.
Después de configurar el soporte de RenderScript en su proyecto con pocas líneas, aquí está el algoritmo de RenderScript para usar:
1) Cree el archivo RenderScript de la app/src/main/rs/rotator.rs
con el siguiente contenido.
#pragma version(1)
#pragma rs java_package_name(ua.kulku.rs)
rs_allocation inImage;
int inWidth;
int inHeight;
uchar4 __attribute__ ((kernel)) rotate_90_clockwise (uchar4 in, uint32_t x, uint32_t y) {
uint32_t inX = inWidth - 1 - y;
uint32_t inY = x;
const uchar4 *out = rsGetElementAt(inImage, inX, inY);
return *out;
}
uchar4 __attribute__ ((kernel)) rotate_270_clockwise (uchar4 in, uint32_t x, uint32_t y) {
uint32_t inX = y;
uint32_t inY = inHeight - 1 - x;
const uchar4 *out = rsGetElementAt(inImage, inX, inY);
return *out;
}
Preste atención a ua.kulku.rs
, ese es el nombre del paquete que elija para la interfaz RS Java de generación automática.
2) Haz referencia en tu código Java:
import ua.kulku.rs.ScriptC_rotator;
public Bitmap rotate(Bitmap bitmap) {
RenderScript rs = RenderScript.create(mContext);
ScriptC_rotator script = new ScriptC_rotator(rs);
script.set_inWidth(bitmap.getWidth());
script.set_inHeight(bitmap.getHeight());
Allocation sourceAllocation = Allocation.createFromBitmap(rs, bitmap,
Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
bitmap.recycle();
script.set_inImage(sourceAllocation);
int targetHeight = bitmap.getWidth();
int targetWidth = bitmap.getHeight();
Bitmap.Config config = bitmap.getConfig();
Bitmap target = Bitmap.createBitmap(targetWidth, targetHeight, config);
final Allocation targetAllocation = Allocation.createFromBitmap(rs, target,
Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
script.forEach_rotate_90_clockwise(targetAllocation, targetAllocation);
targetAllocation.copyTo(target);
rs.destroy();
return target;
}
Para rotaciones de 180 grados, la solución NDK superó a RenderScript, al igual que para mí, debido al uso del acceso secuencial al elemento de la matriz, ya que la rotación de 180 grados es en realidad la reversión de la matriz de píxeles de la imagen. El algoritmo NDK que he usado en estas comparaciones es de https://github.com/AndroidDeveloperLB/AndroidJniBitmapOperations . El mapa de bits en proceso tampoco se almacena en el montón de Java, lo que impide que OutOfMemoryError
.
Las barras de estadísticas indican lo que obtuve en milisegundos en mi Samsung S4 (Android 5.0) para la foto de 13 MP.