簡體   English   中英

在Android畫布上繪制旋轉位圖的最佳方法是什么?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM