Question

Objective of the program: the user is able to place one picture on the top of camera preview and move it freely (image is big 1920x1080 pixels) and can store this two layers (picture and camera preview) pressing the photo button. So far he is only able to save one picture of this kind because when he takes the second one the out of memory error problem appears.

Solution It seems that the problem can be solved if you use recycle bitmap function when you dont need to use bitmaps anymore. Or you can resize them (didn't want to)... Are these good ideas?

Code:

private PictureCallback mPicture = new PictureCallback()
{
    @Override
    public void onPictureTaken(byte[] data, Camera camera)
    {   
        File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        mPreview.setDrawingCacheEnabled(true);
        mPreview.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_AUTO);
        Bitmap bitmap = mPreview.getDrawingCache();
        bmp = BitmapFactory.decodeByteArray(data, 0, data.length);  
        combination = overlay(bmp, bitmap);

        if(pictureFile == null)
        {
            return;
        }
        try
        {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            combination.compress(CompressFormat.JPEG, 100, fos);
            fos.flush();
            fos.close();
            File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_PICTURES), "MyCameraApp");
                sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
                    Uri.parse("file://"+ mediaStorageDir)));
        }
        catch(FileNotFoundException e)
        {
            Log.d(TAG, "File not found: "+e.getMessage());
        }
        catch(IOException e)
        {
            Log.d(TAG, "Error accessing file: "+e.getMessage());
        }
    }

};

public static Bitmap overlay(Bitmap bmp1, Bitmap bmp2)
{   
    Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(),bmp1.getConfig());
    Canvas canvas = new Canvas(bmOverlay);
    canvas.drawBitmap(bmp1, new Matrix(), null);
    canvas.drawBitmap(bmp2, null, new Rect(0,0,bmp1.getWidth(), bmp1.getHeight()), null);
    return bmOverlay;       
}

private static File getOutputMediaFile(int type)
{
    File mediaFile = null; 

    if(isSdPresent() == false)
    {
        Log.d(TAG, "There is no Sd card. Cannot use the camera");
    }

   else
    {
        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "World Cup Camera");

        if(!mediaStorageDir.exists())
        {
            if(!mediaStorageDir.mkdirs())
            {
                Log.d("WorldCupApp", "failed to create directory");
                return null;
            }
        }

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());       

        if (type == MEDIA_TYPE_IMAGE)
        {        
            mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg");    
        }

        else 
        {       
            return null;  
        }           
    }
    return mediaFile;
}

I heard about this code should I use?

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

        //The new size we want to scale to
        final int REQUIRED_SIZE=70;

        //Find the correct scale value. It should be the power of 2.
        int scale=1;
        while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
            scale*=2;

        //Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize=scale;
        return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
    } 
    catch (FileNotFoundException e) {}
    return null;
}
Was it helpful?

Solution

You can use android:largeHeap="true" inside the application tag on AndroidManifest when you're having outofmemory errors.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top