0

I'm trying to take a picture and add an overlay on top of it. Here is my code (only the callback) :

 private PictureCallback mPicture = new PictureCallback() {
        @Override
        public void onPictureTaken(final byte[] data, Camera camera) {


            if(!dirFile.exists()){
                dirFile.mkdirs();
            }

            try {
                String name = new SimpleDateFormat("ddMMyyyy_HHmmss").format(new Date()) + ".jpg";
                picturePath = new File(dirFile, name);

                new AsyncTask<Void, Void, Void>(){
                    FileOutputStream fos = new FileOutputStream(picturePath);
                    Bitmap photo;

                    @Override
                    protected Void doInBackground(Void... params) {
                        photo = BitmapFactory.decodeByteArray(data, 0, data.length).copy(Config.ARGB_8888, true);
                        Bitmap cadre = BitmapFactory.decodeResource(getResources(), R.drawable.cadre16001200);
                        Canvas canvas = new Canvas(photo);
                        canvas.drawBitmap(cadre, new Matrix(), null);
                        cadre.recycle();

                        photo.compress(CompressFormat.JPEG, 100, fos);
                        try {
                            fos.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                       geotag(picturePath.toString());
                        return null;
                    }

                    protected void onPostExecute(Void result) {

                        dialog.dismiss();

                        mCamera.startPreview();


                        //Affiche la nouvelle photo
                        picture.setImageBitmap(photo);
                    };

                }.execute();


            } catch (FileNotFoundException e) {
                Log.d("PhotoActivity", "File not found: " + e.getMessage());
            } 

        }
    };

I get the following error on my Samsung Galaxy S3 (android 4.1.2) , with an OutOfMemoryException

07-04 10:01:24.076: E/dalvikvm-heap(2980): Out of memory on a 7680016-byte allocation.

Weird thing is that it works perfectly on the Samsung Gio (android 2.2.1) with the same resolution of 1600x1200.

I googled a lot, and I can't use the main solution of downsizing the picture. It is a memory issue, but I don't know how I can reduce the memory usage.

EDIT : I found this, seems it was the real matter : https://stackoverflow.com/a/12377158/1343969

Community
  • 1
  • 1
Oyashiro
  • 505
  • 5
  • 18

2 Answers2

1

you should decode the bitmap before proccessing it to the UI, here's a code example

private Bitmap decodeFile(File f){
        try {
            //decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            FileInputStream stream1=new FileInputStream(f);
            BitmapFactory.decodeStream(stream1,null,o);
            stream1.close();

            //Find the correct scale value. It should be the power of 2.
            final int REQUIRED_SIZE=70;
            int width_tmp=o.outWidth, height_tmp=o.outHeight;
            int scale=1;
            while(true){
                if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                    break;
                width_tmp/=2;
                height_tmp/=2;
                scale*=2;
            }

            //decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize=scale;
            FileInputStream stream2=new FileInputStream(f);
            Bitmap bitmap=BitmapFactory.decodeStream(stream2, null, o2);
            stream2.close();
            return bitmap;
        } catch (FileNotFoundException e) {
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        return null;
}
Alamri
  • 2,112
  • 2
  • 16
  • 21
0

You should simply call the empty constructor of Canvas and draw the photo on it. This would remove the copy() call and reduce the memory usage.

photo = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap cadre = BitmapFactory.decodeResource(getResources(), R.drawable.cadre16001200);
Canvas canvas = new Canvas();
canvas.drawBitmap(photo, 0, 0, null);
canvas.drawBitmap(cadre, new Matrix(), null);
cadre.recycle();

photo.compress(CompressFormat.JPEG, 100, fos);
WarrenFaith
  • 57,492
  • 25
  • 134
  • 150
  • Looks like a good idea, but still not solving the problem. I still have OutOfMemoryException on decodeByteArray. – Oyashiro Jul 04 '13 at 08:48
  • then you just see the symptoms and not the source. What are you doing before? Can you try to free memory before taking the picture? – WarrenFaith Jul 04 '13 at 08:50
  • I only have one button calling the takePicture() method. I have attributes to save my views, camera and camera preview, but nothing else. – Oyashiro Jul 04 '13 at 08:55
  • Looks like it was my views that were too big. See my edit post. – Oyashiro Jul 04 '13 at 09:58