Liz,
I’m guessing that the reason you’re still asking is that maybe the question you’re really asking is :
“Given an non-power-of-two-dimensioned image larger than the size of the screen (say, a 10000 x 10000 image on a 1600 x 1200 screen), how do you ‘best’ display the image under OpenGL?”
In which case the NV_texture_rectangle would technically work, but would be incredibly slow trying to draw, in my example above, a roughly 285 MB texture (if 24-bit color).
What I’ve done in the past is divide the image into tiles of some convieniant size, by which I mean “Of power-of-two” dimensions for Open-GL purposes, as well as fairly small to reduce memory and speed rendering. I usually default to 256 x 256 pixels because my app has to run on an old crappy system.
So, when the user opens the image, your code has to run through the image and divide it into 256 x 256 pixel blocks. One pointnto consider when you write that code - If the image is of an odd (as in non-even) size, don’t create any 1 x 1 blocks. Instead, if you have, say, a 1555 x 1536 image, your array tiles should look like :
[256][256][256][256][256][256][16][2][1]
[256][256][256][256][256][256][16][2][1]
[256][256][256][256][256][256][16][2][1]
[256][256][256][256][256][256][16][2][1]
[256][256][256][256][256][256][16][2][1]
[256][256][256][256][256][256][16][2][1]
where each [number] is the width in pixels, and all heights are 256.
Anyway, when I say “make tiles”, I mean “create a texture”. In my example above, you end up with 54 textures in memory. Remember, once you’ve called glTexImage2D() to create a tile, you don’t have to store the image data for the tile yourself - OpenGL does that for you. All you need to store is the coordinates of each tile’s corners.
Incidentally, it would be much better to optimize that last column down to just 2 tiles ( a [1 x 1024] tile and a [1 x 512] tile instead of 6 [1 x 1] tiles ). Probably good to optimize any tile that ends up consuming less than 100kb of memory…
Now, when you go to draw, you can decide (based on the user’s position and zoom level, for example) how much of the image to display. This tells you which tiles are visible and need to be drawn (don’t draw every tile every time!). Run through and draw a bunch of GL_QUADs across the screen, binding to the appropriate texture for each GL_QUAD.
This gives you a simple “Pan around the image” type application, but “Zooming” out to view the whole image will still be quite slow because you’re still moving all 286MB of image data.
The solution is to add a step to the tile-building process. Once you’ve created all the tiles, take the original 286 MB image and use your favorite high-quality image shrinking algorithm to cut it’s dimensions in half, so you end up with a 77 x 768 pixel image. No go create a whole new set of tiles for this new, “Lower Resolution” version of the image :
[256][256][256][8][1]
[256][256][256][8][1]
[256][256][256][8][1]
Now, when the user zooms out, you draw this set of tiles instead of the first set, and you’re moving only 1.7MB if you draw every tile. You can also continue lowering the resolution of the image until it fits into a single tile if you want to…
This is very similar to mipmapped textures, (in fact, you’re basically doing your own mipmapping). You could have just mipmapped the original set of tiles, but I find that doing so leads to little grid lines because the minimization algorithm doesn’t know anything about the adjacent tiles.
Anyway, this probably seems pretty convoluted to most of you, but simple image viewing programs have gotten annoyingly complicated lately, what with digital cameras spitting out 100MB + images. Ever try to use the standard Windows API to BitBlt such an image? Ouch. Anyway, I suspect all the “real” imaging applications are using a fancier version of this, because when you zoom or pan quickly, the image is drawn one little (probably power-of-two sized) square tile at a time.
Well, if this doesn’t help Liz, I hope it at least helps someone somewhere a bit! I don’t get to read the forums often, but next time I’m here I’ll try to remember to see if you had any questions…
Regards,
-Chris Bond