2013-11-15 25 views
0

我正在研究一个应用程序,在其中我们手动滚动了一些星图。所以我不必在抽象中谈论,这里是有问题的应用程序:https://play.google.com/store/apps/details?id=com.tw.fireballs什么是在Android画布上绘制旋转位图的最高性能方法?

如果您看商店列表,您可以看到我们使用地平线上方的图像......主要是因为它看起来超级漂亮。这对于较低分辨率的设备来说不是问题,由于涉及的像素数量较少,它们似乎不会出现渲染它的大问题。在像我的HTC One或我的wifes Nexus 5这样的更高分辨率的设备上,屏幕上出现大幅下降。防止我释放它还不够坏,但如果可能的话,我想改进它。

我目前只是使用SurfaceView,并绘制到由mSurfaceHolder.lockCanvas(null)获取的画布,所以它不是硬件加速的。我尝试将它作为一个常规视图来实现,但总体上它实际上变慢了,所以在我投入OpenGL领域之前,我想探索一下如果有什么我可以加速的。从本质上讲,我们首先从地平线上的薄片(不透明)图像“切片”开始,将其缩放到屏幕对角线的大小并旋转它以匹配设备的方向。

绘图代码如下:

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(); 
} 

有没有更有效的方法可以做到这一点不会因此受到屏幕分辨率?我们围绕着一些想法大肆宣传,但我很乐意听到有人比我更了解这些东西。如果您有任何问题,请问,我会很感激任何帮助。

干杯, 弥敦道

+1

用矩阵PARAM试drawBirmap,你可能不会使用正确的矩阵 – pskink

+2

时,这是需要一个缩放位图更多的是思想而不是解决方案,不透明的图像需要因背景而绘制两次,因此需要使用更多的资源。图像是否被打补丁?编辑:检查这个链接,http://www.curious-creature.org/docs/android-performance-case-study-1.html –

+0

@pskink - 这是秘密的酱油。在Matrix中使用缩放转换来绘制位图要比旋转画布和绘制缩放位图要快得多。 – thenathanjones

回答

1

@pskink击中了要害。使用Matrix参数绘制位图要比我经历的缩放位图和画布旋转性能高得多。在像我的HTC One这样的1080P设备上,如果我将手机放在对角线上,我曾经看过帧速从50+降至〜10。现在,我是幸运的,如果它降到5

现在修改后的代码看起来像:

@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(); 
} 
相关问题