Fresco: Utilice Fresco con SubsamplingImageView

Creado en 27 mar. 2015  ·  20Comentarios  ·  Fuente: facebook/fresco

Estoy trabajando en una aplicación que requiere manejar una imagen grande. Actualmente estamos cortando la imagen en varios trozos pequeños. (Pero como puede pensar, el OOM siempre nos está molestando). Me gustaría saber si fresco es capaz de manejar eso bien o no. Gracias.

enhancement

Comentario más útil

Acabo de crear un visor de imágenes grande que admite panorámica y zoom, con muy poco uso de memoria y opciones de carga de imágenes con todas las funciones. Desarrollado por Subsampling Scale Image View, Fresco, Glide y Picasso https://github.com/Piasy/BigImageViewer, espero que ayude :)

Todos 20 comentarios

Si la imagen es JPEG, puede intentar cambiar su

Gracias por su respuesta. No podemos simplemente cambiar el tamaño para solucionar el problema porque la imagen puede ser tan grande como 700px x 10000px. También necesitamos admitir el zoom. El cambio de tamaño probablemente no sea bueno para nuestro caso de uso.

Alex621, si no has oído hablar de SubsamplingScaleImageView, te recomiendo buscarlo en GitHub. Utiliza un algoritmo de segmentación de imágenes en mosaico como el que se usa en la Galería de archivo de Android. El algoritmo se ve mejor en Google Maps, pero obviamente es más complejo para Maps. Esa biblioteca admite rotaciones, escalado y traducción. Fue diseñado específicamente para manejar errores OOM y se ha probado hasta imágenes de 20.000 por 20.000 píxeles.

Editar: no soy el propietario de la biblioteca ni un colaborador de esta biblioteca. Estoy en mi telefono. Con suerte, podría hacer un Drawee para este caso de uso: GalleryDrawee

@jparkie Gracias. Es lo que quiero :). Entonces, la siguiente pregunta es, ¿pueden fresco y SSIV vivir juntos en paz?

@ alex621 , eso creo. No lo he probado; Todavía no he tenido tiempo de sumergirme en el código. Publicaré mi progreso cuando pueda. Sin embargo, puede que no sea la mejor combinación. SubsamplingScaleImageView funciona mejor con un ImageSource que hace referencia a un archivo, por lo que realmente no obtiene ningún beneficio de Fresco.

Tendría que ver cómo funciona SubsamplingScaleImageView. Si el archivo de imagen es muy grande, es posible que no sea posible cargar la imagen completa en la memoria, incluso en formato codificado. Eso significa que se debe realizar un submuestreo o recorte durante la decodificación del archivo.
No estoy seguro de cuál es la API que usa SubsamplingScaleImageView, pero tal vez sea posible obtener el archivo en nuestro caché de disco y dejar que SubsamplingScaleImageView luego lo lea directamente.

