GLImage.java 3.58 KB
Newer Older
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
1 2 3 4 5 6 7
package com.projectseptember.RNGL;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.net.Uri;
import android.support.annotation.Nullable;
Gaëtan Renaudeau's avatar
wip  
Gaëtan Renaudeau committed
8
import android.util.Log;
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
9

10
import com.facebook.common.references.CloseableReference;
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
11
import com.facebook.common.util.UriUtil;
12 13 14 15 16 17
import com.facebook.datasource.DataSource;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
18

19
import java.util.concurrent.Executor;
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
20 21 22 23 24

/*
This class is maintained and inspired from
https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java
 */
25 26
public class GLImage {

Gaëtan Renaudeau's avatar
wip  
Gaëtan Renaudeau committed
27
    private Uri src;
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
28
    private GLTexture texture;
29 30 31 32 33 34 35 36 37
    private Runnable onLoad;
    private Executor glExecutor;
    private Executor decodeExecutor;
    private DataSource<CloseableReference<CloseableImage>> pending;

    public GLImage (Executor glExecutor, Executor decodeExecutor, Runnable onLoad) {
        this.onLoad = onLoad;
        this.glExecutor = glExecutor;
        this.decodeExecutor = decodeExecutor;
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
38
        this.texture = new GLTexture(glExecutor);
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
39 40
    }

41 42
    public void setSrc (Uri src) {
        if (this.src == src || this.src!=null && this.src.equals(src)) return;
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
43 44 45 46 47
        this.src = src;
        reloadImage();
    }

    private void reloadImage () {
48 49 50 51 52 53
        if (pending != null && !pending.isFinished())
            pending.close();

        final Uri uri = src;
        ImageRequest imageRequest = ImageRequestBuilder
                .newBuilderWithSource(uri)
54
                .setAutoRotateEnabled(false) // I don't really understand why need to disable this. but it actually fixes the image is properly rotated according to EXIF data
55 56 57 58 59 60 61 62 63 64 65 66 67 68
                .build();

        pending = Fresco.getImagePipeline().fetchDecodedImage(imageRequest, null);

        pending.subscribe(new BaseBitmapDataSubscriber() {
            @Override
            protected void onNewResultImpl(@Nullable Bitmap bitmap) {
                onLoad(bitmap);
            }
            @Override
            protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
                Log.e("GLImage", "Failed to load '" + uri.getPath() + "'", dataSource.getFailureCause());
            }
        }, decodeExecutor);
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
69 70
    }

71 72 73 74
    public void onLoad (final Bitmap source) {
        Matrix matrix = new Matrix();
        matrix.postScale(1, -1);
        final Bitmap bitmap = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
75
        bitmap.setHasAlpha(true);
76
        glExecutor.execute(new Runnable() {
Gaëtan Renaudeau's avatar
wip  
Gaëtan Renaudeau committed
77 78
            public void run() {
                texture.setPixels(bitmap);
79 80
                bitmap.recycle();
                onLoad.run();
Gaëtan Renaudeau's avatar
wip  
Gaëtan Renaudeau committed
81 82
            }
        });
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
83 84 85 86 87 88
    }

    public GLTexture getTexture() {
        return texture;
    }

89
    public static @Nullable Uri getResourceDrawableUri (Context context, @Nullable String name) {
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103
        if (name == null || name.isEmpty()) {
            return null;
        }
        name = name.toLowerCase().replace("-", "_");
        int resId = context.getResources().getIdentifier(
                name,
                "drawable",
                context.getPackageName());
        return new Uri.Builder()
                .scheme(UriUtil.LOCAL_RESOURCE_SCHEME)
                .path(String.valueOf(resId))
                .build();
    }
}