SourceWidth and Height are not being respected in Trimmed Image Sheet

I’ve created an image sheet using TexturePacker. The images are trimmed (rectangles and other shapes) in TexturePacker but are technically 64x64. I want the untrimmed images to be square because they are being used as tiles. The problem is when I call

local image = display.newImageRect(displayGroup, imageSheet, frame, 100, 100)

I get a stretched out image instead of the well proportioned square that I designed. Here is a sample of my sheetinfo.lua

local SheetInfo = {} SheetInfo.sheet = { frames = { { -- image\_1 x=44, y=0, width=64, height=45, sourceX = 0, sourceY = 11, sourceWidth = 64, sourceHeight = 64 }, --etc --etc }, sheetContentWidth = 164, sheetContentHeight = 224 }

Has anyone else experienced this? I could do a workaround to get the image’s actual width and height and scale as necessary to keep proportions but that just defeats the purpose of designing everything to fit in a neat square. This would also introduce rounding errors and images that are supposed to line up seamlessly might have gaps.

Anyone?

What happens if you try and use display.newImage() instead?

Hi Rob, using display.newImage yields the same result. Setting square dimensions for a rectangular piece still causes it to be stretched out. Either way, if I used newImage I would lose out on the benefits of dynamic content scaling that newImageRect provides.

It seems that Corona accounts for positioning of images with trimmed transparent pixels but doesn’t account for the actual dimensions. But what’s the point of having sourcewidth and height if it only affects the position? Corona should do the math behind the scenes to produce an image with the same proportions of the untrimmed image relative to the sourcewidth and height. Otherwise, how else are you supposed to create imagesheets for tiled assets? I can leave the images untrimmed but that takes up unnecessary texture memory.

Can you put together a simple test case that demonstrates the problem?

Hi Vince,

I don’t understand this statement:

“The images are trimmed (rectangles and other shapes) in TexturePacker but are technically 64x64.”

How can a “rectangle” be “technically 64x64” but not be a square? I would need to see your image sheet to understand what you’re attempting to do. This may be a legitimate Corona issue, but many of these cases stem from an improper output setting from TexturePacker.

Best regards,

Brent

@Rob, yes I’ll prepare a simple use case.

@Brent, imagine sections of a track being placed on a grid. The straight pieces are rectangular but techincally each cell in the grid is 64x64. So each png, untrimmed, is a 64x64 square. That way I can just call newImageRect with width and height equal to the size of the cell and not worry about the actual dimensions of the object. See the attached image for an example of how each png is a square.

Hi Vince,

I see what you’re saying, but “sourceWidth” and “sourceHeight” are only for positioning purposes (because if you’re animating a sprite, for example, not all frames will always be the same size). Your image sheet frames are what you’ve made them to be in the trimmed sense… so a thinner horizontal piece will not be 64x64, but probably more like 64x42 (just guessing on that).

If you’re positioning all of these pieces as “tiles” then don’t they all share the same center position related to their 64x64 “tile” on an imaginary grid? If so, can’t you just position them there no matter what their actual dimensions are?

Brent

@Brent

The issue isn’t the positioning. It’s the dimensions. Once the rectangular piece is trimmed now I have to know what the actual dimensions are to keep the image proportional when I insert each piece into the grid. So for example, instead of just calling this for every piece

display.newImageRect(blah,"frame1", 64, 64) display.newImageRect(blah,"frame2", 64, 64)

I now have to call

display.newImageRect(blah,"frame1", 64, 42) display.newImageRect(blah,"frame2", 42, 64)

In order to keep certain pieces from being stretched out in the x or y direction.

I can’t be the only person who wants to trim their tiled assets in an image sheet to save texture memory. How do people normally handle this?

Hi Vince,

TexturePacker itself is doing the “processing” here, and it outputs all of the frame-related information for you. So, if you want to get fully dynamic image sizes for newImageRect(), and you don’t know them in advance because you designed them on a 64x64 pixel “tile” with surrounding transparency, you should probably retrieve the table of frame info that TP gives you, and then dig down into its table structure to get the exact width and height.