Utiliza un algoritmo de segmentación de pirámide de imágenes para decodificar regiones (http://developer.android.com/reference/android/graphics/BitmapRegionDecoder.html y tal vez un decodificador C ++ personalizado) del archivo de imagen a través de un hilo de fondo. Esencialmente, el ejemplo famoso es Google Maps; no carga todo el mundo como un mapa, submuestra representaciones que a medida que escala en la pirámide, cargarán resoluciones más altas solo para la ventana gráfica. No he tenido tiempo de profundizar en ambas bibliotecas, pero esta técnica se utiliza en la aplicación nativa de la Galería para cargar las fotos de resolución extremadamente alta de las cámaras modernas en los teléfonos inteligentes.

Gracias @jparkie . BitmapRegionDecoder es API10, lo cual es bueno ya que se admite GB MR1 +. Definitivamente deberíamos hacer uso de esto.

El único problema con BitmapRegionDecoder es con PNG en una versión de Android, creo. No recuerdo cuál. Está perfectamente bien con archivos JPEG. De todos modos, es por eso que hice referencia a tal vez un decodificador C ++ personalizado.

Hola a todos, soy el desarrollador de SSIV . Debido a que BitmapRegionDecoder (basado en Skia) tiene problemas con algunas imágenes, extraje la decodificación de imágenes en clases separadas para que se pueda usar un decodificador personalizado y escribí una clase de ejemplo usando RapidDecoder. Esto se basa en libpng y jpgd. Libpng parece generalmente mejor que Skia, pero jpgd no puede decodificar una región de un JPG sin decodificar la imagen completa, lo que la hace inútil para mi biblioteca. Estoy ansioso por encontrar una mejor opción, y libjpeg-turbo podría ser adecuado.

Estoy interesado en ver si SSIV y Fresco podrían usarse juntos para proporcionar un soporte más confiable para imágenes grandes con pellizcar para hacer zoom, pero por el momento no estoy seguro de cómo se podría hacer. Las dos bibliotecas son muy diferentes. SSIV actualmente requiere que los archivos estén en el sistema de archivos, o en recursos o activos, porque necesita acceso aleatorio al archivo para decodificar mosaicos de él.

Podría ser posible escribir un decodificador personalizado para SSIV que use una biblioteca nativa para leer mosaicos de la memoria caché codificada; esto funcionaría bastante bien al navegar por fotos de alta resolución de Internet.

No tengo mucho tiempo para investigar esto en este momento, pero estaré atento a este hilo y responderé cualquier pregunta que pueda.

¡Hola @davemorrissey ! Estoy pensando en agregar un soporte para obtener un identificador de archivo para nuestros recursos en caché de disco para que el archivo se pueda leer directamente en lugar de pasar por nuestra canalización. Eso ayudaría a integrar SSIV con el backend de Fresco.
Usamos libjpeg-turbo, pero no estoy seguro de si es compatible con la decodificación de regiones. Estoy seguro de que el formato JPEG es adecuado para eso, ya que la imagen está dividida en bloques de 8x8 píxeles, pero no estoy seguro de si la biblioteca hace uso de eso. Sin embargo, valdría la pena comprobarlo.

Consulte también nuestro código de muestra para pellizcar para hacer zoom con Fresco: https://github.com/facebook/fresco/tree/master/samples/zoomable/src/main/java/com/facebook/samples/zoomable

Bump: si se logró algún progreso en esto.

Para su información, finalmente decidimos cortar la imagen grande en el servidor porque hay demasiados problemas con la biblioteca de imágenes de Android.

Sin embargo, esa no es una opción para mí (usando imágenes locales de Android), lo cual también quiero procesar, así que realmente me encantaría este soporte, espero que suceda

Acabo de crear un visor de imágenes grande que admite panorámica y zoom, con muy poco uso de memoria y opciones de carga de imágenes con todas las funciones. Desarrollado por Subsampling Scale Image View, Fresco, Glide y Picasso https://github.com/Piasy/BigImageViewer, espero que ayude :)

Supongo que debería ser posible agregar un decodificador Fresco personalizado que admita algo como esto:
Obtiene el EncodedImage , crea un nuevo tipo CloseableImage que contiene los datos requeridos y luego usa un DrawableFactory que crea un nuevo tipo Drawable que usa esos datos . Esto podría combinarse con nuestro código de muestra para zoooming con una nueva vista que puede actualizar estos elementos de diseño especiales para decodificar la región correcta.

Pero, ¿cuándo decodifica la región de soporte Fresco? Puedo cargar el EncodedImage en un decodificador de imagen SubsamplingImageView personalizado con, pero sin decodificación de región, es inútil.

El código fuente es algo como esto, ¿algún consejo?

public class FrescoBigImageViewRegionDecoder implements ImageRegionDecoder {
    private static final String TAG = "FrescoBigImageViewRegionDecoder";

    private EncodedImage mEncodedImage;
    private CloseableImage mCloseableImage;
    private CountDownLatch mCountDownLatch;

    public FrescoBigImageViewRegionDecoder() {
        Log.d(TAG, "FrescoBigImageViewRegionDecoder: ");
    }

    <strong i="8">@Override</strong>
    public Point init(Context context, Uri uri) throws Exception {
        mCountDownLatch = new CountDownLatch(1);
        ImageRequest request = ImageRequest.fromUri(uri);
        Fresco.getImagePipelineFactory().getImagePipeline().fetchEncodedImage(request, context).subscribe(new BaseDataSubscriber<CloseableReference<PooledByteBuffer>>() {
            <strong i="9">@Override</strong>
            protected void onNewResultImpl(DataSource<CloseableReference<PooledByteBuffer>> dataSource) {
                mEncodedImage = new EncodedImage(dataSource.getResult());
                mEncodedImage.parseMetaData();
                mCountDownLatch.countDown();
            }

            <strong i="10">@Override</strong>
            protected void onFailureImpl(DataSource<CloseableReference<PooledByteBuffer>> dataSource) {
                Log.d(TAG, "onFailureImpl: failed to decode");
                mEncodedImage = new EncodedImage(dataSource.getResult());
                mEncodedImage.parseMetaData();
                mCountDownLatch.countDown();
            }
        }, CallerThreadExecutor.getInstance());
        mCountDownLatch.await();
        return new Point(mEncodedImage.getWidth(), mEncodedImage.getHeight());
    }

    <strong i="11">@Override</strong>
    public Bitmap decodeRegion(Rect rect, int i) {
        PlatformDecoder decoder = Fresco.getImagePipelineFactory().getPlatformDecoder();
        return decoder.decodeJPEGFromEncodedImage(mEncodedImage, Bitmap.Config.ARGB_8888, mEncodedImage.getSize()).get();
    }

    <strong i="12">@Override</strong>
    public boolean isReady() {
        return mEncodedImage != null && mEncodedImage.isValid();
    }

    <strong i="13">@Override</strong>
    public void recycle() {
        if (mEncodedImage != null) {
            mEncodedImage.close();
        }
    }
}

Comencé a trabajar en el soporte de decodificación de regiones que ahora se puede usar desde un decodificador personalizado. Agregaré una muestra rápida para que esto se pueda habilitar antes de que el soporte completo esté disponible en Fresco.

Un ejemplo realmente básico para esto ahora está disponible en la aplicación Showcase, consulte baa629dd46797a3342a50b918ea0989b63819c87

Tenga en cuenta que esto solo funciona para archivos JPEG en este momento y que aún necesita algo de trabajo si se cambia el tamaño de la imagen / se reduce la resolución, ya que el BitmapFactory.Options#inSampleSize no se maneja correctamente.

¿Fue útil esta página
0 / 5 - 0 calificaciones