在Android上绘制高帧率的高分辨率动画

发布于 2024-10-12 17:31:45 字数 929 浏览 1 评论 0原文

我有 30 多个单位图(320x240 像素),我想在 Android 设备上全屏显示它们,从而产生动画。目前,我使用 ImageView 和设置下一帧的计时器实现了动画,然后发送一条将应用下一帧的消息。结果帧速率非常低:< 2 帧/秒。

计时器:

animationTimer.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        Drawable frame = getNextFrame();
            if (frame != null) {
                Message message = animationFrameHandler.obtainMessage(1, frame);
                animationFrameHandler.sendMessage(message);
            }
        }
    }, 0, (int) (1000.0d / fps));

处理程序:

final Handler animationFrameHandler = new Handler() {
    @Override
    public void handleMessage(Message message) {
        setImageDrawable((Drawable) message.obj);
    }
};

由于我想实现高达 30 fps 的帧速率,我必须使用另一种机制并听说过 Canvas.drawBitmapMesh() OpenGL

如果可能的话我想避免使用 OpenGL。

非常感谢您分享您的经验!

I've got 30+ single bitmaps (320x240 pixels) that I would like to display one after another in full screen on Android devices resulting in an animation. Currently I implemented the animation using an ImageView and a Timer that sets the next frame and then sends a message that will apply the next frame. The resulting frame rate is very low: < 2 fps.

The timer:

animationTimer.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        Drawable frame = getNextFrame();
            if (frame != null) {
                Message message = animationFrameHandler.obtainMessage(1, frame);
                animationFrameHandler.sendMessage(message);
            }
        }
    }, 0, (int) (1000.0d / fps));

The handler:

final Handler animationFrameHandler = new Handler() {
    @Override
    public void handleMessage(Message message) {
        setImageDrawable((Drawable) message.obj);
    }
};

Since I want to achieve frame rates up to 30 fps I have to make use of another mechanism and heard of Canvas.drawBitmapMesh() and OpenGL.

If possible I would like to avoid using OpenGL.

Thank you very sharing your experiences!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

月竹挽风 2024-10-19 17:31:45

我现在的工作方法如下:

在开始动画之前,将每个帧加载到 List 中。重要提示:如果遇到 OutOfMemoryError,请调用 System.gc() – 这确实有助于将更多位图加载到内存中。然后运行一个线程,将下一帧发布到 View 实例,然后更新其画布。

加载帧并开始动画

// Loading the frames before starting the animation
List<Bitmap> frames = new ArrayList<Bitmap>();
for (int i = 0; i < 30; i++) {
    // Load next frame (e. g. from drawable or assets folder)
    frames.add(...);
    // Do garbage collection every 3rd frame; really helps loading all frames into memory
    if (i %% 3 == 0) {
        System.gc();
    }
}

// Start animation
frameIndex = 0;
animationThread.start();

应用下一帧的线程

private final class AnimationThread extends Thread {
    @Override
    public void run() {
        while (!isInterrupted()) {
            // Post next frame to be displayed
            animationView.postFrame(frames.get(frameIndex));

            // Apply next frame (restart if last frame has reached)
            frameIndex++;
            if (frameIndex >= frames.size()) {
                frameIndex = 0;
            }

            try {
                sleep(33); // delay between frames in msec (33 msec mean 30 fps)
            } catch (InterruptedException e) {
                break;
            }
        }
    }
}

动画视图

class AnimationView extends View {
    Bitmap frame = null;

    public void postFrame(Bitmap frame) {
        Message message = frameHandler.obtainMessage(0, frame);
        frameHandler.sendMessage(message);
    }

    protected final Handler frameHandler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            if (message.obj != null) {
                frame = (Bitmap) message.obj;
            } else {
                frame = null;
            }
            invalidate();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (frame == null) return;
        canvas.drawARGB(0, 0, 0, 0);
        canvas.drawBitmap(frame, null, null, null);
    }
}

My now working approach is the following:

Before starting the animation, load every frame into a List<Bitmap>. Important: Call System.gc() if you're getting OutOfMemoryErrors – that really helps loading more bitmaps into the memory. Then have a thread running that posts the next frame to a View instance that then update it's canvas.

