什么是画一个Android的画布上旋转的位图最高效的方法是什么? [英] What is the most performant way to draw a rotated bitmap on an Android canvas?

查看:232
本文介绍了什么是画一个Android的画布上旋转的位图最高效的方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的工作,我们手卷一些星图的应用程序。所以,我没有在抽象交谈,这里是有问题的应用程序:的 https://play.google.com/store/apps/details?id=com.tw.fireballs

I'm working on an app where we hand rolled some star maps. So I don't have to talk in the abstract, here is the app in question: https://play.google.com/store/apps/details?id=com.tw.fireballs

如果你看看商店上市,你可以看到我们使用图像就在地平线上......主要是因为它看起来超pretty。这不是在较低分辨率设备的问题,他们似乎并不遭受了巨大的问题,使得它由于数量较少涉及的像素。像我的HTC One还是我妻子的Nexus 5的分辨率更高的设备,有一个很大的帧率下降时,它在屏幕上。这还不够糟糕到prevent我释放它,但我想如果可能的话,以改善它。

If you look on the store listing, you can see we use an image just above the horizon...mostly because it looks super pretty. It's not an issue on lower resolution devices, they don't seem to suffer a huge issue rendering it due to lower number of pixels involved. On a higher resolution device like my HTC One or my wifes Nexus 5, there is a big framerate drop when it's on the screen. It's not bad enough to prevent me releasing it, but I'd like to improve it if possible.

我目前只使用一个SurfaceView,并绘制由mSurfaceHolder.lockCanvas(空)获得了画布,所以它不是硬件加速。我试图实现为是常规的观点,但总体上居然跑到慢,所以我花了一大笔钱到OpenGL的土地之前,我想探索是否有什么我可以做,以加快这

I'm currently just using a SurfaceView, and drawing to a canvas acquired by mSurfaceHolder.lockCanvas(null), so it's not hardware accelerated. I tried implementing it as a regular view which is, but overall it actually went slower, so before I take the plunge into OpenGL land I want to explore if there is something I can do to speed this up.

本质上,我们开始用薄(不透明)图像片,通过在地平线上,缩放到对角线屏幕的尺寸和周围旋转以匹配设备的方向。

Essentially, we start with a thin (opaque) image "slice" through the horizon, scale it up to the size of the diagonal of the screen and rotate it around to match the orientation of the device.

绘图code是如下:

private void loadResources() {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig = Bitmap.Config.RGB_565;
    mHorizonImage = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.star_map_background, options);
}

@Override
public void updateDimensions(int width, int height) {
    super.updateDimensions(width, height);

    int horizonHeight = mCanvasHeight / 3;
    int horizonWidth = (int) Math.sqrt(Math.pow(mCanvasHeight, 2) + Math.pow(mCanvasWidth, 2));

    mHorizonImage = Bitmap.createScaledBitmap(mHorizonImage, horizonWidth, horizonHeight, false);
}

@Override
public void drawOn(Canvas canvas) {
    double upScreen = -mProjection.distanceFromScreen * Math.tan(Math.toRadians(mOrientation.elevation));
    double rightWithTiltCheat = upScreen * Math.sin(Math.toRadians(mOrientation.tilt));
    double upWithTiltCheat = upScreen * Math.cos(Math.toRadians(mOrientation.tilt));

    float x = (float) (mCanvasWidth / 2 * (1 + rightWithTiltCheat / mProjection.screenWidthInCm));
    float y = (float) (mCanvasHeight / 2 * (1 - upWithTiltCheat / mProjection.screenHeightInCm));

    canvas.save();
    canvas.translate(x, y);
    canvas.rotate((float) mOrientation.tilt);
    canvas.drawBitmap(mHorizonImage, -mHorizonImage.getWidth() / 2, -mHorizonImage.getHeight(), null);
    canvas.restore();
}

有没有更有效的方法来做到这一点,将不会如此受到屏幕分辨率?我们周围到处传说的一些想法,但我渴望从别人谁知道这东西比我更好,如果您有任何疑问,请询问,我会的任何援助表示感谢听到。

Is there a more efficient way to do this that won't be so affected by screen resolution? We've bandied around a few ideas, but I'd be keen to hear from someone who knows this stuff better than I. If you have any questions, please ask, I'd be grateful for any assistance.

干杯,
内森

推荐答案

@pskink击中了要害。用矩阵参数绘制位图比缩放的位图和画布旋转我正经历着更高性能。像我的HTC One 1080P的设备我用,如果我把手机上的对角线从50+到10〜观看帧率下降。现在,我是幸运的,如果它降到5。

@pskink hit the nail on the head. Drawing the bitmap with a Matrix param is much more performant than the scaled bitmap and canvas rotation I was experiencing. On 1080P devices like my HTC One I used to watch the frame rate drop from 50+ to ~10 if I held the phone on a diagonal. Now I'd be lucky if it drops 5.

修改code现在看起来像:

The modified code now looks like:

@Override
public void updateDimensions(int width, int height) {
    super.updateDimensions(width, height);

    mHorizonHeight = mCanvasHeight / 3;
    mHeightScale = (float)mHorizonHeight / (float)mHorizonImage.getHeight();

    mHorizonWidth = (int) Math.sqrt(Math.pow(mCanvasHeight, 2) + Math.pow(mCanvasWidth, 2));
    mWidthScale = (float)mHorizonWidth / (float)mHorizonImage.getWidth();
}

@Override
public void drawOn(Canvas canvas) {
    double upScreen = -mProjection.distanceFromScreen * Math.tan(Math.toRadians(mOrientation.elevation));
    double rightWithTiltCheat = upScreen * Math.sin(Math.toRadians(mOrientation.tilt));
    double upWithTiltCheat = upScreen * Math.cos(Math.toRadians(mOrientation.tilt));

    float x = (float) (mCanvasWidth / 2 * (1 + rightWithTiltCheat / mProjection.screenWidthInCm));
    float y = (float) (mCanvasHeight / 2 * (1 - upWithTiltCheat / mProjection.screenHeightInCm));

    mDrawMatrix.reset();
    mDrawMatrix.postScale(mWidthScale, mHeightScale);
    mDrawMatrix.postTranslate(x - mHorizonWidth / 2, y - mHorizonHeight);
    mDrawMatrix.postRotate((float) mOrientation.tilt, x, y);
    canvas.drawBitmap(mHorizonImage, mDrawMatrix, null);
    canvas.save();
}

这篇关于什么是画一个Android的画布上旋转的位图最高效的方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