190 votes

Rapide Bitmap flou pour Android SDK

Actuellement, dans une application Android, je développe une boucle à travers les pixels d'une image pour la rendre floue. Cela prend environ 30 secondes sur une image 640x480.

Lors de la navigation dans les applications de l’Android Market, j’en ai rencontré une qui comporte une fonction de flou et leur flou est très rapide (environ 5 secondes), elles doivent donc utiliser une méthode de flou différente.

Quelqu'un connaît-il un moyen plus rapide que de parcourir les pixels?

314voto

Yahel Points 5018

Pour les futurs googleurs, voici un algorithme que j'ai porté de Quasimondo. Son genre de mélange entre une boîte floue et un flou gaussien, c'est très joli et assez rapide aussi:

 public Bitmap fastblur(Bitmap sentBitmap, int radius) {

        // Stack Blur v1.0 from
        // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
        //
        // Java Author: Mario Klingemann <mario at quasimondo.com>
        // http://incubator.quasimondo.com
        // created Feburary 29, 2004
        // Android port : Yahel Bouaziz <yahel at kayenko.com>
        // http://www.kayenko.com
        // ported april 5th, 2012

        // This is a compromise between Gaussian Blur and Box blur
        // It creates much better looking blurs than Box Blur, but is
        // 7x faster than my Gaussian Blur implementation.
        //
        // I called it Stack Blur because this describes best how this
        // filter works internally: it creates a kind of moving stack
        // of colors whilst scanning through the image. Thereby it
        // just has to add one new block of color to the right side
        // of the stack and remove the leftmost color. The remaining
        // colors on the topmost layer of the stack are either added on
        // or reduced by one, depending on if they are on the right or
        // on the left side of the stack.
        //
        // If you are using this algorithm in your code please add
        // the following line:
        //
        // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>

        Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);

        if (radius < 1) {
            return (null);
        }

        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        int[] pix = new int[w * h];
        Log.e("pix", w + " " + h + " " + pix.length);
        bitmap.getPixels(pix, 0, w, 0, 0, w, h);

        int wm = w - 1;
        int hm = h - 1;
        int wh = w * h;
        int div = radius + radius + 1;

        int r[] = new int[wh];
        int g[] = new int[wh];
        int b[] = new int[wh];
        int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
        int vmin[] = new int[Math.max(w, h)];

        int divsum = (div + 1) >> 1;
        divsum *= divsum;
        int dv[] = new int[256 * divsum];
        for (i = 0; i < 256 * divsum; i++) {
            dv[i] = (i / divsum);
        }

        yw = yi = 0;

        int[][] stack = new int[div][3];
        int stackpointer;
        int stackstart;
        int[] sir;
        int rbs;
        int r1 = radius + 1;
        int routsum, goutsum, boutsum;
        int rinsum, ginsum, binsum;

        for (y = 0; y < h; y++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            for (i = -radius; i <= radius; i++) {
                p = pix[yi + Math.min(wm, Math.max(i, 0))];
                sir = stack[i + radius];
                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);
                rbs = r1 - Math.abs(i);
                rsum += sir[0] * rbs;
                gsum += sir[1] * rbs;
                bsum += sir[2] * rbs;
                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];
                } else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];
                }
            }
            stackpointer = radius;

            for (x = 0; x < w; x++) {

                r[yi] = dv[rsum];
                g[yi] = dv[gsum];
                b[yi] = dv[bsum];

                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;

                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];

                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];

                if (y == 0) {
                    vmin[x] = Math.min(x + radius + 1, wm);
                }
                p = pix[yw + vmin[x]];

                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);

                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];

                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;

                stackpointer = (stackpointer + 1) % div;
                sir = stack[(stackpointer) % div];

                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];

                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];

                yi++;
            }
            yw += w;
        }
        for (x = 0; x < w; x++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            yp = -radius * w;
            for (i = -radius; i <= radius; i++) {
                yi = Math.max(0, yp) + x;

                sir = stack[i + radius];

                sir[0] = r[yi];
                sir[1] = g[yi];
                sir[2] = b[yi];

                rbs = r1 - Math.abs(i);

                rsum += r[yi] * rbs;
                gsum += g[yi] * rbs;
                bsum += b[yi] * rbs;

                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];
                } else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];
                }

                if (i < hm) {
                    yp += w;
                }
            }
            yi = x;
            stackpointer = radius;
            for (y = 0; y < h; y++) {
                // Preserve alpha channel: ( 0xff000000 & pix[yi] )
                pix[yi] = ( 0xff000000 & pix[yi] ) | ( dv[rsum] << 16 ) | ( dv[gsum] << 8 ) | dv[bsum];

                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;

                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];

                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];

                if (x == 0) {
                    vmin[y] = Math.min(y + r1, hm) * w;
                }
                p = x + vmin[y];

                sir[0] = r[p];
                sir[1] = g[p];
                sir[2] = b[p];

                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];

                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;

                stackpointer = (stackpointer + 1) % div;
                sir = stack[stackpointer];

                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];

                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];

                yi += w;
            }
        }

        Log.e("pix", w + " " + h + " " + pix.length);
        bitmap.setPixels(pix, 0, w, 0, 0, w, h);

        return (bitmap);
    }
 