Loading the frames and starting the animation

// Loading the frames before starting the animation
List<Bitmap> frames = new ArrayList<Bitmap>();
for (int i = 0; i < 30; i++) {
    // Load next frame (e. g. from drawable or assets folder)
    frames.add(...);
    // Do garbage collection every 3rd frame; really helps loading all frames into memory
    if (i %% 3 == 0) {
        System.gc();
    }
}

// Start animation
frameIndex = 0;
animationThread.start();

Thread that applies the next frame

private final class AnimationThread extends Thread {
    @Override
    public void run() {
        while (!isInterrupted()) {
            // Post next frame to be displayed
            animationView.postFrame(frames.get(frameIndex));

            // Apply next frame (restart if last frame has reached)
            frameIndex++;
            if (frameIndex >= frames.size()) {
                frameIndex = 0;
            }

            try {
                sleep(33); // delay between frames in msec (33 msec mean 30 fps)
            } catch (InterruptedException e) {
                break;
            }
        }
    }
}

The animation view

class AnimationView extends View {
    Bitmap frame = null;

    public void postFrame(Bitmap frame) {
        Message message = frameHandler.obtainMessage(0, frame);
        frameHandler.sendMessage(message);
    }

    protected final Handler frameHandler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            if (message.obj != null) {
                frame = (Bitmap) message.obj;
            } else {
                frame = null;
            }
            invalidate();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (frame == null) return;
        canvas.drawARGB(0, 0, 0, 0);
        canvas.drawBitmap(frame, null, null, null);
    }
}
离不开的别离 2024-10-19 17:31:45

您应该查看 FrameAnimation 类; http://developer.android.com/guide/topics /graphics/2d-graphics.html#frame-animation 使用 Android 动画制作帧动画。

尽管这可能仍然太慢。

如果您不想使用 OpenGL ES,另一种选择是像您提到的那样绘制到画布上。但只使用.drawBitmap,而不是drawBitmapMesh。创建一个 SurfaceView,它有一个线程,该线程应该以您想要的任何时间间隔在您的 Canvas 上绘制。

非常简单,只需阅读 Android 文档,信息就在那里。

You should look at the FrameAnimation class; http://developer.android.com/guide/topics/graphics/2d-graphics.html#frame-animation to do frame animation with Androids animation.

Though that might still be too slow.

The other alternative if you don't want to use OpenGL ES is to draw to the Canvas as you've mentioned. But just use .drawBitmap, not the drawBitmapMesh. Create a SurfaceView, which has a thread, that thread should draw on your Canvas at whatever interval you want.

It's pretty straightforward, just read the Android docs, the information is all there.

倾城°AllureLove 2024-10-19 17:31:45

我会让其他人讨论执行此操作的最佳方法,但从您的帖子中立即跳到脑海中的一件事没有帮助,那就是使用 TimerTask 是执行此操作的一种糟糕方法,并且不适用于动画。

I'll let someone else go into the best way of doing this but one thing that immediately jumps to mind from your post that isn't helping is using TimerTask is a terrible way to do this and is not meant for animation.

捶死心动 2024-10-19 17:31:45

可能对性能没有帮助,但如果这些位图是资源,您可能需要考虑使用 AnimationDrawable。如果没有,请尝试扩展 Drawable 并实现 Animatable 接口。视图已经内置了对可绘制动画的支持,无需为此使用处理程序。

提高性能的一种方法可能是将可绘制对象的位深度与当前窗口的位深度相匹配。 Romain Guy 曾就此问题和一般动画做过一次主题演讲:http://www.youtube.com/观看?v=duefsFTJXzc

Probably won't help with performance, but if those bitmaps are resources you might want to consider using an AnimationDrawable. If not, try to extend Drawable and implement the Animatable interface. Views already have built-in support for animating drawables, no need to use a handler for that.

One way to improve performance might be to match the bit-depth of the drawables to those of your current window. Romain Guy did a keynote on this and animations in general once: http://www.youtube.com/watch?v=duefsFTJXzc

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文