Spanish Capturar la imagen de la cámara y exponerla en un objeto sin guardarla en el dispositivo

Sergio Haurat

Active Member
Licensed User
Longtime User
La idea es poder tomar una foto y dejarla en un objeto Panel o ImageView sin necesidad de grabarlo en el dispositivo y luego utilizar LoadBitmap
 

Heppy

Active Member
Licensed User
Longtime User

bgsoft

Well-Known Member
Licensed User
Longtime User
Hola Sergio

Te he creado un pequeño ejemplo de lo que quieres.

He echo dos cosas por si mas adelante quieres ampliar la aplicación:
1) Guardar la captura a archivo
2) En el sub de ConfigurarCamara puedes ver las caracteristicas del movil y asi hacer mas cosas

Emplea la libreria ACL para crear la aplicacion

B4X:
Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.

  
    Dim camara As AdvancedCamera
    Dim PanelCamara As Panel
    Dim Button1 As Button ' captura
    dim Button2 As Button  ' marcha/paro camara
    
     Dim CamaraOK As Boolean
     Dim CamaraVisible As Boolean

     ' ampliaciones futuras
     Dim FlagSoportaZoom As Boolean
     Dim FlagSoportaLed As Boolean
     Dim FlagSoportaAutoFoco As Boolean

' .................
' .................
' .................
' .................


Sub Activity_Create(FirstTime As Boolean)
   'Do not forget to load the layout file created with the visual designer. For example:
   Activity.LoadLayout("Layout1")
  
   Button1.Enabled = False
' .................
' .................
' .................
' .................


Sub Activity_Resume

  Try
    camara.Initialize(PanelCamara, "camara")
  Catch
    CamaraOK = False
    Msgbox("Error al iniciar cámara" & CRLF & "Inténtelo de nuevo","")
  End Try
 
End Sub


Sub Activity_Pause (UserClosed As Boolean)

   If UserClosed = True Then
    If CamaraOK = True AND CamaraVisible = True Then
       camara.StopPreview
       camara.Release
     End If  
     DoEvents
     Activity.Finish
   End If
    
   If CamaraOK = True AND CamaraVisible = True Then
     camara.StopPreview
     camara.Release
   End If  

End Sub

Sub Button1_Click
   Button1.Enabled = False
   camara.TakePicture
  
End Sub

Sub Button2_Click
    ' MARCHA/PARO CAMARA
  
  If CamaraOK = True Then
    If CamaraVisible = True Then
       ' parar camara
        camara.StopPreview
        CamaraVisible = False
     Else
        ' marcha camara
        PanelCamara.top=0
        Try  
           camara.StartPreview
           CamaraVisible = True
       Catch
          Log("Error en Camara.StartPreview")
       End Try

     End If  
   End If  
    
End Sub


Sub camara_Ready (Success As Boolean)
    
   If Success Then
       CamaraOK = True
       ConfigurarCamara
       Button1.Enabled = True
    Else
      CamaraOK = False
      Msgbox("No se puede poner la cámara en marcha" & CRLF & "Inténtelo de nuevo", "")
  End If
    
End Sub

Sub camara_PictureTaken(Data() As Byte)
  Button1.Enabled = True
    
  camara.StartPreview

  ' ---------------------------------------------------------------------------
  ' para grabar a memoria
  Dim salida As OutputStream
  salida = File.OpenOutput(File.DirRootExternal,"foto.jpg",False)
  salida.WriteBytes(Data,0,Data.Length)
  salida.Close
  ToastMessageShow("Imagen guardada en: " & File.Combine(File.DirRootExternal,"foto.jpg"), True)
  
End Sub



Sub ConfigurarCamara
  Dim tmp As String
  

   FlagSoportaZoom = camara.isZoomSupported
   If FlagSoportaZoom = False OR camara.MaxZoom = 0 Then
     Msgbox("La cámara no soporta zoom","")
   End If  
  
   tmp = camara.SupportedFlashMode
   ' [off, auto, on, torch]
   Log("flash" & tmp)
   If tmp.Contains("torch") Then FlagSoportaLed = True
   If FlagSoportaLed = False Then
     Msgbox("La cámara no tiene led","")
   End If
  
  
   tmp = camara.SupportedFocusMode
   If tmp.Contains("auto") Then FlagSoportaAutoFoco = True
   Log("Tipo foco " & tmp)
   '[auto, infinity, macro, continuous-picture, continuous-video]
  
  
   If FlagSoportaAutoFoco = False Then
    Msgbox("La cámara no soporta auto-foco","")
   Else
    'Log("foco" & tmp)
    'Camara.FocusMode = ModoFoco
   End If
  
  
   If Activity.Height > Activity.Width Then
     ' movil vertical
     camara.OriPortrait
   Else
     camara.OriLandscape
   End If
  
  DoEvents
  
   If CamaraOK = True AND CamaraVisible = True Then
     DoEvents
    Try
      camara.StartPreview
     Catch
       Log("Error StartPreview en configurar camara")
     End Try  
   End If  
   
  
