2010-08-23 21 views
31

Tengo un SurfaceView que se utiliza para dibujar imágenes, y me gustaría superponerlas a una transmisión en vivo desde la cámara del teléfono.Superposición de imágenes en la vista previa de la cámara SurfaceView

Actualmente, el SurfaceView que contiene las imágenes tiene un fondo blanco, pero si tuviera que superponerlas en la alimentación de la cámara del teléfono, tendrían que ser transparentes. La cámara y el dibujo de animación no se pueden hacer en el mismo SurfaceView.

¿Cuál es el mejor curso para utilizar varias vistas que implican administrar la cámara y dibujar imágenes? ¿Es posible hacer un SurfaceView transparente?

Respuesta

1

podría this code ayuda? `

+0

Mi clase DrawonTop también extiende SurfaceView e implementa la interfaz SurfaceHolder.Callback. ¿Crees que eso me causará problemas si intento superponerlo en la Vista previa de la cámara? Leí que SurfaceViews no puede ser transparente, pero me pregunto si eso es solo un montón de basura. – GobiasKoffi

+0

Además de esto, ¿no se debe llamar a la clase DrawOnTop en algún tipo de UIthread? No se está haciendo en el ejemplo que sugirió. – GobiasKoffi

+0

El enlace ya no funciona. –

6

que estoy haciendo aplicación aumentada también y golpear el mismo problema se golpea. Hay muy poca información sobre cómo resolverlo correctamente. Pero encontré un framework llamado mixare - le permite crear la aplicación AR para Android. Definitivamente debe mirarlo source - se ve bastante prometedor. Espero que esto te ayudará.

5

He tenido éxito con el siguiente enfoque.

En primer lugar hacer un archivo XML de diseño que se ve algo como esto (tenga en cuenta el orden de los dos puntos de vista):

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" android:layout_height="fill_parent" 
    android:orientation="vertical"> 

    <com.yourcustom.OverlayView 
     android:id="@+id/overlay" android:layout_width="fill_parent" 
     android:layout_height="fill_parent"> 
    </com.yourcustom.OverlayView> 

    <SurfaceView android:id="@+id/surface" 
     android:layout_width="fill_parent" android:layout_height="fill_parent"> 
    </SurfaceView> 

</FrameLayout> 

OverlayView es una subclase de SurfaceView con las implementaciones de hilos de dibujo y animación. El otro SurfaceView será la superficie que maneja la vista previa de la cámara. Dentro de onCreate se deben establecer sus puntos de vista como esto:

mView = (OverlayView)this.findViewById(R.id.overlay); 
    mView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 

    mSurfaceView = (SurfaceView)this.findViewById(R.id.surface); 
    mSurfaceHolder = mSurfaceView.getHolder(); 
    mSurfaceHolder.addCallback(this); 
    mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

Usted debe agregar una aplicación a la SurfaceHolder.CallbackSurfaceHolder de mView que maneja el hilo animación. Un ejemplo de aplicación de la presente dentro de la subclase y el uso de la animación/dibujo hilos se puede encontrar en el viejo ejemplo LunarLander aquí: http://developer.android.com/resources/samples/LunarLander/src/com/example/android/lunarlander/LunarView.html

Además de configurar la cámara SurfaceView la misma manera que este ejemplo: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.html

+0

se le olvida cerrar

+4

Esto es incorrecto porque com.yourcustom.OverlayView necesita ser el segundo en el Framelayout para estar en la parte superior ... – Lumis

20

Bueno, así es como lo hice ... Espero que alguien lo encuentre útil aunque las cosas de Qualcomm AR estén fuera ... podría ser obselete ... oh y básicamente lo que hace es generar dos cubos funky a partir de ese Ejemplo de Android, la funcionalidad adicional introducida son los eventos táctiles, aunque los vectores rotacionales están apagados por mucho, solo para un propósito de demostración de todos modos y por supuesto los cubos superpuestos en la parte superior de la previa de la cámara que se puede mover en una pantalla ..


    public class TakeRecieptPicture extends Activity implements Callback { 
    private Camera camera; 
    private SurfaceView mSurfaceView; 
    SurfaceHolder mSurfaceHolder; 

    private TouchSurfaceView mGLSurfaceView; 

    ShutterCallback shutter = new ShutterCallback(){ 

     @Override 
     public void onShutter() { 
      // TODO Auto-generated method stub 
      // No action to be perfomed on the Shutter callback. 

     } 

     }; 
    PictureCallback raw = new PictureCallback(){ 
     @Override 
     public void onPictureTaken(byte[] data, Camera camera) { 
      // TODO Auto-generated method stub 
      // No action taken on the raw data. Only action taken on jpeg data. 
     } 

     }; 

    PictureCallback jpeg = new PictureCallback(){ 

     @Override 
     public void onPictureTaken(byte[] data, Camera camera) { 
      // TODO Auto-generated method stub 

      FileOutputStream outStream = null; 
      try{ 
       outStream = new FileOutputStream("/sdcard/test.jpg"); 
       outStream.write(data); 
       outStream.close(); 
      }catch(FileNotFoundException e){ 
       Log.d("Camera", e.getMessage()); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       Log.d("Camera", e.getMessage()); 
      } 

     } 

     }; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     this.requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
    WindowManager.LayoutParams.FLAG_FULLSCREEN); 


     mGLSurfaceView = new TouchSurfaceView(this); 
    addContentView(mGLSurfaceView, new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT)); 

     mSurfaceView = new SurfaceView(this); 
     addContentView(mSurfaceView, new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT)); 
     mSurfaceHolder = mSurfaceView.getHolder(); 
     mSurfaceHolder.addCallback(this); 
     mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
     mSurfaceHolder.setFormat(PixelFormat.TRANSLUCENT|LayoutParams.FLAG_BLUR_BEHIND); 
     } 

    private void takePicture() { 
     // TODO Auto-generated method stub 
     camera.takePicture(shutter, raw, jpeg); 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { 
     // TODO Auto-generated method stub 
     Camera.Parameters p = camera.getParameters(); 
     p.setPreviewSize(arg2, arg3); 
     try { 
     camera.setPreviewDisplay(arg0); 
     } catch (IOException e) { 
     e.printStackTrace(); 
     } 
     camera.startPreview(); 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 
     // TODO Auto-generated method stub 
    camera = Camera.open(); 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 
     // TODO Auto-generated method stub 
     camera.stopPreview(); 
     camera.release(); 
    } 
    } 

El TouchSurfaceView se define a continuación:


    class TouchSurfaceView extends GLSurfaceView { 

    public TouchSurfaceView(Context context) {  
     super(context); 
     cr = new CubeRenderer(true); 
     this.setEGLConfigChooser(8, 8, 8, 8, 16, 0); 
     this.setRenderer(cr); 
     this.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 
     this.getHolder().setFormat(PixelFormat.TRANSPARENT); 

     } 

    public boolean onTrackballEvent(MotionEvent e) {  
     cr.mAngleX += e.getX() * TRACKBALL_SCALE_FACTOR;  
     cr.mAngleY += e.getY() * TRACKBALL_SCALE_FACTOR;  
     requestRender(); 
     return true; } 

    @Override 
    public boolean onTouchEvent(MotionEvent e) {  
     float x = e.getX();  
     float y = e.getY();  
     switch (e.getAction()) {  
     case MotionEvent.ACTION_MOVE:  
      float dx = x - mPreviousX;   
      float dy = y - mPreviousY;   
      cr.mAngleX += dx * TOUCH_SCALE_FACTOR; 
      cr.mAngleY += dy * TOUCH_SCALE_FACTOR;  
      requestRender();  
      }  
     mPreviousX = x; 
     mPreviousY = y;  
     return true; 

    } 
    private final float TOUCH_SCALE_FACTOR = 180.0f/320; 
    private final float TRACKBALL_SCALE_FACTOR = 36.0f; 
    public CubeRenderer cr ; 
    private float mPreviousX; 
    private float mPreviousY; 


} 

Y el CubeRenderer viene dada por:


    class CubeRenderer implements GLSurfaceView.Renderer { 
    public CubeRenderer(boolean useTranslucentBackground) { 
     mTranslucentBackground = useTranslucentBackground; 
     mCube = new Cube(); 
     } 


    public void onDrawFrame(GL10 gl) { 
     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 
     gl.glMatrixMode(GL10.GL_MODELVIEW);  
     gl.glLoadIdentity();  
     gl.glTranslatef(0, 0, -5.0f); 
     gl.glRotatef(mAngle,  0, 1, 0); 
     gl.glRotatef(mAngle*0.25f, 1, 0, 0);  
     gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
     gl.glEnableClientState(GL10.GL_COLOR_ARRAY);  
     mCube.draw(gl);  
     gl.glRotatef(mAngle*2.0f, 0, 1, 1);  
     gl.glTranslatef(0.5f, 0.5f, 0.5f);  
     mCube.draw(gl);  
     mAngle += 1.2f; 
     } 
    public void onSurfaceChanged(GL10 gl, int width, int height) {  
     gl.glViewport(0, 0, width, height);  
     float ratio = (float) width/height;  
     gl.glMatrixMode(GL10.GL_PROJECTION);  
     gl.glLoadIdentity();  
     gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); 
     } 

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {  

     gl.glDisable(GL10.GL_DITHER);  
     gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); 
     if (mTranslucentBackground) {   
      gl.glClearColor(0,0,0,0);  
      } else {   
       gl.glClearColor(1,1,1,1);  
       }  
     gl.glEnable(GL10.GL_CULL_FACE);  
     gl.glShadeModel(GL10.GL_SMOOTH);  
     gl.glEnable(GL10.GL_DEPTH_TEST); 
     } 

    public void setAngle(float _angle){ 

    } 
    private boolean mTranslucentBackground; 
    private Cube mCube; 
    private float mAngle; 
     public float mAngleX; 
     public float mAngleY; 

} 

Y finalmente el Cubo está dado por:


    class Cube{ 
    public Cube() 
    {  int one = 0x10000;  
    int vertices[] = { 
      -one, -one, -one, 
      one, -one, -one,  
      one, one, -one,  
      -one, one, -one,   
      -one, -one, one,   
      one, -one, one,   
      one, one, one,   
      -one, one, one,  }; 

    float[] colors = {  
      0f, 0f, 0f, 0.5f, 
      1f , 0f, 0f, 0.1f,  
      1f,1f,0f,0.5f, 
      0f, 1f, 0f, 0.1f,  
      0f, 0f, 1f, 0.1f,  
      1f, 0f, 1f, 0.2f,  
      1f, 1f, 1f, 0.1f,   
      0f, 1f, 1f, 0.1f,  };  

    byte indices[] = {   
      0, 4, 5, 0, 5, 1,  
      1, 5, 6, 1, 6, 2,  
      2, 6, 7, 2, 7, 3,  
      3, 7, 4, 3, 4, 0,  
      4, 7, 6, 4, 6, 5,  
      3, 0, 1, 3, 1, 2  }; 


    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4); 
    vbb.order(ByteOrder.nativeOrder());  
    mVertexBuffer = vbb.asIntBuffer();  
    mVertexBuffer.put(vertices);  
    mVertexBuffer.position(0);  
    ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4); 
    cbb.order(ByteOrder.nativeOrder());  
    mColorBuffer = cbb.asFloatBuffer();  
    mColorBuffer.put(colors);  
    mColorBuffer.position(0);  
    mIndexBuffer = ByteBuffer.allocateDirect(indices.length);  
    mIndexBuffer.put(indices);  
    mIndexBuffer.position(0); } 
    public void draw(GL10 gl) {  
     gl.glFrontFace(gl.GL_CW);  
     gl.glVertexPointer(3, gl.GL_FIXED, 0, mVertexBuffer); 
     gl.glColorPointer(4, gl.GL_FIXED, 0, mColorBuffer);  
     gl.glDrawElements(gl.GL_TRIANGLES, 36, gl.GL_UNSIGNED_BYTE, mIndexBuffer); } 

    private IntBuffer mVertexBuffer; 
    private FloatBuffer mColorBuffer; 
    private ByteBuffer mIndexBuffer; 

    } 

Bueno, espero que alguien lo encuentre útil ...

+1

+1 respuesta de trabajo completa. – Behnam

+0

¿cómo cambio el ángulo de la cámara? se ha girado a -90 grados ahora. muchas gracias – onexf

0

Acabo de encontrar una réplica levemente extraña de la actualización de mi teléfono a la 4.0.4. Tengo una superposición translúcida de pantalla completa en una vista previa de la cámara de pantalla completa, que funcionó bastante bien en una versión anterior de ics (creo que era 4.0.3, pero no es cierto). Después de actualizar a 4.0.4, la vista previa se volvió un poco desconcertante, con la imagen de la cámara mostrando áreas de color primarias psicodélicas en cualquiera de las partes más brillantes de la imagen de la cámara (las partes más oscuras parecían estar bien). Finalmente se encontró que el cambio de glclearcolour a 0,0,0,0 de 0.5, 0.5, 0.5. 0 lo resolvió.

Parece que, aunque el alfa era cero en las partes no utilizadas de la superposición gl, la función de fusión seguía teniendo en cuenta el fondo gris gl.

Cuestiones relacionadas