11
votes

Conversion du cadre d'aperçu au bitmap

Je sais que le sujet était au bord de la planche plusieurs fois, mais je ne peux pas faire fonctionner de toute façon ... Je souhaite enregistrer des images d'affichage de l'aperçu des fichiers JPEG. Il semble plus ou moins (le code est simplifié - sans logique supplémentaire, exception, etc.) comme celui-ci ...

public int[] decodeYUV420SP( byte[] yuv420sp, int width, int height) {   

    final int frameSize = width * height;   

    int rgb[]=new int[width*height];   
    for (int j = 0, yp = 0; j < height; j++) {   
        int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;   
        for (int i = 0; i < width; i++, yp++) {   
            int y = (0xff & ((int) yuv420sp[yp])) - 16;   
            if (y < 0) y = 0;   
            if ((i & 1) == 0) {   
                v = (0xff & yuv420sp[uvp++]) - 128;   
                u = (0xff & yuv420sp[uvp++]) - 128;   
            }   

            int y1192 = 1192 * y;   
            int r = (y1192 + 1634 * v);   
            int g = (y1192 - 833 * v - 400 * u);   
            int b = (y1192 + 2066 * u);   

            if (r < 0) r = 0; else if (r > 262143) r = 262143;   
            if (g < 0) g = 0; else if (g > 262143) g = 262143;   
            if (b < 0) b = 0; else if (b > 262143) b = 262143;   

            rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) &    
    0xff00) | ((b >> 10) & 0xff);   


        }   
    }   
    return rgb;   
    } 


1 commentaires

Au cas où il aide, il y a une discussion à ce sujet à stackoverflow.com/questions/12345415/... et Stackoverflow.com/questions/9325861/...


5 Réponses :


0
votes

Comme je l'ai découvert la largeur et la hauteur, la lecture de la prévisualisation était fausse .... En d'autres termes, la conversion s'est mal passée car elle était basée sur de fausses valeurs. Après avoir utilisé une nouvelle façon de définir les paramètres de prévisualisation (de l'exemple de Deleivered par Google) tout fonctionne bien.

EDIT:

Désolé pour la réponse rapide ci-dessus et le délai de longue date.

C'était il y a quelque temps et je ne peux pas creuser le code maintenant, mais je pense que j'ai utilisé:

http://developer.android. Com / Référence / Android / Matériel / Caméra.Parameters.html # GetsUpportedPrevisseSise ()

et a pris le premier élément de la liste et définissez les valeurs avec

http: // développeur .Android.com / Référence / Android / Hardware / Camera.Parameters.html # SetPreviewSize (int, int)

J'ai enregistré la largeur et la hauteur et l'ai utilisé pour transformer l'image.

Cela ne sais pas si c'était la meilleure solution, mais cela a fonctionné.


1 commentaires

C'est informatif. Lorsque vous vous souciez de la valeur qui n'est pas pris en charge, il semble de produire des ordures.



1
votes

Si je ne me trompe pas, vous voulez que la largeur et la hauteur de la photo décodent, pas la largeur et l'heigth de l'aperçu.


0 commentaires

12
votes

Simplement économiser sur une JPEG est une tâche plus facile que de convertir en bitmap, pas besoin de ce code de décodage YUV grâce à yuvimage code> classe.

import android.graphics.YuvImage; 

@Override 
public void onPreviewFrame(byte[] data, Camera camera) { 
    try { 
        Camera.Parameters parameters = camera.getParameters(); 
        Size size = parameters.getPreviewSize(); 
        YuvImage image = new YuvImage(data, parameters.getPreviewFormat(), 
                size.width, size.height, null); 
        File file = new File(Environment.getExternalStorageDirectory(), "out.jpg"); 
        FileOutputStream filecon = new FileOutputStream(file); 
        image.compressToJpeg( 
                new Rect(0, 0, image.getWidth(), image.getHeight()), 90, 
                filecon); 
    } catch (FileNotFoundException e) { 
        Toast toast = Toast 
                .makeText(getBaseContext(), e.getMessage(), 1000); 
        toast.show(); 
    } 
} 


0 commentaires

1
votes

Afin d'éviter une image JPEG dégradée sur la sortie (par exemple avec des taches vertes entrelacées / rouges), vous devez Flush STRAND> et FERME STRUT> FileOutPutStream forte >

FileOutputStream filecon = new FileOutputStream(file); 
image.compressToJpeg( 
            new Rect(0, 0, image.getWidth(), image.getHeight()), 90, 
        filecon);
filecon.flush();
filecon.close();


0 commentaires

19
votes

Alternativement, si vous do em> avez besoin d'un bitmap pour une raison quelconque et / ou souhaitez le faire sans créer de Yuvimage et de compresser à JPEG, vous pouvez utiliser le "scriptIntrinsicyuvtorgb" HandyRinstickInvtorGB "(API 17 +):

@Override 
public void onPreviewFrame(byte[] data, Camera camera) { 
   Bitmap bitmap = Bitmap.createBitmap(r.width(), r.height(), Bitmap.Config.ARGB_8888);
    Allocation bmData = renderScriptNV21ToRGBA8888(
        mContext, r.width(), r.height(), data);
    bmData.copyTo(bitmap);
}

public Allocation renderScriptNV21ToRGBA8888(Context context, int width, int height, byte[] nv21) {
  RenderScript rs = RenderScript.create(context);
  ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));

  Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)).setX(nv21.length);
  Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);

  Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
  Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);

  in.copyFrom(nv21);

  yuvToRgbIntrinsic.setInput(in);
  yuvToRgbIntrinsic.forEach(out);
  return out;
}


3 commentaires

Quel est l'argument "R" dans l'appel à CreateBitMap?


Je suppose que "R" est la largeur / hauteur que vous pouvez obtenir en appelant caméra.getparameters (). Obtenez la taille d'aperçu (). Largeur etc.


J'ai cherché cette réponse pendant un moment. C'est la meilleure réponse, devrait être accepté.