So, think of it like this. At the end of that TP file you get, you’ll see something like this:

[lua]

function SheetInfo:getSheet()

    return self.sheet;

end

function SheetInfo:getFrameIndex(name)

    return self.frameIndex[name];

end

return SheetInfo

[/lua]

It returns “SheetInfo”, so in whatever place you need access to it (where you require() it), just call the TP-generated “getSheet()” function (obviously you need to require() that TP file regardless, otherwise you can’t use the image data it generated). From there, you can just dig down into the frame’s data (table) and gather the width and height to pass to newImageRect().

Hope this makes sense… I may not have described it very well. :confused:

Brent

Hi Brent,

Yes I get what you’re saying. I can retrieve the actual width and height from the frame info. The issue then is that I have to do the math to scale the image proportionally to reach an arbitrary width and height (because the width and height of the png is not a 1:1 relation with Corona’s display points).

But what I said a couple posts ago is that Corona should be doing that math behind the scenes if there is a source width and height. It’s already doing the math to position the object within those dimensions, so why not take it a step further to return a proportional image relative to the source width and height? That’s the way I expected it to work and was surprised to find out that it didn’t.

Your spites should be designed to your content units. Then display.newImageRect()'s width and  height would be the right values.

But that said, I understand what you’re saying and it probably should work that way:  take sprite A and position it in this width/height box and this x,y location. The resulting display.newImageRect() should return the transparent filled sourceWidth and sourceHeight. Is that what you’re suggesting?

If so please go to https://feedback.coronalabs.com and put in a feature request for this and lets see if we can get some votes on it. We are getting ready to get into our next development cycle and now’s a good time to bring up these issues, but I have to have a request on the feedback site to carry this forward.

Rob

Hi Rob,

Yes I was under the impression that Corona would return an image that was essentially the same as using the untrimmed image. And then I could supply an arbitrary width and height to display.newImageRect and it would scale the “untrimmed” image to fit within those dimensions.

I’ll submit a feature request. How many votes are necessary to make it happen?

It’s not a set number of votes. There are many factors that go into it including complexity, cross-platform compatibility, etc.  The only real answer I can give you is “the more the better”.

You can always set Trim mode to None within TexturePackers Advanced settings.

I’m actually surprised that TexturePacker even allows you to use Trimming when it’s not supported by Corona.

Yes that’s the workaround that I ended up using. But it is not ideal because you lose out on the texture memory savings that trimming provides, especially if you have many assets on a single imagesheet.

Hi @Vince_,

Did you ever file a bug report or feature request for this? If so, do you have a case number? We can look into resolving this, but we need a file on it to speed up the process.

Thanks,

Brent

Hi Brent,

No, I haven’t had the time to. But it doesn’t necessarily seem like a bug, just something that Corona wasn’t designed to handle. And from Rob’s suggestion to put in a feature request, I mean that’s great but I don’t have faith that it will get enough votes. Especially considering that this other feature request

http://feedback.coronalabs.com/forums/188732-corona-sdk-feature-requests-feedback/suggestions/9316359–plugin-google-play-cloud-save?tracking_code=8dbf17e2e71c093f6409aef2442009e3

had over 300 votes and took almost a year before work was started on it.

Not all feature requests are created equal. Somethings are very hard. Some things are hyper easy. Some things make sense in a cross-platform environment, platform specific things have to rise to a higher standard since it benefits fewer people. Some things our core engineers have to build. Somethings the community can build. You can’t look at any one feature request and it’s vote count and measure that as how another feature request will be managed.

But one thing I can say, if there isn’t a feature request, the chances of it being implemented is quite very small.

Rob

I created a feature request:

http://feedback.coronalabs.com/forums/188732-corona-sdk-feature-requests-feedback/suggestions/15596511-trimmed-images-from-tools-like-texturepacker-shoul