在Android画布上绘制旋转位图最有效的方法是什么?
我正在开发一个应用程序,我们手推了一些星图。所以我不必抽象地说,这里是有问题的应用程序: 如果你看一下商店清单,你会发现我们使用的是地平线上的一张图片……主要是因为它看起来非常漂亮。这不是低分辨率设备的问题,因为涉及的像素数较少,所以它们在渲染时似乎不会遇到太大的问题。在更高分辨率的设备上,如我的HTC One或我妻子的Nexus 5,当它出现在屏幕上时,帧速率会大幅下降。这还不足以阻止我发布它,但如果可能的话,我想改进它 我目前只使用一个SurfaceView,并将其绘制到由mSurfaceHolder.lockCanvas(null)获取的画布上,因此它不是硬件加速的。我试着将它实现为一个常规视图,但总体来说,它实际上运行得比较慢,所以在我进入OpenGL领域之前,我想探索一下我是否可以做些什么来加速它 从本质上讲,我们从一个穿过地平线的薄(不透明)图像“切片”开始,将其放大到屏幕对角线的大小,然后旋转以匹配设备的方向 图纸代码如下所示:在Android画布上绘制旋转位图最有效的方法是什么?,android,graphics,bitmap,android-canvas,surfaceview,Android,Graphics,Bitmap,Android Canvas,Surfaceview,我正在开发一个应用程序,我们手推了一些星图。所以我不必抽象地说,这里是有问题的应用程序: 如果你看一下商店清单,你会发现我们使用的是地平线上的一张图片……主要是因为它看起来非常漂亮。这不是低分辨率设备的问题,因为涉及的像素数较少,所以它们在渲染时似乎不会遇到太大的问题。在更高分辨率的设备上,如我的HTC One或我妻子的Nexus 5,当它出现在屏幕上时,帧速率会大幅下降。这还不足以阻止我发布它,但如果可能的话,我想改进它 我目前只使用一个SurfaceView,并将其绘制到由mSurfaceH
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();
}
有没有一种更有效的方法可以避免屏幕分辨率的影响?我们已经提出了一些想法,但我很想听听比我更了解这些东西的人的意见。如果你有任何问题,请提问,我将非常感谢你的帮助
干杯,
内森@pskink一针见血。使用矩阵参数绘制位图要比我所经历的缩放位图和画布旋转性能好得多。在像我的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();
}
使用矩阵参数尝试drawBirmap,当使用适当的矩阵时,您可能不需要缩放位图。这与其说是一个解决方案,不如说是一个想法。由于背景的原因,不透明图像需要绘制两次,因此需要使用更多的资源。图像有补丁吗?编辑:检查这个链接,@pskink-这是秘密酱汁。在矩阵中使用缩放变换绘制位图比旋转画布并绘制缩放位图要快得多。@PontusBacklund-谢谢,这是一个有用的页面。它最终并没有解决我的问题,但它给了我一些总体优化应用程序的想法。