New discovery! Apparently the pixel data itself is also organised in chunks. Each chunk is preceded by a 32-bit unsigned integer stating the chunk's length.
Not only is this useful for reading in the pixel data, but it also explains why I had to increase the shift by 4 bytes for each chunk when I was ripping them with Texture Finder.
(By the way, when I say "unsigned integer", usually I actually have no idea whether it's signed or not. I haven't seen the highest bit set yet, so reading them as signed or unsigned shouldn't matter, but I don't see a use for negative numbers here so I'm just assuming it's unsigned.)
EDIT: Also fixed some errors that I just noticed in my last post.
Not only is this useful for reading in the pixel data, but it also explains why I had to increase the shift by 4 bytes for each chunk when I was ripping them with Texture Finder.
(By the way, when I say "unsigned integer", usually I actually have no idea whether it's signed or not. I haven't seen the highest bit set yet, so reading them as signed or unsigned shouldn't matter, but I don't see a use for negative numbers here so I'm just assuming it's unsigned.)
EDIT: Also fixed some errors that I just noticed in my last post.