2

I have tried develop an apps. This is ok for a small 101KB image file but when i use this apps for 307KB image instead of this image then it doesn't run and shows : java.lang.OutOfMemoryError: bitmap size exceeds VM budget.

Following is my code:

    Resources rs = getResources();
    Drawable dw = rs.getDrawable(R.drawable.chart);
    width =  dw.getIntrinsicWidth();
    height = dw.getIntrinsicHeight();
    DisplayMetrics dm = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);

    fitScaleX = (float)dm.widthPixels / (float)width;
    fitScaleY = fitScaleX;

and at line, Drawable dw = rs.getDrawable(R.drawable.chart); The error occurs. How can i avoid this probleme?

This is my full code:

public class ZoomActivity extends Activity implements OnTouchListener { 

ImageView view;
Matrix  matrix = new Matrix();
Matrix  savedMatrix = new Matrix();
PointF  start = new PointF();
PointF  mid = new PointF();
float   oldDist = 0;
int     width = 0;
int     height = 0;
float   fitScaleX = 1.0f;
float   fitScaleY = 1.0f;

static final int STATE_NONE = 0;
static final int STATE_DRAG = 1;
static final int STATE_ZOOM = 2;
int mode = STATE_NONE;
long doubleClickStartTime = 0;
boolean doubleClickFlag = false;

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

    setContentView(R.layout.chart);        

    view = (ImageView) findViewById(R.id.imageViewChart);
    view.setOnTouchListener(this);

    getFitScale();      

    matrix.postScale(fitScaleX, fitScaleY, 0, 0);
    view.setImageMatrix(matrix);
}

public void onStart() {
    super.onStart();


}

private void getFitScale() {        
    Resources rs = getResources();
    Drawable dw = rs.getDrawable(R.drawable.chart);
    width =  dw.getIntrinsicWidth();
    height = dw.getIntrinsicHeight();
    DisplayMetrics dm = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);

    fitScaleX = (float)dm.widthPixels / (float)width;
    fitScaleY = fitScaleX;
}   

public boolean onTouch(View v, MotionEvent event)
{       
    // Handle touch events here...
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN:
         savedMatrix.set(matrix);
         start.set(event.getX(), event.getY());
         mode = STATE_DRAG; 
         break;
    case MotionEvent.ACTION_UP:
        mode = STATE_NONE;
         // for Auto Fitting
         if(doubleClickFlag == false)
             doubleClickStartTime = SystemClock.uptimeMillis();

         if(doubleClickFlag) { 
             if(SystemClock.uptimeMillis() - doubleClickStartTime < 500) {
                matrix.reset();
                matrix.postScale(fitScaleX, fitScaleY, 0, 0);
             } else {
                doubleClickStartTime = SystemClock.uptimeMillis();
                doubleClickFlag = false;
             }
         }

         if(doubleClickFlag == false)
             doubleClickFlag = true;
         else
             doubleClickFlag = false;
         break;
    case MotionEvent.ACTION_POINTER_UP:
         mode = STATE_NONE;  
         break;
    case MotionEvent.ACTION_MOVE:
         if (mode == STATE_DRAG) {
             float dx = event.getX() - start.x;
             float dy = event.getY() - start.y;
             float[] values = new float[9];              

             matrix.set(savedMatrix);
             matrix.getValues(values);

             if(values[Matrix.MTRANS_X]+ dx < view.getWidth() - width * values[Matrix.MSCALE_X]) {                  
                dx = view.getWidth()  - values[Matrix.MTRANS_X] - width * values[Matrix.MSCALE_X];
             }               
             else if(values[Matrix.MTRANS_X]+ dx > 0) {
                 dx = 0 - values[Matrix.MTRANS_X];
             }

             if(values[Matrix.MTRANS_Y] + dy  < view.getHeight() - height*values[Matrix.MSCALE_Y]) {                     
                dy = view.getHeight() - height * values[Matrix.MSCALE_Y] - values[Matrix.MTRANS_Y];
             }
             else if(values[Matrix.MTRANS_Y] + dy > 0) {
                 dy = 0 - values[Matrix.MTRANS_Y];
             }

             matrix.postTranslate(dx, dy);
         }
         else if (mode == STATE_ZOOM) {
              float newDist = spacing(event);
              matrix.set(savedMatrix);

              if (newDist > 10f) {
                 float[] values = new float[9];              

                 matrix.set(savedMatrix);
                 matrix.getValues(values);

                 float scale = newDist / oldDist;

                 if(values[Matrix.MSCALE_X] * scale > 3.0f ||
                    values[Matrix.MSCALE_Y] * scale > 3.0f   ) {
                    matrix.reset();
                    matrix.postScale(3.0f, 3.0f, 0, 0);
                 }
                 else if(values[Matrix.MSCALE_X] * scale < fitScaleX ||
                         values[Matrix.MSCALE_Y] * scale < fitScaleY) {
                    matrix.reset();
                    matrix.postScale(fitScaleX, fitScaleY, 0, 0);
                 }
                 else {
                     matrix.postScale(scale, scale, 0, 0);
                 }
              }
           }
         break;

    case MotionEvent.ACTION_POINTER_DOWN:
         oldDist = spacing(event);

         if (oldDist > 10f) {
             savedMatrix.set(matrix);
             midPoint(mid, event);
             mode = STATE_ZOOM;            
         }
         break;
    }

    // Perform the transformation
    view.setImageMatrix(matrix);

    return true; // indicate event was handled
}

private float spacing(MotionEvent event) {
    float x = event.getX(0) - event.getX(1);
    float y = event.getY(0) - event.getY(1);

    return FloatMath.sqrt(x * x + y * y);
}

private void midPoint(PointF point, MotionEvent event) {
    float x = event.getX(0) + event.getX(1);
    float y = event.getY(0) + event.getY(1);
    point.set(x / 2, y / 2);
}
}

1 Answer 1

1

Bitmap images consume lot of memory, it is better to reduce their resolution. Here is a link with couple of workarounds with this issue. Bitmap images exceed VM budget work arounds

Sign up to request clarification or add additional context in comments.

3 Comments

Please summarize the result, rather than just linking to it?
One of the summary point is set your bitmap references to null at the end, which will allow gc to do garbage collection frequently. There are couple of workarounds for this, so referring that link may helpful.
Sorry, Can't understand at where i have to change the code. Please specify.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.