I used image:transformedImage
for the first time and it seems there is an off-by-one error — when flipping the image around its x axis by a transformation that contains scale(-1, 1)
, the image output is moved one pixel to the right. The same happens when flipping around y axis or both axes.
The expected result in the next picture is 4 identical square/circle images, but when applying X, Y, and XY flips on the respective images, the result looks like this (code and a zipped minimal example are below):
I made sure to use an image with an even resolution in both axes. My theory is that somewhere along the way 0- and 1-based numbering collides when relaying the data between lua and C parts of the SDK, but I’m not sure how that could apply in the gfx/image context.
Related
At first I couldn’t find any similar issues, but i’d say that this is the underlying problem in several more specific longstanding issues (esp around image rotation), such as:
- image:rotatedImage(90) offsets/crops pixels by (-1,-1)… new in SDK 1.12?
- Image edge clipped when using affine transforms - #2 by downie
- and perhaps even playdate.graphics.image:transformedImage crashes simulator with certain size images
I recently encountered a similar weird issue where Image:sample() returns phantom values — where there’s seems to be a problem with boundary check being aligned with 1-based numbering in a bitmap context.
Code
This is the code that generated the image (full minimal example: transformed-image-bug.zip (10.8 KB)):
-- image with a circle drawn inside
local img = gfx.image.new(10, 10)
gfx.pushContext(img)
gfx.drawCircleAtPoint(5, 5, 5)
gfx.popContext()
-- unflipped image
gfx.setDrawOffset(10, 10)
gfx.drawRect(-1, -1, 12, 12)
img:draw(0, 0)
-- flipped X
gfx.setDrawOffset(30, 10)
gfx.drawRect(-1, -1, 12, 12)
local tx = affineTransform.new()
tx:scale(-1, 1)
img:transformedImage(tx):draw(0, 0)
-- flipped Y
gfx.setDrawOffset(50, 10)
gfx.drawRect(-1, -1, 12, 12)
local ty = affineTransform.new()
ty:scale(1, -1)
img:transformedImage(ty):draw(0, 0)
-- flipped XY
gfx.setDrawOffset(70, 10)
gfx.drawRect(-1, -1, 12, 12)
local txy = affineTransform.new()
txy:scale(-1, -1)
img:transformedImage(txy):draw(0, 0)