1

I need to make several frame-by-frame animation, each containing up to 150 full screen, 480x800, frames, compressed JPEGs.

AnimationDrawable hangs itself with vm budget exceeded after first 10 frames or so.

SurfaceView with new bitmaps loading on timer gives a pretty slow framerate, probably less than 5 fps.

Since I'm new to OpenGL, I wanted to ask if its the right way to go in my situation?

Thanks! :)

edit:

loading jpges by

    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    BitmapFactory.decodeResource(getResources(), R.drawable.y1).compress(Bitmap.CompressFormat.JPEG, 80, stream);
    byeArr.add( stream.toByteArray() );

    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    BitmapFactory.decodeResource(getResources(), R.drawable.y2).compress(Bitmap.CompressFormat.JPEG, 80, stream);
    byeArr.add( stream.toByteArray() );

... and so on.

and playing by

@Override
public void onTick(long millisUntilFinished) {

    if ( i < byeArr.size() )
    {
    bitMap = BitmapFactory.decodeByteArray ( byeArr.get(i) , 0,  byeArr.get(i).length );
    }

yet loading 25 frames takes about 3-5 second. Maybe there's a way to speed that up? Also is there a way to see how much free memory I have, i.e. how much frames can I load?

Thanks


edit2: experimentally found that it can keep about 350 frames in an array, which is very good for about 2 full animations. now I just need to find a way to somehow store this pictures as bytes, to be able to load them in almost real time, since decodeResource is kinda slow.

edit3: in edit 2 I made sure that I can store about 350 frames in an array, which is quite enough for one animation.

Therefor I can load frames needed for a current animation into a byte array and play the animation.

Yet the problem is that loading frames by

ByteArrayOutputStream stream = new ByteArrayOutputStream();
BitmapFactory.decodeResource(getResources(), R.drawable.y1).compress(Bitmap.CompressFormat.JPEG, 80, stream);
byeArr.add( stream.toByteArray() );

takes too long. So I need to find a way to speed that up. Supposedly I need to store jpegs already as byte arrays in res or assets, what do you think?

Roger Travis
  • 8,402
  • 18
  • 67
  • 94

1 Answers1

3

Start with convert your animation to a video stream then use MediaMetadataRetriever.getFrameAtTime to get the frames. If getting right frames turns to be a problem, you might need to use a library like ffmpeg, look here.

Another solution - if your total allocation size of jpeg set is small enough - might be to keep jpegs in memory as byte arrays and decode them through BitmapFactory.decodeByteArray whenever you need it. This will help you with 1) vm budget 2) slow disk access.

You can use the method below to get the raw data from a resource.

byte[] getBytesFromResource(final int res) {
    byte[] buffer = null;
    InputStream input = null;

    try {
        input = getResources().openRawResource(res);
        buffer = new byte[input.available()];
        if (input.read(buffer, 0, buffer.length) != buffer.length) {
            buffer = null;
        }
    } catch (IOException e) {
        buffer = null;
    } finally {
        if (input != null) {
            try {
                input.close();
            } catch (IOException e) {}
        }
    }

    return buffer;
}
Community
  • 1
  • 1
auselen
  • 27,577
  • 7
  • 73
  • 114
  • That's up to you but don't forget to check [supported media formats page](http://developer.android.com/guide/appendix/media-formats.html). – auselen Sep 16 '12 at 07:56
  • @RogerTravis how much for example an animation session allocates space in disk? I mean how much those 150 jpegs take space? – auselen Sep 16 '12 at 08:30
  • I guess about 5 Mbs, not that much. – Roger Travis Sep 16 '12 at 08:49
  • Thanks, the second solution gives very good results with playback. Yet it takes a while ( ~3 seconds to load ), see above. Is there a way to speed it up? – Roger Travis Sep 16 '12 at 10:26