Convert NPOT PVR texture to POT within iOS

I would like to manually load NPOT PVR textures on iOS (I don’t mean loading the texture in OpenGL memory, I mean loading it in a custom data structure that allows accessing the image data in order enlarge the canvas and save it again as a new PVR).





I am asking this because we are implementing an OpenGL iOS application with lots of background textures (480 x 320 on non retina displays). We intend to store this textures as NPOT PVR files, so we have memory gains on 3GS+ iPhones.





3G- iPhone cannot load NPOT PVR textures in non OpenGL memory. My intentions are to implement a preprocessing step for 3G- devices that converts all NPOT PVRs textures to POT PVRs and stores them on the app’s Cache folder.





Is it possible to load and process a PVR in this way? For example, a TexturePacker generated PVR.





I don’t want to include both texture versions within the game, to keep the IPA size at the minimum.

I’m not entirely clear about what you are trying to to do so please forgive me if I’ve got the wrong end of the stick here. Are you wanting to store your textures as NPOT on ‘disk’ then pad them in memory for earlier platforms that don’t support NPOT, before passing to GL?





PVR is a container format that holds a header with texture data following it. If you examine the PVRTexLib manual then there is a description of the format in Appendix B. Also, you can see some code that handles parsing this in the Tools/OGLES(2) folder of one of our SDKs in the file PVRTTextureAPI.cpp. If you’re not passing these to OpenGL then you can load whatever dimensions of texture that you can fit into RAM: the process is just to read the header for how much data there is, allocate memory for the data and then read it in from the file. If the format of the data is simple enough RGB565 or ARGB8888 then it should be easy enough to pad the data for the earlier devices. Using even a 16bit format at 320x480 is still going to take up more memory than a PVRTC 4bpp texture at 512x512, though.





If you are hoping to resize PVRTC data (i.e. from compressed PVR files) then this will be much more problematic. I don’t believe a tool is available to produce NPOT PVRTC data at this time (I would be interested if you know of one); padding PVRTC data is going to be pretty tricky too.

Sorry for my very late reply, we are having some busy weeks. Thank you, Gordon, for your quick and detailed answer. I’m quite new to OpenGL and to the PowerVR texture format (learning new things every day!), but your message was very clarifying…





Gordon wrote:
I'm not entirely clear about what you are trying to to do so please forgive me if I've got the wrong end of the stick here. Are you wanting to store your textures as NPOT on 'disk' then pad them in memory for earlier platforms that don't support NPOT, before passing to GL?




That's exactly what I'm trying to do.



Gordon wrote:

PVR is a container format that holds a header with texture data following it. If you examine the PVRTexLib manual then there is a description of the format in Appendix B. Also, you can see some code that handles parsing this in the Tools/OGLES(2) folder of one of our SDKs in the file PVRTTextureAPI.cpp. If you're not passing these to OpenGL then you can load whatever dimensions of texture that you can fit into RAM: the process is just to read the header for how much data there is, allocate memory for the data and then read it in from the file. If the format of the data is simple enough RGB565 or ARGB8888 then it should be easy enough to pad the data for the earlier devices.




I think I completely understand this part. I need to carefully study the documentation and code you pointed out, thanks about that.



Gordon wrote:

Using even a 16bit format at 320x480 is still going to take up more memory than a PVRTC 4bpp texture at 512x512, though.




I finally understood the difference between PVR (the container) and PVRTC (the texture format). Luckily for us, we are trying to pad PVR textures, most of them are RGB565.



Gordon wrote:

If you are hoping to resize PVRTC data (i.e. from compressed PVR files) then this will be much more problematic. I don't believe a tool is available to produce NPOT PVRTC data at this time (I would be interested if you know of one); padding PVRTC data is going to be pretty tricky too.



I acknowledge that PVRTC is a proprietary format, and as such, PowerVR doesn't provide APIs for reading them, just for creating them. Is that right?



Cheers and merry christmas!

Padding RGB565 data should be fairly easy. Assign a large enough buffer for your POT texture and then just grab the data from after the header, line by line and write each line to the nearest POT offset in your buffer (for horizontal padding). Then upload to GL. Altering the code in our Tools folder (e.g. Tools/OGLES2/PVRTTextureAPI.cpp) might be a good place to start for this as it already reads the PVR format for you.





As I say, PVRTC is more tricky. There is decompression code in our SDK for PVRTC so you can read back the colour values of a file using this, but this doesn’t really solve your problem as I don’t think this code can deal with NPOT PVRTCs at this time and you’d still have to compress to PVRTC again after padding (which isn’t available for device).





Hope that helps (and you had a good holiday)