Here is my question. Empty cocos2d project has weight 3.38 MB (standart "Hello world"). I check it by the Profile->Allocate Kit.
Now I have a .png image with a size 382x512 pixels. It will be extended to 512x512 in the RAM (2 degree). I add this file to project just like this:
CCSprite* sprite = [CCSprite spriteWithFile:#"mySprite.png"];
And now the most interesting. "mySprite.png" has a 8888 pixel format, i.e. it must occupie 512x512 = 0.5*0.5 = 0.25 MB * 4 = 1 MB (4 - 4 bytes from the pixel format). Am I right? I think so, but when I checked how much the project weight, I found that the project has the 5,54 MB, i.e. "mySprite" has oppupied > 2 MB in the RAM.
What am I doing wrong? And how can I fix it? :/
Thx.
I remember reading somewhere about this. I went through the cocos2d forums and found this post:
http://www.cocos2d-iphone.org/forum/topic/4510
You should check Karl's explanation which seems to make sense for me:
It takes up 8MB because the loader routine uses the OS to load a UIImage, and then copies the pixels to a newly allocated buffer in a GL-friendly 32-bit format. This means that your 1024x1024 image will take 8MB to load, but 4MB of that should be freed once the UIImage gets released...
Related
I am making a game with a large number of sprite sheets in cocos2d-x. There are too many characters and effects, and each of them use a sequence of frames. The apk file is larger than 400mb. So I have to compress those images.
In fact, each frame in a sequence only has a little difference compares with others. So I wonder if there is a tool to compress a sequence of frames instead of just putting them into a sprite sheet? (Armature animation can help but the effects cannot be regarded as an armature.)
For example, there is an effect including 10 png files and the size of each file is 1mb. If I use TexturePacker to make them into a sprite sheet, I will have a big png file of 8mb and a plist file of 100kb. The total size is 8.1mb. But if I can compress them using the differences between frames, maybe I will get a png file of 1mb and 9 files of 100kb for reproducing the other 9 png files during loading. This method only requires 1.9mb size in disk. And if I can convert them to pvrtc format, the memory required in runtime can also be reduced.
By the way, I am now trying to convert .bmp to .pvr during game loading. Is there any lib for converting to pvr?
Thanks! :)
If you have lots of textures to convert to pvr, i suggest you get PowerVR tools from www.imgtec.com. It comes with GUI and CLI variants. PVRTexToolCLI did the job for me , i scripted a massive conversion job. Free to download, free to use, you must register on their site.
I just tested it, it converts many formats to pvr (bmp and png included).
Before you go there (the massive batch job), i suggest you experiment with some variants. PVR is (generally) fat on disk, fast to load, and equivalent to other formats in RAM ... RAM requirements is essentially dictated by the number of pixels, and the amount of bits you encode for each pixel. You can get some interesting disk size with pvr, depending on the output format and number of bits you use ... but it may be lossy, and you could get artefacts that are visible. So experiment with limited sample before deciding to go full bore.
The first place I would look at, even before any conversion, is your animations. Since you are using TP, it can detect duplicate frames and alias N frames to a single frame on the texture. For example, my design team provide me all 'walk/stance' animations with 5 pictures, but 8 frames! The plist contains frame aliases for the missing textures. In all my stances, frame 8 is the same as frame 2, so the texture only contains frame 2, but the plist artificially produces a frame8 that crops the image of frame 2.
The other place i would look at is to use 16 bits. This will favour bundle size, memory requirement at runtime, and load speed. Use RGBA565 for textures with no transparency, or RGBA5551 for animations , for examples. Once again, try a few to make certain you get acceptable rendering.
have fun :)
6/4/14
I need to (if possible) create a surface in SDL 1.2 where the bpp = 1. bpp is Bits Per Pixel.
I'm working in 100% black and white, the 'surface' size is so ridiculously large my physical memory is bottle-necking me.
I have 4GB of ram, and the program needs to run on budget machines, meaning 2-4 gigs.
I've been using a color depth of 8; I imagine I'm wasting about 3/4 of my memory realistically?
I'm saving the surface as a .bmp file, which is supposed to support a black/white format where bpp = 1.
Is there any way to lower the bpp in SDL or should I look for an alternative?
6/5/14
I hit a bottle-neck on my machine at about 39000x39000 pixels at a color depth of 8 bits. Because SDL stores surfaces in physical memory, I'm running out of RAM. Processing power is not an issue as I'm rendering a still image.
I'm hoping to double that resolution, but I'll take what I can get.
Yes I can potentially split the image into multiple files, but because it will be high-res laser printed at a later date, it will have to be open as a single file then anyways. The goal is to package the program as a single unit, not requiring additional steps to stitch and convert the images later in another program.
SDL and c++ in general don't seem to have support for single bit variables (bool not included), so assigning a color value to a 1 bpp pixel using SDL is beyond me.
I am working on memory measurement of a little cocos2d demo, the demo's task is to add one png image into cocos2d texture cache, the monitors I use are Allocations and Activity Monitor in Instruments.
The test device is ipod touch4.
In order to find the relationship between app's memory and live bytes of allocations, I design two test scenarios.
The first scenario is to add texture into cache, and remove it immediately. Test Code is below:
CCTextureCache* cache = [CCTextureCache sharedTextureCache];
CCTexture2D* tex = [cache addImage:#"textureatlas_RGBA8888.png"];
[cache removeTexture:tex];
The second scenario is to add texture into cache, but leave it in cache. Test Code is below:
CCTextureCache* cache = [CCTextureCache sharedTextureCache];
CCTexture2D* tex = [cache addImage:#"textureatlas_RGBA8888.png"];
The size of png file is 270KB, and it has 1024 * 1024 size with 32-bit colour depth, its texture will take up 1024 * 1024 * 4 bytes (32 bits) = 4096 KB in cache.
Test Results are following:
The first scenario's result:
The live bytes will raise to 6.16MB during adding image into cache, in a while, it will return back to a little more than 2.08MB.
Until the app finish all operations, the level of live bytes will keep stable. At this time, the real mem in Activity Monitor is 11.61MB.
The second scenario's result:
The graph of the second test is similar as the first one, however, when the live bytes is stable, the real men is 15.62MB.
My first question is:
Why the graphs are almost same even I don't remove texture in cache in the second scenario? doesn't the Allocations consider the texture as live bytes in memory?
The second question is:
As I learned from this article: How to optimize memory usage and bundle size of a Cocos2D app (http://www.learn-cocos2d.com/2012/11/optimize-memory-usage-bundle-size-cocos2d-app/), since the png file will be converted to UIImage firstly, and then add to texture cache, one 1024*1024 texture use 4MB of memory, while loading it will use 8MB of memory for a short time, why I cannot observe it in the tracking graph of Allocations?
Thanks for your help.
I have been searching the cocos2d forum but I do not understand some of the concepts the people are using. In my game I am having to load over 100 images to use as an animation for my main menu but the problem that I am having is these images take about 3 to 5 seconds to load and then my game starts up. The animation runs great after the images are loaded but it's the loading that is the problem. I would use sprite sheets but the images are to big so I have to load them separately. So should I make a loading screen to load all of these images in first and if so how is the best way to implement this? This is my first time of trying to do something like this.
#Stephen : Two ways to do this. With TexturePacker you can create a .tps file, one for each source image, then under File->Export Image. Set the geometry to 1024x1024 for your images. Specify .pvr format, enable pre-multiplied alpha, and toy with dithering (this may actually benefit some textures, ie improve on .png's). You could also probably benefit from RGBA4444 for menus (gain on memory required, with no significant loss on rendered quality).
You can also use the builtin texturetool as follows:
before you do this, you must convert toto.png to a POT file (1024x1024) in your case, with photoshop for example.
MrEvil:pvrCenter$ /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/texturetool -m -f PVR -e PVRTC toto.png -o toto.pvr
MrEvil:pvrCenter$ gzip toto.pvr
this gives excellent compressions after a gzip (from 691Kb png to 295Kb).
I used texturetool because i can script that in shell, and process a whole lot of images with a single command (play D3 while the box churns out the images :) ).
EDIT 1 : some info on packing and file sizes.
ok, i started with one of my own 960x640 8 bits PNG, 691 Kb.
load it TexturePacker, set format to RBGA8888, 1024x1024, i get 766 Kb (this gives my my POT file).
export to RGBA8888 as a .pvr.ccz, 996 Kb.
export to RGBA8888 as a .pvr.gz, 1.001 Mb
export to RGBA4444 as a .pvr.ccz, 193Kb.
if i use texturetool on the 766 Kb file, then gzip the file 305Kb (RGBA8888). I cant really explain the difference between 305Kb and 996 Kb. It could be related to the dithering processing by TexturePacker, not certain.
Yes, definitely use a texture atlas (sprite sheet is not the correct term but means the same thing). A great tool for that is TexturePacker.
A texture atlas will save time when loading, and conserve memory. You can also try out different image color depth and compression options to further improve memory usage and loading times, but many options will affect image quality to a varying degree and depending on your images.
Btw, how big are these images? Assuming each is 512x512, and you load 100 of them, they'll consume 100 MB of memory. I mention that because this is often overlooked, and file sizes on disk are a fraction of what the images consume as textures.
In my Game i'm loading around 13-15 Png's which include few sprite sheets(6-7) of 2048x2048 dimension and others 1024x1024 and some 512x512.
and now i'm facing the huge memory warning.
There is no way for me to reduce the number of sprite sheets in my game :(.
So, m thinking to convert all the 2048x2048 sprite sheets from png to pvr.ccz format.
Is that the optimal solution or Some thing else is there, which i'm completely missing?
Any help would be highly appreciated.
If all the PNG/texture images have to be available for each frame, then each will be stored uncompressed in texture memory and thus the memory problem. No GPU (to my knowledge) can render directly from a compressed PNG (or JPG for that matter) image.
The only options are to drop to, say, 4444 colour or to use PVRTC (probably at 4bpp).
[Update: WRT PVRTC, I'm assuming this is an iphone game.]