在画布

时间:2018-06-02 09:13:28

标签: c# android xamarin.android surfaceview

我正在创建一个纸牌游戏,为此我创建了一个自定义表面视图,其中图像正在加载。由于图像是从互联网上下载的,因此它们的大小不同,在屏幕上看起来很糟糕。我想在这里做两件事。

  1. 加载固定大小的图像或动态调整图像大小。
  2. 从屏幕底部向上绘制图像。
  3. 对于第一点,我使用CreateBitmap方法,但得到以下异常。

    java.lang.OutOfMemoryError: Failed to allocate a 1915060280 byte allocation with 4194304 free bytes and 123MB until OOM error
    

    为了解决我想到使用基于questionthis的Glide / Picasso的问题,但我发现Glide / Picasso仅在imageview上加载图像,但我不知道有任何imageview,我只在linearlayout内有一个自定义的surfaceview。

    对于第二点,我使用了图像的旋转。以下是该代码。

      public  void Render(Canvas paramCanvas)
        {
    
            try
            {
                // paramCanvas.DrawColor(Android.Graphics.Color.Blue);
    
    
                int i = 0;
                Down_Card_Gap = 0;
                foreach (Cards localcard in FaceDownDeck.ToList())
                {
    
    
                    Bitmap localimage = BitmapFactory.DecodeResource(Resources, localcard.GetImageId(context));  
                    Bitmap rotatedimage = RotateBitmap(localimage, 180);
                    paramCanvas.DrawBitmap(rotatedimage, (Screen_Center_X - Card_Width / 2)+Down_Card_Gap, (Screen_Height - Card_Height), null);
                   //   paramCanvas.DrawBitmap(localimage, (Screen_Center_X - Card_Width / 2), (Screen_Center_Y - Card_Height), null);
    
    
                    if (i++ == 7)
                    { break; }
                    if (Down_Card_Gap > 0)
                    {
                        Down_Card_Gap += Card_Width / 2; 
                    }
                    else
                    {
                        Down_Card_Gap -= Card_Width / 2;
                    }
                    Down_Card_Gap *= -1;
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.ToString());
            }
        }
    
        private Bitmap RotateBitmap(Bitmap localimage, float angle)
        {
             Matrix matrix = new Matrix();
            matrix.PostRotate(angle);
            matrix.PostScale(Card_Width, Card_Height);
            Bitmap resized= Bitmap.CreateBitmap(localimage, 0, 0, localimage.Width, localimage.Height, matrix, true);
            localimage.Recycle();
            return resized;
        }
    

    我想知道这是一种正确的方法,还是有更好的方法来实现这一功能。

1 个答案:

答案 0 :(得分:0)

  

加载固定大小的图像或动态调整图像大小。

关于固定尺寸和调整大小,您可以参考this,找到decodeFile方法:

   protected Bitmap decodeFile(File f) {
        try { 
            //decode image size 
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f), null, o);

            //Find the correct scale value. It should be the power of 2. 
            final int REQUIRED_SIZE = 150;
            int width_tmp = o.outWidth, height_tmp = o.outHeight;
            int scale = 1;
            while (true) { 
                if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
                    break; 
                width_tmp /= 2;
                height_tmp /= 2;
                scale *= 2;
            } 

            //decode with inSampleSize 
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize = scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        } catch (FileNotFoundException e) {
        } 
        return null; 
    } 

您可以看到,它使用BitmapFactory.Options.inJustDecodeBounds= true预加载位图,并缩放位图。您也可以参考official document。阅读this以压缩位图的质量。

除此之外,您还需要考虑图片缓存。This talks about how to build an efficient memory cache for bitmaps.