268voto

for3st Points 2727

Android Flou Guide 2014

avec Vitrine et de Référence en Application et de Source sur Github

Après avoir expérimenté beaucoup de choses, je peux maintenant safley vous donner quelques recommandations qui feront de votre vie eaiser dans Android lors de l'utilisation de l'Android Cadre.

Charger et Utiliser revus à la baisse Bitmap (pour la très les images floues)

N'utilisez jamais de la taille réelle d'une image Bitmap. Le plus gros de l'image le plus besoin d'être floue et aussi plus le rayon de flou doit être et généralement, plus le rayon de flou le plus lent de l'algorithme.

final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap blurTemplate = BitmapFactory.decodeResource(getResources(), R.drawable.myImage, options);

Cela va charger l'image bitmap avec inSampleSize 8, de sorte que seule 1/64 de l'image d'origine. Test ce inSampleSize convient à vos besoins, mais le garder 2^n (2,4,8,...) afin d'éviter de dégrader la qualité de la mise à l'échelle. Voir Google doc pour plus d'

Un autre grand avantage est que bitmap le chargement est très rapide. Au début de ma flou des tests, j'ai compris que le plus de temps au cours de l'ensemble du flou le processus de chargement de l'image. Donc, pour charger une 1920x1080 image à partir du disque de mon Nexus 5 nécessaire 500ms alors que le flou a seulement pris un autre 250 ms environ.

Utilisation Renderscript

Renderscript fournit ScriptIntrinsicBlur qui est un filtre de flou Gaussien. Il a une bonne qualité visuelle et est juste la manière la plus rapide vous des attitudes réalistes obtenir sur Android. Google prétend être "en règle générale 2-3x plus rapide qu'un multithread C mise en œuvre et souvent 10x+ rapide qu'une implémentation de Java". Renderscript est vraiment sophistiqué (à l'aide de fastes dispositif de traitement (GPU, FAI,etc.), etc.) et il y a aussi le v8 bibliothèque de prise en charge pour elle ce qui la rend compatible vers le bas pour 2.2. Voici un exemple simple qui vous permettra de départ

//define this only once if blurring multiple times
RenderScript rs = RenderScript.create(context);

(...)
//this will blur the bitmapOriginal with a radius of 8 and save it in bitmapOriginal
final Allocation input = Allocation.createFromBitmap(rs, bitmapOriginal); //use this constructor for best performance, because it uses USAGE_SHARED mode which reuses memory
final Allocation output = Allocation.createTyped(rs, input.getType());
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
script.setRadius(8f);
script.setInput(input);
script.forEach(output);
output.copyTo(bitmapOriginal);

Lors de l'utilisation de la v8 de soutien avec Gradle, qui est spécifiquement recommandé par Google ", parce qu'ils comprennent les améliorations les plus récentes", vous avez seulement besoin d'ajouter 2 lignes à votre script de construction et d'utilisation android.support.v8.renderscript avec la version actuelle des outils

android {
    ...
    defaultConfig {
        ...
        renderscriptTargetApi 19
        renderscriptSupportMode true
    }
}

Simple indice de Référence sur un Nexus 5 - comparaison de RenderScript avec différents autres java et renderscript implémentations:

The average runtime per blur on different pic sizes La moyenne d'exécution par le flou sur les différentes pic tailles

Megapixels per sec that can be blurred Mégapixels par seconde, peut être atténuée

Chaque valeur est la avg de 250 tours. RS_GAUSS_FAST est - ScriptIntrinsicBlur (qui est presque toujours le plus rapide), d'autres qui commencent avec RS_ sont pour la plupart de convolution implémentations avec de simples noyaux. Les détails des algorithmes peuvent être trouvés ici. Ce n'est pas purement flou, mais une bonne partie est la collecte des ordures qui est mesurée. Ceci peut être vu dans ce ici (ScriptIntrinsicBlur sur 100x100 image avec environ 500 tours)

enter image description here

Les pointes sont gc.

Vous pouvez vérifier vous-même, l'indice de référence de l'app est dans le playstore: BlurBenchmark

Réutilise Bitmap dans la mesure du possible (si prio: performance > empreinte mémoire)

Si vous avez besoin de plusieurs flous pour un live de flou ou similaire, et la mémoire lui permet de ne pas charger l'image à partir d'un drawable plusieurs fois, mais le garder "en cache" dans une variable de membre. Dans ce cas, essayez de toujours utiliser les mêmes variables, pour garder la collecte des ordures à un minimum.

Découvrez également la nouvelle "inBitmap" option lors du chargement d'un fichier ou d'un drawable qui permettra de réutiliser l'image bitmap en mémoire et enregistre la collecte des ordures temps.

Pour le mélange de sharp pour le flou

La simple et naiive méthode est d'utiliser 2 imageviews, un flou et fondu alpha. Mais si vous voulez un plus sopisticated look qui atténue progressivement à partir de sharp pour le flou, puis vérifier Roman Nurik post sur la façon de le faire comme dans son Muzei app.

Fondamentalement, il explique qu'il a pré-flou des images avec différents flou s'étend et les utilise comme des images clés dans une animation qui ressemble vraiment lisse

Diagram where Nurik exaplains his approach

81voto

Luke Points 394

Ceci est une prise de vue dans le noir, mais vous pouvez essayer de réduire l'image puis de l'agrandir à nouveau. Cela peut être fait avec Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) . Assurez-vous et définissez le paramètre de filtre sur true. Il s'exécutera dans le code natif afin d'être plus rapide.

