[英]What is the most performant way to draw a rotated bitmap on an Android canvas?
我正在開發一個應用程序,我們手動滾動一些星圖。 所以我不必抽象地談論,這是有問題的應用程序: https : //play.google.com/store/apps/details?id = com.tw.fireballs
如果你查看商店列表,你可以看到我們使用的是地平線上方的圖像...主要是因為它看起來非常漂亮。 這對於較低分辨率的設備來說不是問題,由於所涉及的像素數量較少,它們似乎沒有遇到很大的問題。 在像我的HTC One或我的妻子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();
}
有沒有更有效的方法來做到這一點,不會受到屏幕分辨率的影響? 我們圍繞着一些想法,但是我很想聽到比我更了解這些東西的人。如果你有任何問題,請問,我會感激任何幫助。
干杯,內森
@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();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.