Reputation: 8538
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?
Upvotes: 1
Views: 2093
Reputation: 28087
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;
}
Upvotes: 3