跨多个设备使用手动缩放位图的性能

时间:2011-08-22 15:25:47

标签: java android bitmap scaling

我正在开发一款在图像资源方面相当沉重的Android游戏。我面临的挑战之一是我需要手动缩放图形以匹配不同的屏幕尺寸。不允许Android自动缩放的原因是游戏依赖于图形不会拉伸或倾斜。我可能会在每次按屏幕时切换3-4位图,因此性能是关键(我已经设置了一个缓存操作来帮助这个)。

在考虑了Android设备的问题和多样性之后,我决定采用以下方法来尽可能多地设置目标:

  1. 制作特定密度的图片(通过http://developer.android.com/guide/topics/resources/providing-resources.html以及dev.android.com中列出的其他建议)
  2. 不是为不同的屏幕尺寸制作多个版本的图像,而是创建一个覆盖所有目标屏幕的非常大的图像,并使用手动缩放来缩小其尺寸以匹配设备。
  3. 到目前为止,这种方法进展顺利,但我需要从我的自定义BitmapScaler类中获得更多性能。我利用这里找到的代码库来满足我自己的需求:http://zerocredibility.wordpress.com/2011/01/27/android-bitmap-scaling/

    话虽如此,这是我的问题:有没有人对我解决屏幕命运/屏幕大小问题的方法的可行性有任何意见?我知道我在这里为了方便而交易表现。任何人都可以建议在我的位图缩放操作中挤出更好的性能(下图)?

        public class BitmapScaler {
    
    private Bitmap scaledBitmap;
    
    public Bitmap getScaledBitmap()
    {
    return scaledBitmap;
    }
    
    /* IMPORANT NOTES:
    * The process of scaling bitmaps for Android is not a straightforward process. In order to
    * help preserve memory on the phone, you need to go through several steps:
    *
    * 1. Decode the target resource, but use the inJustDecodeBounds option. This allows you to "sample"
    * the resource without actually incurring the hit of loading the entire resource. If set to true, the decoder will return null
    * (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate
    * the memory for its pixels.
    * 2. Determine the new aspects of your bitmap, particularly the scale and sample. If the sample size is set to a value > 1,
    * requests the decoder to subsample the original image, returning a smaller image to save memory. The sample size is the number
    * of pixels in either dimension that correspond to a single pixel in the decoded bitmap. For example, inSampleSize == 4 returns
    * an image that is 1/4 the width/height of the original, and 1/16 the number of pixels. Any value <= 1 is treated the same as 1.
    * Note: the decoder will try to fulfill this request, but the resulting bitmap may have different dimensions that precisely what
    * has been requested. Also, powers of 2 are often faster/easier for the decoder to honor.
    * 3. Prescale the bitmap as much as possible, rather than trying to fully decode it in memory. This is a less
    * expensive operation and allows you to "right size" your image.
    * 4. Create your new bitmap, applying a matrix to "fine tune" the final resize.
    *
    * Partial Ref: http://zerocredibility.wordpress.com/2011/01/27/android-bitmap-scaling/
    */
    
    public BitmapScaler(Resources resources, int targetResourceID, int targetWidth, int targetHeight)
    {
    BitmapInfo originalInfo = getOriginalBitmapInfo(resources, targetResourceID);
    BitmapInfo newInfo = getScaledBitmapInfo(targetHeight, targetWidth, originalInfo);
    prescaleScaledBitmap(resources, targetResourceID, newInfo);
    scaleScaledBitmap(newInfo);
    }
    
    private void scaleScaledBitmap(BitmapInfo newInfo)
    {
    
    int ScaledHeight = scaledBitmap.getHeight();
    int ScaledWidth = scaledBitmap.getWidth();
    
    float MatrixWidth = ((float)newInfo.width) / ScaledWidth;
    float MatrixHeight = ((float)newInfo.height) / ScaledHeight;
    
    Matrix matrix = new Matrix();
    matrix.postScale(MatrixWidth, MatrixHeight);
    
    scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, ScaledWidth, ScaledHeight, matrix, true);
    }
    
    private void prescaleScaledBitmap(Resources resources, int targetResourceID, BitmapInfo newInfo)
    {
    BitmapFactory.Options scaledOpts = new BitmapFactory.Options();
    scaledOpts.inSampleSize = newInfo.sample;
    scaledBitmap = BitmapFactory.decodeResource(resources, targetResourceID, scaledOpts);
    }
    
    private BitmapInfo getOriginalBitmapInfo(Resources resources, int targetResourceID)
    {
    BitmapFactory.Options bitOptions = new BitmapFactory.Options();
    bitOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(resources, targetResourceID, bitOptions);
    
    return new BitmapInfo(bitOptions.outHeight,bitOptions.outWidth);
    }
    
    private BitmapInfo getScaledBitmapInfo(int targetHeight, int targetWidth, BitmapInfo originalBitmapInfo)
    {
    float HeightRatio = targetHeight / (float)originalBitmapInfo.height;
    float WidthRatio = targetWidth / (float)originalBitmapInfo.width;
    
    BitmapInfo newInfo = new BitmapInfo(0,0);
    
    if (HeightRatio > WidthRatio)
    {
    newInfo.scale = WidthRatio;
    newInfo.width = targetWidth;
    newInfo.height = (int)(newInfo.scale * originalBitmapInfo.height);
    } else {
    newInfo.scale = HeightRatio;
    newInfo.height = targetHeight;
    newInfo.width = (int)(newInfo.scale * originalBitmapInfo.width);
    }
    
    newInfo.sample = 1;
    
    int SampleHeight = originalBitmapInfo.height;
    int SampleWidth = originalBitmapInfo.width;
    
    while (true) {
    if (SampleWidth / 2 < newInfo.width || SampleHeight / 2 < newInfo.height) {
    break;
    }
    SampleWidth /= 2;
    SampleHeight /= 2;
    newInfo.sample *= 2;
    }
    
    return newInfo;
        }
    
    }
    

    谢谢!

0 个答案:

没有答案