54voto

zeh Points 2192

EDIT (avril 2014): C'est une question/réponse page qui obtient beaucoup de succès, il me semble. Je sais que je suis toujours upvotes pour ce poste. Mais si vous êtes de lire ceci, vous devez réaliser les réponses postées ici (à la fois de la mine et de la accepté de répondre) ne sont pas à jour. Si vous voulez mettre en œuvre efficace de flou aujourd'hui, vous devez utiliser RenderScript au lieu de le NDK ou Java. RenderScript fonctionne sur Android 2.2+ (à l'aide de l' Android Support Library), donc il n'y a aucune raison de ne pas l'utiliser.

La vieille suit la réponse, mais méfiez-vous car il est obsolète.


Pour future2 Googlers, voici un algorithme que j'ai porté à partir de Yahel du port de Quasimondo de l'algorithme, mais en utilisant le NDK. Il est basé sur Yahel réponse, bien sûr. Mais c'est en cours d'exécution native code C, il est donc plus rapide. Beaucoup plus rapide. Comme, 40 fois plus rapide.

Je trouve qu'utiliser le NDK est de savoir comment tous de manipulation de l'image doit être fait sur Android... c'est un peu ennuyeux à mettre en œuvre au premier abord (lire un tutoriel sur l'utilisation de JNI et le NDK ici), mais beaucoup mieux, et en temps quasi-réel pour beaucoup de choses.

Pour référence, à l'aide de Yahel Java de fonction, il a fallu 10 secondes pour le flou de mon 480x532 pixels de l'image avec un effet de flou rayon de 10. Mais il a fallu 250ms à l'aide de la maternelle C version. Et je suis sûr qu'on peut encore être optimisé... j'ai juste fait un muet de conversion du code java, il y a probablement quelques manipulations qui peut être raccourcie ne voulais pas passer trop de temps refactoring l'ensemble de la chose.

#include <jni.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <android/log.h>
#include <android/bitmap.h>

#define LOG_TAG "libbitmaputils"
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

typedef struct {
    uint8_t red;
    uint8_t green;
    uint8_t blue;
    uint8_t alpha;
} rgba;

JNIEXPORT void JNICALL Java_com_insert_your_package_ClassName_functionToBlur(JNIEnv* env, jobject obj, jobject bitmapIn, jobject bitmapOut, jint radius) {
    LOGI("Blurring bitmap...");

    // Properties
    AndroidBitmapInfo   infoIn;
    void*               pixelsIn;
    AndroidBitmapInfo   infoOut;
    void*               pixelsOut;

    int ret;

    // Get image info
    if ((ret = AndroidBitmap_getInfo(env, bitmapIn, &infoIn)) < 0 || (ret = AndroidBitmap_getInfo(env, bitmapOut, &infoOut)) < 0) {
        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
        return;
    }

    // Check image
    if (infoIn.format != ANDROID_BITMAP_FORMAT_RGBA_8888 || infoOut.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
        LOGE("Bitmap format is not RGBA_8888!");
        LOGE("==> %d %d", infoIn.format, infoOut.format);
        return;
    }

    // Lock all images
    if ((ret = AndroidBitmap_lockPixels(env, bitmapIn, &pixelsIn)) < 0 || (ret = AndroidBitmap_lockPixels(env, bitmapOut, &pixelsOut)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    }

    int h = infoIn.height;
    int w = infoIn.width;

    LOGI("Image size is: %i %i", w, h);

    rgba* input = (rgba*) pixelsIn;
    rgba* output = (rgba*) pixelsOut;

    int wm = w - 1;
    int hm = h - 1;
    int wh = w * h;
    int whMax = max(w, h);
    int div = radius + radius + 1;

    int r[wh];
    int g[wh];
    int b[wh];
    int rsum, gsum, bsum, x, y, i, yp, yi, yw;
    rgba p;
    int vmin[whMax];

    int divsum = (div + 1) >> 1;
    divsum *= divsum;
    int dv[256 * divsum];
    for (i = 0; i < 256 * divsum; i++) {
        dv[i] = (i / divsum);
    }

    yw = yi = 0;

    int stack[div][3];
    int stackpointer;
    int stackstart;
    int rbs;
    int ir;
    int ip;
    int r1 = radius + 1;
    int routsum, goutsum, boutsum;
    int rinsum, ginsum, binsum;

    for (y = 0; y < h; y++) {
        rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
        for (i = -radius; i <= radius; i++) {
            p = input[yi + min(wm, max(i, 0))];

            ir = i + radius; // same as sir

            stack[ir][0] = p.red;
            stack[ir][1] = p.green;
            stack[ir][2] = p.blue;
            rbs = r1 - abs(i);
            rsum += stack[ir][0] * rbs;
            gsum += stack[ir][1] * rbs;
            bsum += stack[ir][2] * rbs;
            if (i > 0) {
                rinsum += stack[ir][0];
                ginsum += stack[ir][1];
                binsum += stack[ir][2];
            } else {
                routsum += stack[ir][0];
                goutsum += stack[ir][1];
                boutsum += stack[ir][2];
            }
        }
        stackpointer = radius;

        for (x = 0; x < w; x++) {

            r[yi] = dv[rsum];
            g[yi] = dv[gsum];
            b[yi] = dv[bsum];

            rsum -= routsum;
            gsum -= goutsum;
            bsum -= boutsum;

            stackstart = stackpointer - radius + div;
            ir = stackstart % div; // same as sir

            routsum -= stack[ir][0];
            goutsum -= stack[ir][1];
            boutsum -= stack[ir][2];

            if (y == 0) {
                vmin[x] = min(x + radius + 1, wm);
            }
            p = input[yw + vmin[x]];

            stack[ir][0] = p.red;
            stack[ir][1] = p.green;
            stack[ir][2] = p.blue;

            rinsum += stack[ir][0];
            ginsum += stack[ir][1];
            binsum += stack[ir][2];

            rsum += rinsum;
            gsum += ginsum;
            bsum += binsum;

            stackpointer = (stackpointer + 1) % div;
            ir = (stackpointer) % div; // same as sir

            routsum += stack[ir][0];
            goutsum += stack[ir][1];
            boutsum += stack[ir][2];

            rinsum -= stack[ir][0];
            ginsum -= stack[ir][1];
            binsum -= stack[ir][2];

            yi++;
        }
        yw += w;
    }
    for (x = 0; x < w; x++) {
        rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
        yp = -radius * w;
        for (i = -radius; i <= radius; i++) {
            yi = max(0, yp) + x;

            ir = i + radius; // same as sir

            stack[ir][0] = r[yi];
            stack[ir][1] = g[yi];
            stack[ir][2] = b[yi];

            rbs = r1 - abs(i);

            rsum += r[yi] * rbs;
            gsum += g[yi] * rbs;
            bsum += b[yi] * rbs;

            if (i > 0) {
                rinsum += stack[ir][0];
                ginsum += stack[ir][1];
                binsum += stack[ir][2];
            } else {
                routsum += stack[ir][0];
                goutsum += stack[ir][1];
                boutsum += stack[ir][2];
            }

            if (i < hm) {
                yp += w;
            }
        }
        yi = x;
        stackpointer = radius;
        for (y = 0; y < h; y++) {
            output[yi].red = dv[rsum];
            output[yi].green = dv[gsum];
            output[yi].blue = dv[bsum];

            rsum -= routsum;
            gsum -= goutsum;
            bsum -= boutsum;

            stackstart = stackpointer - radius + div;
            ir = stackstart % div; // same as sir

            routsum -= stack[ir][0];
            goutsum -= stack[ir][1];
            boutsum -= stack[ir][2];

            if (x == 0) vmin[y] = min(y + r1, hm) * w;
            ip = x + vmin[y];

            stack[ir][0] = r[ip];
            stack[ir][1] = g[ip];
            stack[ir][2] = b[ip];

            rinsum += stack[ir][0];
            ginsum += stack[ir][1];
            binsum += stack[ir][2];

            rsum += rinsum;
            gsum += ginsum;
            bsum += binsum;

            stackpointer = (stackpointer + 1) % div;
            ir = stackpointer; // same as sir

            routsum += stack[ir][0];
            goutsum += stack[ir][1];
            boutsum += stack[ir][2];

            rinsum -= stack[ir][0];
            ginsum -= stack[ir][1];
            binsum -= stack[ir][2];

            yi += w;
        }
    }

    // Unlocks everything
    AndroidBitmap_unlockPixels(env, bitmapIn);
    AndroidBitmap_unlockPixels(env, bitmapOut);

    LOGI ("Bitmap blurred.");
}

int min(int a, int b) {
    return a > b ? b : a;
}

int max(int a, int b) {
    return a > b ? a : b;
}

Ensuite l'utiliser comme ceci (en considérant une classe appelée com.insérer.votre.package.Un nom de classe et une fonction native appelée functionToBlur, comme le code ci-dessus):

// Create a copy
Bitmap bitmapOut = bitmapIn.copy(Bitmap.Config.ARGB_8888, true);
// Blur the copy
functionToBlur(bitmapIn, bitmapOut, __radius);

Il s'attend à un RGB_8888 bitmap!

Pour utiliser un RGB_565 bitmap, soit créer un converti copie avant de transmettre le paramètre (beurk), ou de modifier la fonction à utiliser un nouveau rgb565 type, au lieu d' rgba:

typedef struct {
    uint16_t byte0;
} rgb565;

Le problème est que si vous faites cela, vous ne pouvez pas lire .red, .green et .blue de pixel en plus, vous avez besoin pour lire l'octet correctement, duh. Quand j'ai besoin qu'avant, j'ai fait ça:

r = (pixels[x].byte0 & 0xF800) >> 8;
g = (pixels[x].byte0 & 0x07E0) >> 3;
b = (pixels[x].byte0 & 0x001F) << 3;

Mais il y a probablement un peu moins con moyen de le faire. Je ne suis pas beaucoup d'un faible niveau C codeur, je le crains.

13voto

B.Young Points 4486

Vous pouvez maintenant utiliser ScriptIntrinsicBlur à partir de la bibliothèque RenderScript pour flouter rapidement. Voici comment accéder à l'API RenderScript. Ce qui suit est une classe que j'ai faite pour rendre floues les vues et les bitmaps:

 public class BlurBuilder {
    private static final float BITMAP_SCALE = 0.4f;
    private static final float BLUR_RADIUS = 7.5f;

    public static Bitmap blur(View v) {
        return blur(v.getContext(), getScreenshot(v));
    }

    public static Bitmap blur(Context ctx, Bitmap image) {
        int width = Math.round(image.getWidth() * BITMAP_SCALE);
        int height = Math.round(image.getHeight() * BITMAP_SCALE);

        Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
        Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);

        RenderScript rs = RenderScript.create(ctx);
        ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
        Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
        Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
        theIntrinsic.setRadius(BLUR_RADIUS);
        theIntrinsic.setInput(tmpIn);
        theIntrinsic.forEach(tmpOut);
        tmpOut.copyTo(outputBitmap);

        return outputBitmap;
    }

    private static Bitmap getScreenshot(View v) {
        Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(b);
        v.draw(c);
        return b;
    }
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X