2012-01-06 18 views
6

ACTUALIZACIÓN tal vez cambiar el tamaño de mapa de bits en la nueva actividad puede solucionar el problemaAndroid reducir el tamaño de imagen de cámara

String myRef = this.getIntent().getStringExtra("filepath"); 
    File imgFile = new File(myRef); 

    Log.e("BeatEmUp", myRef); 
    if(imgFile.exists()){ 

     Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath()); 
     ImageView myImage = (ImageView) findViewById(R.id.imagepunch); 
     myImage.setImageBitmap(myBitmap); 

    } 

Algo como esto tal vez?

Bitmap scaled = Bitmap.createScaledBitmap(bit, 200, 200, true);

o tal vez esta es la mejor manera a continuación

Hasta ahora tengo mi aplicación que está tomando una foto y luego usando un Intent para llevar a la imagen una y otra pantalla en una nueva Activity . Una vez que he hecho esto, tengo un código que muestra imágenes en la parte superior con el onClick. El problema es cuando la imagen se toma, se está tomando en un tamaño máximo, creo que mi aplicación se cierra a la fuerza.

En mi logcat obtengo java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap Size=7431KB, Allocated=2956KB, Bitmap Size=19764KB), lo que creo que significa que la imagen es demasiado grande.

He probado poniendo una imagen más pequeña en el código en lugar de la imagen de la cámara que se tomó y funciona, lo que también me lleva de vuelta al problema de que tiene el tamaño de la imagen de la cámara.

Así que estoy tratando de implementar This From CommonsWare pero sin suerte hasta el momento. Si miro el código, creo que busca la menor cantidad/tamaño de información y luego tomo la cámara usando esa configuración. ¿Tengo razón al pensar eso y, de ser así, cómo puedo implementar eso en mi código?

public class AndroidCamera extends Activity implements SurfaceHolder.Callback{ 

Camera camera; 
SurfaceView surfaceView; 
SurfaceHolder surfaceHolder; 
boolean previewing = false; 
LayoutInflater controlInflater = null; 

final int RESULT_SAVEIMAGE = 0; 

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 



    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 

    getWindow().setFormat(PixelFormat.UNKNOWN); 
    surfaceView = (SurfaceView)findViewById(R.id.camerapreview); 
    surfaceHolder = surfaceView.getHolder(); 
    surfaceHolder.addCallback(this); 
    surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

    controlInflater = LayoutInflater.from(getBaseContext()); 
    View viewControl = controlInflater.inflate(R.layout.control, null); 
    LayoutParams layoutParamsControl 
     = new LayoutParams(LayoutParams.FILL_PARENT, 
     LayoutParams.FILL_PARENT); 
    this.addContentView(viewControl, layoutParamsControl); 

    Button buttonTakePicture = (Button)findViewById(R.id.takepicture); 
    buttonTakePicture.setOnClickListener(new Button.OnClickListener(){ 

     public void onClick(View arg0) { 
      // TODO Auto-generated method stub 
      camera.takePicture(myShutterCallback, 
        myPictureCallback_RAW, myPictureCallback_JPG); 



     }}); 

} 

ShutterCallback myShutterCallback = new ShutterCallback(){ 

    public void onShutter() { 
     // TODO Auto-generated method stub 

    }}; 

PictureCallback myPictureCallback_RAW = new PictureCallback(){ 

    public void onPictureTaken(byte[] arg0, Camera arg1) { 
     // TODO Auto-generated method stub 

    }}; 

PictureCallback myPictureCallback_JPG = new PictureCallback(){ 

    public void onPictureTaken(byte[] arg0, Camera arg1) { 
     // TODO Auto-generated method stub 
     /*Bitmap bitmapPicture 
      = BitmapFactory.decodeByteArray(arg0, 0, arg0.length); */ 
     int imageNum = 0; 
     Intent imageIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
     File imagesFolder = new File(Environment.getExternalStorageDirectory(), "Punch"); 
     imagesFolder.mkdirs(); // <---- 
     String fileName = "image_" + String.valueOf(imageNum) + ".jpg"; 
     File output = new File(imagesFolder, fileName); 
     while (output.exists()){ 
      imageNum++; 
      fileName = "image_" + String.valueOf(imageNum) + ".jpg"; 
      output = new File(imagesFolder, fileName); 
     } 

     Uri uriSavedImage = Uri.fromFile(output); 
     imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage); 


     OutputStream imageFileOS; 
     try { 
      imageFileOS = getContentResolver().openOutputStream(uriSavedImage); 
      imageFileOS.write(arg0); 
      imageFileOS.flush(); 
      imageFileOS.close(); 

      Toast.makeText(AndroidCamera.this, 
        "Image saved", 
        Toast.LENGTH_LONG).show(); 

     } catch (FileNotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     Intent intent = new Intent(getBaseContext(), Punch.class); 
     intent.putExtra("filepath",Uri.parse(output.getAbsolutePath()).toString()); 
     //just using a request code of zero 
     int request=0; 
     startActivityForResult(intent,request); 
    }}; 

public void surfaceChanged(SurfaceHolder holder, int format, int width, 
     int height) { 
    // TODO Auto-generated method stub 
    if(previewing){ 
     camera.stopPreview(); 
     previewing = false; 
    } 

    if (camera != null){ 
     try { 
      camera.setPreviewDisplay(surfaceHolder); 
      camera.startPreview(); 
      previewing = true; 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      camera.release(); 
      e.printStackTrace(); 
     } 
    } 
} 





public void surfaceCreated(SurfaceHolder holder) { 
    // TODO Auto-generated method stub 

    camera = Camera.open(); 
    try { 
      Camera.Parameters parameters = camera.getParameters(); 

      if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) { 
       // This is an undocumented although widely known feature 
       parameters.set("orientation", "portrait"); 
       // For Android 2.2 and above 
       camera.setDisplayOrientation(90); 
       // Uncomment for Android 2.0 and above 
       parameters.setRotation(90); 
      } else { 
       // This is an undocumented although widely known feature 
       parameters.set("orientation", "landscape"); 
       // For Android 2.2 and above 
       camera.setDisplayOrientation(0); 
       // Uncomment for Android 2.0 and above 
       parameters.setRotation(0); 
      } 


      camera.setParameters(parameters); 
      camera.setPreviewDisplay(holder); 
     } catch (IOException exception) { 
     camera.release(); 


     } 
     camera.startPreview(); 

    } 


public void surfaceDestroyed(SurfaceHolder holder) { 
    // TODO Auto-generated method stub 
    if(previewing && camera != null) { 
     if(camera!=null) { 
      camera.stopPreview(); 
      camera.release(); 
      camera = null; 
     } 
     previewing = false; 
    } 
} 


} 
+0

esto es lo que intentamos hacer --- Tomar una foto, pasar la imagen a una nueva actividad con solo hacer clic en ella? Si estoy en lo correcto, ¿necesitas una imagen de tamaño medio para hacer clic? –

+0

@Mohit Sharma: No te entiendo del todo, pero sí, algo así – Matt

Respuesta

13

So far I have my app which is taking a picture and then using an Intent to carry the picture over and display in a new Activity.

En la mayoría de los casos, pasar datos entre las actividades que utilizan Intent extras es una buena solución. Los grandes mapas de bits, sin embargo, causan problemas de esa manera debido al consumo de memoria. Este es un caso en el que cuidadosamente utiliza un miembro de datos estáticos.

In my logcat I am getting java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap Size=7431KB, Allocated=2956KB, Bitmap Size=19764KB) which I think means that the image is too large.

Significa que no tiene suficiente memoria para lo que está tratando de hacer.

Looking through the code I think it searches for the smallest resouloution/size and then takes the camera using those settings am I right in thinking that

Sí.

if so how can I implement that into my code?

Copiar y pegar generalmente funciona. :-)

Para decirle a la cámara qué tamaño de imagen tomar, use setPictureSize() en Camera.Parameters. Sin embargo, debe elegir un tamaño que admita, y no todos los dispositivos admitirán tamaños arbitrarios. Llamar al getSupportedPictureSizes() le dirá qué tamaños son compatibles. Depende de usted determinar cuál de esos tamaños usar. En the example I linked de su otra pregunta, repito sobre esos tamaños y encuentro el más pequeño en términos de área.

Dicho esto, si el problema solo con el tamaño de la imagen lo está pasando de una actividad a otra, iría primero a la ruta del miembro de datos estáticos. Solo asegúrese de null ese miembro de datos estáticos cuando ya no necesite la imagen.

Something like this maybe?

Una vez más, eso depende de lo que sea su objetivo. Parece que está buscando soluciones, cuando solo ha articulado un problema (e incluso allí, no nos ha dicho donde está obteniendo el error de falta de memoria).

Si su objetivo es tomar una imagen de resolución completa, guardarla en un archivo y luego mantener en la memoria una miniatura, createScaledBitmap() es una buena solución.

Si su objetivo es tomar una imagen en miniatura en primer lugar (es decir, no necesita o desea una imagen de resolución completa), use setPictureSize().

Si su objetivo es utilizar una imagen de resolución completa, use cuidadosamente un miembro de datos estáticos para eliminar cualquier copia innecesaria del Bitmap y vea si eso es suficiente. Puede que no lo sea, dependiendo de lo que intentes hacer con la imagen.

+0

Respuesta impresionante, entiendo lo que quieres decir. Mi objetivo es, básicamente, una vez que la imagen de la cámara ha sido tomada y llevada a la siguiente actividad que tiene 'onClick' que superpone una imagen diferente sobre la imagen de la cámara en cada' onClick'. Es entonces cuando se cierra la fuerza 'error de memoria 'cuando intento' onCLick' – Matt

+0

¿El código de su enlace configura automáticamente la cámara para que tome el tamaño más bajo dependiendo del teléfono o el usuario tiene que elegir todavía? – Matt

+0

@Matt: El usuario no tiene opción en mi muestra. Si desea que el usuario elija el tamaño, debe usar 'getSupportedPictureSizes()' para rellenar un 'Spinner' o' AlertDialog' o algo así. – CommonsWare

2

Pruebe esta imagen de captura de la cámara.

Intent cameraActivity=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
      cameraActivity.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(left)); 
      startActivityForResult(cameraActivity,CAMERA_PIC_REQUEST_LEFTIMAGE); 

Esto le devolverá la imagen a tamaño grande, ahora para su reducción u puede usar algo como esto

BitmapFactory.Options options=new BitmapFactory.Options(); 
         options.inSampleSize = 6; 
         FileInputStream fileInputStream;  
         try { 
           fileInputStream=new FileInputStream(left); 
           leftPhoto=BitmapFactory.decodeStream(fileInputStream,null,options); 
           leftImage.setImageBitmap(leftPhoto); 
           fileInputStream.close(); 
          } catch (FileNotFoundException e) { 
           Toast.makeText(getCurrentContext(), e.getMessage(),Toast.LENGTH_LONG).show(); 
           e.printStackTrace(); 
          } catch (IOException e) { 
           e.printStackTrace(); 
           Toast.makeText(getCurrentContext(), e.getMessage(),Toast.LENGTH_LONG).show(); 
          } 

Ahora u puede añadir al hacer clic sobre este.

Cuestiones relacionadas