Bug with saveImage() on retina devices

I’m working on getting Texture Packer sprite sheet support into CocosCodea, and as one of my tests I’m downloading a .plist and texture using http.request() from my public dropbox folder. Once the texture is downloaded, I’m using saveImage() to save the texture to my Documents folder. According to the Codea reference, when using saveImage() on retina iPads, a @2x version and a 50% scaled non-retina version are supposed to be saved, however that does not appear to be the case here: only a 50% scaled non-retina version is being saved, and the @2x version is strangely absent.

The odd thing is, if I use setContext() to render the texture into a new image, and then call saveImage(), both versions are saved.

Looking at the runtime, it appears that the problem is that a retina version is not saved out unless a) the device is a retina device, and b) the image->scaleFactor is 2, which is apparently not the case with the image I have downloaded for some reason.

@toadkick that’s an interesting problem. The reason we don’t save an @2x on non-retina devices is because we are under the assumption that we do not have a retina graphic (an @2x is never loaded from a sprite pack, or created from an image on a non-retina device).

However we didn’t envisage the case of downloading an @2x image on a non-retina device. I’m not sure how to deal with this and would be happy to hear your thoughts.

Well, downloading and saving an image on a non-retina device isn’t really an issue, Codea behaves as expected in that case. The issue I’m running into is that on my retina iPad, I was expecting Codea to save the downloaded image as the @2x image, and to create a 50% scaled image as the non-@2x image. Stepping through the runtime, it is saving a 50% scaled version of my image, but since a downloaded image always seems to have a scale factor of 1 (btw, how is this scale factor determined?), it is not saving the image as-is as a @2x version. In other words, Codea always scales down my image and saves it, but doesn’t save the raw image with an @2x suffix. Other than always saving the image as an @2x version on retina devices, regardless of the image’s scale factor, or providing an optional flag as a param to saveImage() to force it to ignore the image’s scale factor, I’m not really sure what else could be done. Also, It might not have been a problem if Codea didn’t scale the image down before saving the non-@2x version, but as it is now, on a retina device, any image I download and save will be scaled down to 50% whether I want it to or not (I say “might” because I’m not entirely sure that would solve my issue, but at least it wouldn’t exacerbate it as it does now).

Scale factor is determined automatically by iOS — if you attempt to load a local image file, and an @2x version also exists, the @2x version is automatically loaded and the scale factor is set to 2.

The problem is that iOS has no idea about remote images. So all remote images are assumed to be at a scale factor of 1.

Okay right, that makes sense. So does it make sense then, if on a retina device, to always have saveImage() assume that we want the saved image to be an @2x version? Can you see a problem with that? As it stands now, it already will always generate an @2x version for any sprite saved from a sprite pack or generated from the image() command, so I don’t think there would be an issue with just removing the check for image->scaleFactor == 2 when determining whether or not to generate an @2x version, but I’m not entirely sure this wouldn’t cause other problems.

EDIT: turns out I was wrong (big surprise there) about Codea saving out the image at 50%. I tried implementing the idea I suggested above, but my sprite sheet sprites are still rendering using the wrong texture coordinates. I’ll have to investigate further to figure out why…I’m guessing it has something to do with the coordinates being scaled.

Alright, so, the good news is, I’ve been able to get Texture Packer generated sprite sheets to work with CCSpriteBatchNode in CocosCodea. The bad news is, for retina devices, there’s no way to specify whether to use a retina sprite sheet or a non-retina sprite sheet. cocos2d-iPhone/iOS handles this by automatically loading any file (not just images) with an @2x extension on retina devices, so normally you would supply a SpriteSheet.plist, SpriteSheet.png, SpriteSheet@2x.plist, and SpriteSheet@2x.png, and cocos2d chooses the correct one. Since Codea doesn’t have any concept of file i/o, there’s no way to do this :frowning: My hope is that if/when Codea does provide file i/o, it takes this into account, and will automatically load files with @2x extensions on retina devices. Until then, it looks like this will just have to wait :frowning:

@toadkick I’ll keep in mind to check for equivalent files with an @2x extension for all file types, not just images, when IO is implemented (also @2x versions will be hidden, as they are with sprites).

Thanks @Simeon :slight_smile: