10

Is there any reason why an SKTexture appears to ignore the .scale of an image when constructed via textureWithImage:?

I have one image resource available, "retina_image@2x.png"

When I try to create a texture while creating a UIImage first:

UIImage* image = [UIImage imageNamed:@"retina_image"];
SKTexture* texture_image = [SKTexture textureWithImage:image];
NSLog(@"image size %@, scale %f", NSStringFromCGSize(image.size), image.scale);
NSLog(@"texture from image, size %@", NSStringFromCGSize(texture_image.size));

I get the following result:

image size {50, 50}, scale 2.000000
texture from image, size {100, 100}

While I would expect to get

image size {50, 50}, scale 2.000000
texture from image, size {50, 50}

As the size of the image (in points) is 50x50
This is also what you get when you construct the texture with the resource directly:

SKTexture* texture_named = [SKTexture textureWithImageNamed:@"retina_image"];
NSLog(@"texture named, size %@", NSStringFromCGSize(texture_named.size));

gives the following output (as expected):

texture named, size {50, 50}

This suggests SKTexture ignores the scale property when determining its own size when constructed form an image, while properly respecting the scale when constructed from the imagename.
Is this expected behaviour?

(obviously in my real code I create the UIImage I want to use in a texture programmatically and not via imageNamed)

Edit: This is a (confirmed) bug in SpriteKit, fixed in iOS8

Pieter
  • 17,435
  • 8
  • 50
  • 89

3 Answers3

9

I've found this too and believe it's a bug. Not sure how Apple are going to rectify this as it could break existing code.

My workaround is to read the scale of the UIImage and then set the scale of the SKSpriteNode to 1.0 / scale. You need to do this for both the x and y scales of the SKSpriteNode.

user3432827
  • 106
  • 1
  • 2
  • 1
    I believe so too, I've filed a bugreport till now the only response I got was "check again in 7.1" when it was released (bug is still there), I'll keep this updated if I have more news – Pieter Mar 18 '14 at 11:17
  • 1
    The bug is fixed in iOS8, you get the expected result now (so in my above example everything would report as {50,50}) – Pieter Jun 16 '14 at 15:26
  • FWIW, I just discovered this bug on Mavericks. It seems to be fixed on Yosemite. – sam Aug 12 '14 at 20:26
  • 2
    And it's likely a problem because "scale" in the UIImage world and in the SpriteKit world are two different things. A higher scale on a UIImage makes the image "smaller" on screen, it's the opposite with SK... You would never be able to use the equally spelled "scale" of the two APIs interchangeably without converting like in this answer. – Jonny Feb 01 '16 at 07:30
  • Oups! I just realized we can load it as an UIImage first, then use `[SKTexture textureWithImage:theuiimage];`. How could I miss that constructor of SKTexture? It correctly uses the scale too! – Jonny Feb 03 '16 at 10:21
0

From apples doc's of UIImage

On a device running iOS 4 or later, the behavior is identical if the device’s screen has a scale of 1.0. If the screen has a scale of 2.0, this method first searches for an image file with the same filename with an @2x suffix appended to it. For example, if the file’s name is button, it first searches for button@2x. If it finds a 2x, it loads that image and sets the scale property of the returned UIImage object to 2.0. Otherwise, it loads the unmodified filename and sets the scale property to 1.0. See iOS App Programming Guide for more information on supporting images with different scale factors.

But according to textureWithImageNamed:.

The new texture object is initialized with the name of the image file and then control returns immediately to your game. Sprite Kit loads and prepares the texture data when it is needed by your game.

When loading the texture data, Sprite Kit searches the app bundle for an image file with the specified filename. If a matching image file cannot be found, Sprite Kit searches for the texture in any texture atlases stored in the app bundle. If the specified image does not exist anywhere in the bundle, Sprite Kit creates a placeholder texture image.

From the above textureWithImageNamed: and SKTexture doesn't care about scaling with device.(retina image).

Mani
  • 17,549
  • 13
  • 79
  • 100
  • But if you look at the output of my NSLog, it apparently does. `textureWithImageNamed:` gets a size of {50,50}, taking the scale into account – Pieter Jan 07 '14 at 10:50
  • Ya In this first `SKTexture` read scale from `UIImage` in which image scale is 2. But in second it won't create `UIImage`. Just load image data from file and remain scale is 1 for `SKTexture`. – Mani Jan 07 '14 at 10:54
  • 1
    The opposite of what you say happens, the first ignores the scale of the image, resulting in an image twice the expected size, while the second properly takes the scale into account. (you say "From the above textureWithImageNamed: doesn't care about scaling with device.", but my example shows that that function DOES care about scaling (and properly scales), an image with 100x100 pixels should result in an image with 50x50 size, scaling 2, when used as retina) – Pieter Jan 07 '14 at 11:07
  • @Pieter I think, I've misunderstood :( – Mani Jan 07 '14 at 11:12
  • I thought so too, but wondered if maybe I was misunderstanding something ;) Glad we cleared that up and thanks a lot for trying to help making sense of this. – Pieter Jan 07 '14 at 11:17
  • it does not ignore the scale of the uiimage. 50x50 times 2 gives you 100x100 so the texture created did take scaling into account. It seems you're simply thinking about this differently, expecting the opposite result. Would be helpful to know what files you have in the bundle, retina-image or retina-image@2x or both? – CodeSmile Jan 07 '14 at 11:23
  • @LearnCocos2D Ya I've misunderstood. Now I've cleared after Pieter's comment. Did you see above comments? thanks LearnCocos2D. – Mani Jan 07 '14 at 11:29
  • they confused me even more, not sure i'm correct after i commented now :) – CodeSmile Jan 07 '14 at 11:31
  • @LearnCocos2D I'm (obviously) not here to confuse people ;) clarified the question, hopefully it makes sense now – Pieter Jan 07 '14 at 18:05
0

I have the same behavior with textures from atlas created from a dictionary. On iOS 8.3

How to force SKTextureAtlas created from a dictionary to not modify textures size?

Community
  • 1
  • 1
Dominique Vial
  • 3,729
  • 2
  • 25
  • 45