I am playing through an animation of about 90 images # 480x320 each, and I am wondering with the images not being power of 2, will this be a big performance hit? I am programing for as far back as the iphone 3Gs. Also I am using cocs2d.
Assuming you load all of these images at the start and they are 16 bit images.
Well you will have 512x512x90 = 23,592,960 pixels
With 16 bit images thats 377,487,360 bits.
377,487,360 bits = 45 Megabytes of RAM.
So yes that is a big performance hit.
Let's see...
480x320 image will create a texture of 512x512 (next nearest power of two). 512x512 times 32bit color depth (4 bytes) equals 1 Megabyte. 90 times 1 Megabyte equals 90 Megabytes.
Your biggest problem will be allocating this much memory and caching it. Without caching the animation images, you'll have to load each image every time the animation frame changes. Loading 1 Megabyte from flash memory is pretty darn slow, I'm guessing > 100 milliseconds. So every time a frame changes, your app will stop for a fraction of a second. This will be a problem on the 3GS, and possibly the Retina devices as well if you use Retina images (each 960x640 image then requires 4 Megabytes texture memory).
You can only improve this by using PVR compressed images (use TexturePacker). Even halving texture size to 16 bit will probably not be enough for a smooth animation.
Related
I wish to compress my png sprite textures a bit so they don't take up that much memory as I build for mobile devices. As I use a lot of gif animations this is crucial for my game's performance.
I looked for an answer but the threads I found were more than 1 year old and not about sprites so I figured I ask my version. An image that's 224 KB in size takes up 1.6 MB in Unity with the generate mip maps turned off
So compressing the png sprite textures in my game. How to do that?
Try setting Format to Automatic Compressed.
For this to work on all mobile platforms make sure the initial image has sizes that are power of 2 (actually I think that multiple of 4 should be enough, but just to be on the safe side).
This will lower the quality of the image but should save you some space.
Turning mip map off is again a good idea as mim map increase the size of the image by about 33%.
And one more thing, make sure that Non Power of 2 is set to None, that may be the reason you see an increase in size at the moment.
Importing a set of 80 icons in QML as non-visible images to be used for shader sources (for arbitrary colorization):
property Image action: Image { sourceSize.width: 512; sourceSize.height: 512; source: "icons/action.svg"; mipmap: true; antialiasing: true }
// 79 more of those
I discover that my memory consumption has skyrocketed, from 45 mb to 128 mb, a whooping ~185% increase, thats 83 extra mb for the 80 icons.
It was expected, after all, 512 * 512 * 4 / 1024 / 1024 makes up for exactly 1 mb of memory. However, that cost is not acceptable, especially in the face of targeting mobile phones with the app.
I could reduce the rasterization size, however, I want the icons to be nice and crisp. The icon size itself varies according to the device display, but for optimal user experience it needs to be about an inch or so. Given that most new high end phones are already pushing above 500 dpi, I'd really hate to scale the icons down and have them appear blurry.
Since the SVGs are supposed to be colorized in arbitrary colors, they are in effect simply alpha masks, meaning that all I really need is one of those 4 channels. Unfortunately, QML's Image doesn't seem to offer any sort of control, the SVG is rasterized to a RGBA image.
And indeed, if I
QVector<QImage> imgs;
imgs.reserve(80);
QDirIterator it(":/icons", QDirIterator::Subdirectories);
while (it.hasNext()) {
QSvgRenderer renderer (it.next());
QImage ic(512, 512, QImage::Format_Alpha8);
ic.fill(Qt::transparent);
QPainter pp(&ic);
renderer.render(&pp);
imgs.append(ic);
}
I get the expected modest 20 mb increase in memory usage.
Any ideas how to save on some memory?
2 hours later - good news, first and foremost, a custom QQuickImageProvider works out of the box with QImage::Format_Alpha8, no problems there. Unnecessary channels are eliminated.
But more importantly, I realized that the icons lend themselves very well to distance fields representation. So I now employ 128x128 SDF textures, which scale beautifully to far above 512x512, reducing the memory usage for the icons to the measly 1.25 mb, for a total of 64x reduction of ram usage compared to the initial implementation.
The only downside is the 3-4 seconds (on a Note 3 phone) additional startup, because the distance fields are calculated on startup, but there are remedies for this as well, I might switch to pre-computed SDFs or offload if to shaders, which would be a little more complex, but should reduce the time at least 5-fold.
The thing with the Image component is it appears to render the SVG to a bitmap before it is drawn. Hence the requirement to set sourceSize to force it to render your SVG at different resolutions. This force rendering can lead to poor memory usage and poor performance.
As an alternative, I found a number of components in QML that render SVG perfectly via the icon property.
Item {
width: 256
height: 256
Button {
anchors.centerIn: parent
background: Item { }
icon.source: "https://raw.githubusercontent.com/Esri/calcite-ui-icons/master/icons/biking-32.svg"
icon.width: 256
icon.height: 256
icon.color: "blue"
enabled: false
}
}
Which renders my biking-32.svg at 256x256 resolution in blue:
I have a website using three.js with CanvasRenderer. The renderer's size is set depending on the window size. On an iPad, the size is 1024 x 672 pixels. With this size, I get extremely bad performance (~1 FPS). If I reduce the width to 1023 Pixels, I get about 60 FPS.
Is there any specific reasion why the performance should drop significantly when hitting 1024 pixels? I don't have any issues with this resolution in Firefox.
I have heard about the HTML5 canvas element in some browsers losing a massive amount of performance once a certain number of pixels is being rendered. This would appear to be caching issue with the browser itself. Though the question is still unanswered.
Why does drawImage performance differ greatly with larger than 65776 pixel canvas sources
Render the canvas at a lower resolution and use CSS to scale it up to full HD.
I am building a map system that requires a large image (native 13K pixels wide by 20K pixels tall) to be overlayed onto an area of the US covering about 20 kilometers or so. I have the file size of the image in jpg format down to 23 MB and it loads onto the map fairly quickly. I can zoom in and out and it looks great. It's even located exactly where I need it to be (geographically). However, that 25 MB file is causing Firefox to consume an additional 1GB of memory!!! I am using Memory Restart extension on Firefox and without the image overlay, the memory usage is about 360 MB to 400 MB, which seems to be about the norm for regular usage, browsing other websites etc. But when I add the image layer, the memory usage jumps to 1.4 GB. I'm at a complete loss to explain WHY that is and how to fix it. Any ideas would be greatly appreciated.
Andrew
The file only takes up 23 MB as a JPEG. However, the JPEG format is compressed, and any program (such as FireFox) that wants to actually render the image has to uncompress it and store every pixel in memory. You have 13k by 20k pixels, which makes 260M pixels. Figure at least 3 bytes of color info per pixel, that's 780 MB. It might be using 4 bytes, to have each pixel aligned at a word boundary, which would be 1040 MB.
As for how to fix it, well, I don't know if you can, except by reducing the image size. If the image contains only a small number of colors (for instance, a simple diagram drawn in a few primary colors), you might be able to save it in some format that uses indexed colors, and then FireFox might be able to render it using less memory per pixel. It all depends on the rendering code.
Depending on what you're doing, perhaps you could set things up so that the whole image is at lower resolution, then when the user zooms in they get a higher-resolution image that covers less area.
Edit: to clarify that last bit: right now you have the entire photograph at full resolution, which is simple but needs a lot of memory. An alternative would be to have the entire photograph at reduced resolution (maximum expected screen resolution), which would take less memory; then when the user zooms in, you have the image at full resolution, but not the entire image - just the part that's been zoomed in (which likewise needs less memory).
I can think of two approaches: break up the big image into "tiles" and load the ones you need (not sure how well that would work), or use something like ImageMagick to construct the smaller image on-the-fly. You'd probably want to use caching if you do it that way, and you might need to code up a little "please wait" message to show while it's being constructed, since it could take several seconds to process such a large image.
I am trying to use SpriteSheet to run an animation. My frames are of 320x480 in size each, So I am able to put max 6 frames on the texture image. But my animation consists of frame number ranging from 50 to 200 sometimes, and all are of size 320x480.
But this much number of frames cannot be added on the Texture image as the size is restricted to 1024x1024.
Is there any other approach I can try out. Can I play one animation after the other.And won't it be hampering the performance.
Please, I need suggestions.
Best,
Vaibhav Tekam.
Ugh, you're going way past what the device can handle! You'll have to reconsider what you're trying to achieve and how to achieve it. Let me explain.
Every 1024x1024 texture with 32 bit colors requires 4 MB of memory. If you want a sprite animation consisting of 60 full-screen sprites, you need 10 such textures. That makes 40 MB of memory. Or 120 MB for your upper-case scenario with 180 animation frames.
Keep in mind that the 128 MB RAM memory models of the iOS devices have about 30 MB memory available for your App, at most and under ideal conditions. You will start running into memory issues with only five 1024x1024 textures. The 256 MB devices still have only about 100 MB available for your App.
Since it's supposed to be an animation, it's also not an option to load one texture, and after every 6th image, remove that texture and load the next one. Loading a 1024x1024 texture into memory takes about 1-3 seconds depending on the device. Your App will be irresponsible during that time.