Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 跨多个设备手动缩放位图的性能_Java_Android_Bitmap_Scaling - Fatal编程技术网

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

Java 跨多个设备手动缩放位图的性能,java,android,bitmap,scaling,Java,Android,Bitmap,Scaling,我正在开发一款Android游戏,它的图像资源非常丰富。我面临的挑战之一是,我需要手动缩放图形以匹配不同的屏幕大小。不允许Android自动缩放的原因是,游戏依赖于图形不被拉伸或扭曲。我可能会在每次屏幕按下时切换3-4个位图,所以性能是关键(我已经设置了一个缓存操作来帮助实现这一点) 在考虑了这个问题和Android设备的多样性后,我决定采用以下方法,以尽可能多的设备为目标: 制作特定密度的图形(通过dev.android.com中列出的其他建议) 不要为不同的屏幕大小制作多个版本的图像,而是创

我正在开发一款Android游戏,它的图像资源非常丰富。我面临的挑战之一是,我需要手动缩放图形以匹配不同的屏幕大小。不允许Android自动缩放的原因是,游戏依赖于图形不被拉伸或扭曲。我可能会在每次屏幕按下时切换3-4个位图,所以性能是关键(我已经设置了一个缓存操作来帮助实现这一点)

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

  • 制作特定密度的图形(通过dev.android.com中列出的其他建议)
  • 不要为不同的屏幕大小制作多个版本的图像,而是创建一个覆盖所有目标屏幕的非常大的图像,并使用手动缩放缩小其大小以匹配设备
  • 到目前为止,这种方法进展顺利,但我需要从自定义BitmapScaler类中挤出更多性能。我已利用此处找到的代码库来满足自己的需要:

    说到这里,我的问题是:有人对我解决屏幕命运/屏幕大小问题的方法的可行性有任何评论吗?我知道我在这里交易业绩是为了方便。有谁能建议一种方法,在我的位图缩放操作(如下)中挤出更好的性能

    公共类位图缩放器{
    私有位图缩放位图;
    公共位图getScaledBitmap()
    {
    返回缩放位图;
    }
    /*重要注意事项:
    *Android的位图缩放过程并不是一个简单的过程
    *为了帮助保留手机内存,您需要执行以下几个步骤:
    *
    *1.解码目标资源,但使用inJustDecodeBounds选项。这允许您“采样”
    *资源,而不会实际导致加载整个资源的命中。如果设置为true,解码器将返回null
    *(无位图),但out…字段仍将设置,允许调用者查询位图而无需分配
    *它的像素的内存。
    *2.确定位图的新特性,特别是比例和样本。如果样本大小设置为大于1的值,
    *请求解码器对原始图像进行二次采样,返回较小的图像以节省内存。样本大小为数字
    *与解码位图中的单个像素相对应的任意维中的像素数。例如,inSampleSize==4返回值
    *图像的宽度/高度为原始图像的1/4,像素数为1/16。任意值宽度比)
    {
    newInfo.scale=宽度比;
    newInfo.width=targetWidth;
    newInfo.height=(int)(newInfo.scale*originalBitmapInfo.height);
    }否则{
    newInfo.scale=高度比;
    newInfo.height=目标高度;
    newInfo.width=(int)(newInfo.scale*originalBitmapInfo.width);
    }
    newInfo.sample=1;
    int SampleHeight=原始AlbitMapInfo.height;
    int SampleWidth=originalBitmapInfo.width;
    while(true){
    if(采样宽度/2
    谢谢

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