渲染大位图的一个小区域是费时 [英] Rendering a small region of large Bitmap is time consuming

查看:117
本文介绍了渲染大位图的一个小区域是费时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下code。

this.getGame().getGraphics().drawBitmap(Assets.playScreen_LaserBeamAnimation, new Rect(0, 0, 100, 750), new Rect(0, 0, 100, 750), null);
this.getGame().getGraphics().drawBitmap(Assets.playScreen_LaserBeamAnimation, new Rect(0, 200, 10, 800), new Rect(0, 0, 200, 600), null);

第一渲染声明约需 0.6 - 1秒渲染。
围绕第二个 1毫秒

位图大: 968 KB 并装有以下code:

The Bitmap is large: 968 KB and is loaded with the following code:

public Bitmap readAssetsBitmap(String filename) throws IOException {
        try {
            BitmapFactory.Options options = new BitmapFactory.Options(); 
            options.inPurgeable = true;
            Bitmap bitmap = BitmapFactory.decodeStream(assets.open(filename), null, options);
            if(bitmap == null) {
                WSLog.d(Game.GAME_ENGINE_TAG, this,"File cannot be opened: It's value is null");
                throw new IOException("File cannot be opened: It's value is null");
            }
            else {
                WSLog.d(Game.GAME_ENGINE_TAG, this,"File successfully read: " + filename);
                return bitmap;
            }
        } 
        catch (IOException e) {
            WSLog.d(Game.GAME_ENGINE_TAG, this,"File cannot be opened: " + e.getMessage());
            throw new IOException("File cannot be opened: " + e.getMessage());
        }

    }

我期望图像的读取和设置位图需要一段时间,但是渲染它的一个小区域不应该采取这么长时间(而神秘,只有第一个渲染调用)。

I expect the reading of the image and setting the Bitmap to take some time, however rendering a small region of it should not take so long (and mysteriously it is only the first render call).

我如何避免先渲染时间这么长?

How do I avoid the first render to take so long?

注意:它不具有与缩放(我相信)做任何事情

推荐答案

TL; DR 加载和渲染图形实际上是一个相对昂贵的集(内部)操作,先加载到内存中,然后进入在ARM CPU的图形模块当它第一次呈现到屏幕上。此外,动画GIF扩展成每个动画帧使得它颇有几分比你想象的更大的一组图片,之一。为了提高速度,可以考虑减小动画的大小(像素,帧数),或者迫使GIF到显存早些时候,以避免第一帧暂停。

TL;DR Loading and rendering graphics is actually a relatively expensive set of (internal) operations, first loading into memory then into the graphics module of the ARM CPU when it is first rendered to screen. Further, the animated GIF is expanded into a set of images, one for each animation frame making it quite a bit larger than you may think. To improve speed, you might consider decreasing the animation size (pixels and number of frames), or forcing the GIF onto the graphics memory earlier to avoid the first-frame pause.

有很多事情Android已经在内部完成渲染游戏显卡之一赫克,特别是如果你有一个GIF动画:

There is one heck of a lot of things Android has to do internally to render game graphics, especially if you have a GIF animation:


  • 加载从图像(相对较慢)RAM

  • 解压文件

  • 地图256颜色模式为RGBA空间

  • 从GIF文件的图像增量生成动画的每一帧

  • 用定时器创建一个线程的GIF的不同帧之间切换

现在我们已经在CPU中的存储器中的图像(实际上是一组帧)。需要注意的是一个非常小的GIF有很多框架可以在内存中成为一个非常大的 - Android已经有一个全尺寸的图像为您的GIF每一帧。另外,256位色彩模式扩展为RGBA内部,所以你必须每像素4个字节。

Now we have an image (actually a set of frames) in the CPUs memory. Note that a very small GIF with a lot of frames can become a very large in memory - Android has to have a full-sized image for each frame in your GIF. Also the 256 bit colour model is expanded into RGBA internally, so you have 4 bytes per pixel.

就拿一个GIF(128×128像素)的动画就可以了(32x32像素)的小形状。让我们进一步假设你有动画100步 - 这可能是10K左右,根据背景是多么简单。然而,在存储器扩大,在动画的每个帧是4x128x128 = 64KB。你有100帧,这样你的内存大小为6MB。

Take for example a GIF (128x128 pixels) with a small shape animated on it (32x32 pixels). Let's further suppose you have 100 steps in the animation - this might be 10k or so depending on how simple the background is. However, expanded in memory, each frame in the animation is 4x128x128 = 64kB. You have 100 frames, so your in-memory size is 6MB.

下一页:


  • 如果使用3D,我们必须将图像编译成图形模块内部的纹理格式

  • 流的数据到图形内存(这需要一个令人惊讶的很长一段时间 - 这就是为什么大多数的3D游戏有那些载入中...游戏片段之间的页面)

  • 更改从图形模块的格式图像的实际画面的色彩深度(如RGB格式具有24位色彩,但往往LCD显示屏具有18或20位色深,该显卡拥有将图像转换且通常引入了抖动,以模拟其他颜色)

一旦图像(实际上是一堆帧)被加载到图形模块,然后事情就很快。

Once the image (which is actually a bunch of frames) is loaded into the graphics module, then things get fast.

好了,你能怎么办呢?下面是一些建议:

OK, so what can you do about it? Here are some suggestions:


  • 降低的GIF的像素尺寸,或减少在动画
  • 帧的数量
  • pre加载

  • 平铺图像,如果大

减小尺寸的GIF可以显著减少内存使用,且会降低Android的花费帧推入图形模块,并编译成纹理成本的时间。这样做的缺点是,你可能没有修改图形的权限。

Reducing the size of the GIF could reduce the memory usage significantly, and that will reduce the time Android takes to push the frames into the graphics module and the cost to compile into textures. The downside to that is you might not have the authority to modify the graphics.

pre-装载推图像插入图形模块早些时候迫使在游戏加载阶段渲染。该图像可能是离屏(设置为隐藏窗口)后面或者通过设定低Z顺序或在1像素区域的顶层。

Pre-loading pushes the image into the graphics module earlier by forcing a render during the game loading phase. The image might be off-screen (setting the window as hidden) or behind a top-layer by setting a low Z-order or in a 1 pixel region.

平铺在<一个讨论href=\"http://stackoverflow.com/questions/16343040/zooming-and-loading-very-large-tiff-file/16382498#16382498\">my回答类似的问题)。以谷歌地球的最极端的例子 - 这个用砖(在任何给定的分辨率)为地球上的每一个领域。要渲染只是你感兴趣的一点,谷歌地球上有只加载那些要显示的瓷砖。因为瓷砖很小,可能加载速度不够快。然而,在你的情况下,你可能有一个GIF动画,所以这是行不通的。平铺动画可能不实际或可能导致文物或延迟渲染图像的部分。

Tiling is discussed in my answer to a similar question). Take Google Earth as the most extreme example - this uses tiles (at any given resolution) for every area on earth. To render just the bit you are interested in, Google Earth has to load only the tiles that are to be shown. Because the tiles are small, they load fast. However, in your case you may have a GIF animation, so that's not going to work. Tiling an animation might not be practical or might lead to artefacts or delays in rendering portions of the image.

这篇关于渲染大位图的一个小区域是费时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