End Sub


La parte de dimensionar y de posicionar los objetos te la dejo a ti ;)

Espero haberte ayudado

Saludos
 

Sergio Haurat

Active Member
Licensed User
Longtime User
Jesús, Gracias por responder. Veo que con esto la tenés bastante clara. Yo vengo, y creo que todos adoptamos este software por eso, del VB6 y el .NET. Entiendo que en el ejemplo hay varias cosas que permiten la manipulación de la cámara, lo cual es realmente bueno para aplicarlo en otros proyectos. También veo que hay un sub camara_PictureTaken que toma el array de bytes y lo guarda en la SD usando OutputStream. Posiblemente mi pregunta no fue muy clara pero yo quiero evitar grabarla en el disco, es decir, tengo el array de bytes y quiero pasarlo a Bitmap para poder pasarlo a otro objeto y que todo ocurra en la memoria en tiempo de ejecución.

Investigando un poco más logré este código
B4X:
Public Sub SavePictureToBitmap(Data() As Byte) As Bitmap
  Dim insData As InputStream
  insData.InitializeFromBytesArray(Data, 0, Data.Length)
  Dim bmp As Bitmap
  bmp.Initialize2(insData)
  insData.Close
  Dim bmp_draw As BitmapDrawable
  bmp_draw.Initialize(bmp)
  Return bmp_draw.Bitmap
End Sub

Lo probé y funcionó sólo una vez. Algo estoy haciendo mal.

Saludos
 
Last edited:

bgsoft

Well-Known Member
Licensed User
Longtime User
Hola Sergio

Es dificil saber que haces mal sin ver el resto del codigo.
Ese codigo que has puesto lo veo bien, y es una forma para luego poder asignar el bitmap a otro objeto.
Si no ves donde puede estar el error en tu codigo, grabalo a un fichero temporal:
' para grabar a memoria
Dim salida AsOutputStream
salida = File.OpenOutput(File.DirRootExternal,"foto.jpg",False)
salida.WriteBytes(Data,0,Data.Length)
salida.Close

Y luego cargalo desde los ojetos que te interesen. Y cuando ya no lo emplees lo borras.
Si al cargarlo en algun objeto te da problemas de memoria, cargalo con:

B4X:
LoadBitmapSample(Dir,NombreFile,100%x,100%y) ' dale el valor que creas conveniente al %

Saludos
 

Sergio Haurat

Active Member
Licensed User
Longtime User
Jesús, Gracias por responder.

El sub que dejo se puede implementar en cualquier proyecto, lo que necesito hacer es ahorrarme 2 pasos.

1) Guardar data() en un jpg en el dispositivo
2) Leer el jpg desde el dispositivo con LoadBitmap o LoadBitmapSample

Quiero directamente leer el array de bytes devuelto cuando se saca la fotografía cargarlo en el .Bitmap o .Background del elemento que sea. Lo que estoy diciendo en otras plataformas de desarrollo es perfectamente aplicable, en .NET lo tengo implementado por ejemplo con tomar un jpg desde la web y mostrarlo directamente como fondo de un formulario sin necesidad de guardar primero los datos en el disco y luego tener que leerlos.

Espero ser lo suficientemente claro, gracias por tu tiempo
 

bgsoft

Well-Known Member
Licensed User
Longtime User
Hola Sergio, ya lo entendí, lo que te dije es que si te da problemas puedes emplear el sistema que te expuse de guardarlo a jpg y luego cargarlo.
Te comenté que ese codigo (Public Sub SavePictureToBitmap(Data() AsByte) AsBitmap) es correcto, pero sin ver el resto de codigo es dificil saber donde te falla.
Puedes emplear esto directamente en el sub que captura, pero no deja de ser mas de lo mismo de tu sub.

B4X:
Sub camara_PictureTaken(Data() As Byte)
        Dim In As InputStream
        In.InitializeFromBytesArray(Data, 0, Data.Length)
        Dim bmp As Bitmap
        bmp.Initialize2(In)
' ..............
'..............

Saludos
 

JordiCP

Expert
Licensed User
Longtime User
Hola Sergio,

Otra manera de hacerlo, pero quizás te sirva.

Mira este ejemplo. Está basado en la clase cameraEx e Erel, añadiendo una pequeña librería que hice. Te convierte el preview en un bitmap sin grabar ni nada. Este bitmap es mutable y en el ejemplo lo va actualizando en cada evento de preview. Puedes modificar el código para sólo convertirlo (el mismo o diferentes previamente inicializados) una sola vez cuando sea necesario.
 

Sergio Haurat

Active Member
Licensed User
Longtime User
JordiCP, gracias por el dato. Ahora lo pruebo bien. Te cuento que el Sub que yo hice funciona por ejemplo en una Samsung P3113 (tablet de 7) y en un Sony Ericsson Xperia, el problema está en el S4 que no "refresca" por algún motivo. Voy a probar con tu librería si funciona en todos las opciones que tengo a la mano en este momento.

Gracias por responder
 
Top