Images Loaded From Files Not 32-bit Aligned

Hi all,

I've been working on some custom image processing code for the Playdate. As I started to empirically probe the SDK I noticed that the bytes_per_row value is usually 32-bit aligned. This makes sense if you are processing image data 32-bits at a time for performance and I even found a ticket that indicates this is the case 1.

However, it appears that image data is not always 32-bit aligned. Namely, for images loaded from files. I have the following test code that loads a 400x240 image (PD_LCDBitmapFromPath is just a wrapper around loadBitmap):

LCDBitmap* mMainMenu = PD_LCDBitmapFromPath("Images/MainMenu");
{
	S32 width = 0, height = 0, bytes_per_row = 0;
	pd->graphics->getBitmapData(mMainMenu, &width, &height, &bytes_per_row, 0, 0);

	LCDBitmap* bmp = pd->graphics->newBitmap(width, height, kColorWhite);
	pd->graphics->getBitmapData(bmp, &width, &height, &bytes_per_row, 0, 0);
	pd->graphics->freeBitmap(bmp);
}

If I step through this in the debugger then I notice that bytes_per_row for the image loaded from the file is 50 (= 400 / 8) so 8-bit aligned. But the bytes_per_row of the newly created image of the same size is 52 or 32-bit aligned.

So my question would be: Are all images actually 32-bit aligned and maybe bytes_per_row is inaccurate for images loaded from files? Or are images of mixed alignment? Alignment being mixed does complicate the image processing code a bit.

EXPECTATION
All images are either 32-bit or 8-bit aligned. Probably 32-bit aligned as this seems to be the case historically within the SDK.

Originally I had all images using 32-bit alignment, but that caused fonts to use a lot more memory and disk space than they would if we dropped that constraint. I did some testing and found that the speed difference wasn't really noticeable (roughly a 2x penalty for unaligned access, as I recall--you'd only be able to tell if you were in a really tight loop) so I switched to 8-bit alignment. Except, for some reason, in pd->graphics->newBitmap()? :thinking: I can't remember now and the commit logs aren't helping. My best guess is I wanted you to be able to take the fastest route, a single memcpy(), when you're drawing a full-frame image to the screen. ..But most of the time those would be loaded from disk. :confused: Slack is no help either, but I did find our conversation about the change, and I mentioned that 8-bit alignment was actually faster for fonts, presumably because it fits in the cache better.

So: Images created with pd->graphics->newBitmap() happen to have 32-bit aligned data through oversight/accident of history, but as far as I can tell that's the only place we added that constraint.

4 Likes