Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing bitmap image on loop

I have a canvas and I wish to change the bitmap image every 50 milliseconds.

Basically what I'm trying to do is like a gif animation.

As you can see there's 4 images and every 50 milliseconds I want it to change the image.

the code below doesn't work and I have no clue why.

protected void onDraw(final Canvas canvas) {

    res = getResources();
    image = BitmapFactory.decodeResource(res, R.drawable.image_1);
    canvas.drawBitmap(image, 0, 0, paint);

    new Thread(new Runnable() {

        @Override
        public void run() {
            while (!Thread.interrupted())
                try {
                    Thread.sleep(50);
                    System.out.println("OK2");

                    time++;
                    ((Activity) context).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {

                            if (time == 1) {

                                image = BitmapFactory.decodeResource(res,
                                        R.drawable.image_1);

                                canvas.drawBitmap(image, 0, 0, paint);
                                invalidate();
                            }
                            if (time == 2) {
                                image = BitmapFactory.decodeResource(res,
                                        R.drawable.image_2);

                                canvas.drawBitmap(image, 0, 0, paint);
                                invalidate();

                            }

                            if (time == 3) {
                                image = BitmapFactory.decodeResource(res,
                                        R.drawable.image_3);

                                canvas.drawBitmap(image, 0, 0, paint);
                                invalidate();

                            }

                            if (time >= 4) {

                                time = 0;
                                image = BitmapFactory.decodeResource(res,
                                        R.drawable.image_4);
                                canvas.drawBitmap(image, 0, 0, paint);
                                invalidate();

                            }
                        }
                    });
                } catch (InterruptedException e) {

                }
        }

    }).start();
    super.onDraw(canvas);

}

Thanks in advance.

like image 973
Amit Avatar asked Sep 08 '26 03:09

Amit


1 Answers

There's a couple of problems:

You are decoding the resources over and over each time. decodeResource might not be fast enough to load the image within 50 milliseconds. It would be faster to decode the frames once and store them in an array. e.g.:

Bitmap images[4];
void loadFrames()
{
    res = getResources();
    images[0] = BitmapFactory.decodeResource(res, R.drawable.image_1);
    images[1] = BitmapFactory.decodeResource(res, R.drawable.image_2);
    images[2] = BitmapFactory.decodeResource(res, R.drawable.image_3);
    images[3] = BitmapFactory.decodeResource(res, R.drawable.image_4);
}

You are starting a new thread every time onDraw() is called, which means hundreds of threads will be created. Instead, you should create the thread just once. Inside the thread, increment your counter and set image to the correct frame, then call invalidate:

 Thread.sleep(50);
 time = (time + 1) % 4;
 image = images[time];
 ((Activity) context).runOnUiThread(new Runnable() {
      @Override
      public void run() {
          invalidate();
      }
 };

Then inside onDraw(), draw onto the canvas with the current image:

 canvas.drawBitmap(image, 0, 0, paint);
like image 129
samgak Avatar answered Sep 10 '26 17:09

samgak