## PNG loader library for OpenGL v1.45 (10/7/2000)

Ben Wyatt ben@wyatt100.freeserve.co.uk

### Introduction

This is a library for OpenGL to load PNG graphics files as an OpenGL texture as easily as possible. It also has a number of options for generating the alpha channel and mipmaps. It is implemented using modified versions of the LibPNG 1.0.2 and ZLib 1.1.3 libraries.

This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software.

Permission is hereby granted to use, copy, modify, and distribute this source code, or portions hereof, for any purpose, without fee, subject to the following restrictions:

1. The origin of this source code must not be misrepresented. You must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered versions must be plainly marked as such and must not be misrepresented as being the original source.
3. This notice must not be removed or altered from any source distribution.

### Installation for MSDEV

Copy glpng.h to your include/GL folder and copy glpng.lib and glpngd.lib to your lib folder. Then just do #include <GL/glpng.h> and with a bit of luck, MSDEV will automatically link with glpng.lib (release lib) or glpngd.lib (debug lib).

### Installation for Any Other Compiler

Copy glpng.h to your include/GL folder. Then you'll have to build the library yourself with the included source code. Included are makefiles for Linux and SGI. If you need to modify the source code to make it work on your system, please get in contact so I can make future versions compatible.

### Compiling with LibPNG or ZLib

If you are using LibPNG or ZLib in your project there may be problems if you link with the glpng library. To solve this, include glpng.c in your project and, if you're using MSDEV, modify glpng.h to not automatically link with glpng.lib or glpngd.lib.

### OpenGL DLL Dynamic Loading using glsetup

To use glpng with glsetup, include glpng.c, LibPNG and ZLib in your project. In glpng.c, change #include <GL/gl.h> to include the glsetup include and modify glpng.h to not automatically link with glpng.lib or glpngd.lib.

### Functions

- pngLoad
- pngLoadF
- pngBind
- pngBindF
- pngLoadRaw
- pngLoadRawF
- pngSetStencil
- pngSetAlphaCallback
- pngSetViewingGamma
- pngSetStandardOrientation

    success = pngLoad(filename, mipmap, trans, info)

> filename | Filename of PNG file, including ".png"
> mipmap | Mipmapping parameter: 0 or PNG_NOMIPMAP if no mipmap or for the base mipmap level 1,2,3... for mipmap detail level PNG_BUILDMIPMAPS to call a clone of gluBuild2DMipmaps (box filter) PNG_SIMPLEMIPMAPS to generate mipmaps without filtering (uses upper-left of each 2x2 box)
> trans | Transparency setting: PNG_ALPHA to use alpha channel in PNG file, if there is one PNG_SOLID for no transparency PNG_STENCIL to set pixels of a certain value to alpha 0, otherwise 1 (see pngSetStencil) PNG_BLEND1 to set alpha to r+g+b PNG_BLEND2 to set alpha to (r+g+b)/2 PNG_BLEND3 to set alpha to (r+g+b)/3 PNG_BLEND4 to set alpha to r2+g2+b2 PNG_BLEND5 to set alpha to (r2+g2+b2)/2 PNG_BLEND6 to set alpha to (r2+g2+b2)/3 PNG_BLEND7 to set alpha to (r2+g2+b2)/4 PNG_BLEND8 to set alpha to sqrt(r2+g2+b2) PNG_CALLBACK to use the callback function defined by pngSetAlphaCallback.
> info | Pointer to a pngInfo structure to store texture info or NULL if you don't care. The pngInfo fields are: Width - width of the original image in pixels Height - height of the original image in pixels Depth - depth of the original image, where colours = 2Depth Alpha - the number of bits used for the alpha channel (0 if no alpha channel)

> Loads a PNG file and calls glTexImage2D with appropriate parameters. The texture will be resized if the dimensions are not powers of 2 or over the maximum texture size. Should be able to load all colour depths (except 64-bit) and alpha channels if available. It converts them to an appropriate format and gives them to glTexImage2D. The OpenGL paletted texture extension is used if available.

> Returns 1 on success or 0 if file could not be loaded.

    success = pngLoadF(file, mipmap, trans, info)

> file | FILE opened with fopen("something.png", "rb")

> This is used to load a PNG from an already opened file. Handy if you want to batch all your data and textures into one big data file.

    id = pngBind(filename, mipmap, trans, info, wrapst, minfilter, magfilter)
    id = pngBindF(file, mipmap, trans, info, wrapst, minfilter, magfilter)

> wrapst | GL_CLAMP or GL_REPEAT (look up glTexParameter)
> minfilter | Minification function for filtering (look up glTexParameter)
> magfilter | Magnification function for filtering (look up glTexParamter)

> Automates the process further - loads a PNG file, sets the OpenGL parameters, binds it to an OpenGL texture and returns it's ID, or 0 if the file couldn't be loaded.

    success = pngLoadRaw(filename, rawinfo)
    success = pngLoadRawF(file, rawinfo)

> rawinfo | Pointer to a pngRawInfo structure in which to store the PNG data. The pngRawInfo has these fields: Width, Height, Depth, Alpha - as in pngInfo Components - number of colour components (1, 2, 3 or 4) Data - pointer to image data stored as RGBRGB... or RGBARGBA... or indices to the palette table. Must be freed manually using free() Palette - pointer to palette table stored as RGBRGB... or RGBARGBA... Will be NULL if there is no palette table. Must be freed manually using free()

    pngSetStencil(red, green, blue)

> red,green,blue | The colour to stencil out when using the PNG_STENCIL option

> This selects the colour to stencil out when using PNG_STENCIL. The parameters are 0 to 255. By default the colour is 0,0,0 (pure black).

    pngSetAlphaCallback(function)

> function | Pointer to a function taking three unsigned char parameters (red, green, blue) and returning an unsigned char (alpha)

> This sets the function to be called when using PNG_CALLBACK. During the alpha channel generation process, this function will be called for every pixel, with the appropriate RGB values, and will use the result for the alpha value. The RGB and alpha values all range from 0 to 255. The default callback function simply returns 255.

    pngSetViewingGamma(gamma)

> gamma | New gamma correction value

> By default, gamma correction is set to 1.0 for Windows, 1.7 for SGI and 1.45 for Macs. If the VIEWING_GAMMA environmental variable is set, that is used instead. You can override both of these values using pngSetViewingGamma().

    pngSetStandardOrientation(standardorientation)

> standardorientation | If to use the standard orientation (0 is default)

> By default, the image is loaded so that texture coordinates 0,0 represent the top-left - a result of me not knowing the OpenGL spec :-). If you wish to use the standard OpenGL representation where 0,0 is the bottom-left, set this to 1.

### Examples

Here's an example of pngLoad(), to load "Texture.png" with nearest filter, clamping on and no mipmaps or alpha channels...

>     pngInfo info;
>     GLuint id;

>     glGenTextures(1, &id);
>     glBindTexture(GL_TEXTURE_2D, id);

>     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
>     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
>     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
>     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

>     if (pngLoad("Texture.png", PNG_NOMIPMAP, PNG_SOLID, &info)) {
>        puts("Loaded Texture.png with resounding success");
>        printf("Size=%i,%i Depth=%i Alpha=%i\n", info.Width, info.Height, info.Depth, info.Alpha);
>     }
>     else {
>        puts("Can't load Texture.png");
>        exit(1);
>     }

And here's an example to load the same texture with the same options using pngBind()...

>     pngInfo info;
>     GLuint id = pngBind("Texture.png", PNG_NOMIPMAP, PNG_SOLID, &info, GL_CLAMP, GL_NEAREST, GL_NEAREST);

>     if (id != 0) {
>        puts("Loaded Texture.png with resounding success");
>        printf("Size=%i,%i Depth=%i Alpha=%i\n", info.Width, info.Height, info.Depth, info.Alpha);
>     }
>     else {
>        puts("Can't load Texture.png");
>        exit(1);
>     }

If those two examples don't make sense, try the included full source example (which needs GLUT).

### Bugs

- 64-bit PNGs can't be loaded (missing LibPNG feature as far as I can tell).

### Possible Future Developments

- Better attempts could be made to find the optimal texture format for OpenGL. At the moment, it converts everything to 24 or 32 bit, or uses the paletted texture extension in certain (easy to handle) cases.
- Other mipmap generating algorithms could be implemented (wavelet stuff?). Source donations are welcome.
- Saving the frame buffer to a PNG file.
- Support for GL_INTENSITY, GL_LUMINANCE_ALPHA and others.

### History

1.33 (20/5/99) | First public release.
1.34 (27/5/99) | Optimised alpha channel generating, added Alpha property to the pngInfo structure, illegal texture sizes are resized.
1.35 (4/6/99) | Added pngLoadRaw and pngLoadRawF functions.
1.36 (9/6/99) | Fixed problem causing linking warnings/errors (I think) and reduced the size of the library considerably.
1.37 (13/6/99) | Added alpha channel generation callback function.
1.38 (22/6/99) | Stopped it from disabling texturing on calls to pngBind and pngBindF.
1.39 (8/7/99) | Fixed a bug in the extensions reading code, which caused some machines to crash.
1.40 (27/9/99) | Added support for SGI, Linux, and gamma correction (thanks to Mark B. Allan!). Fixed bug in raw reading of gray textures (thanks to Johann Scholtz!). Removed all use of GLU functions to make it easier to dynamically load opengl32.dll or 3dfxvgl.dll or whatever. Added simple mipmap generator.
1.41 (20/10/99) | Made a small optimisation and improved documentation. Remembered to include the makefiles for Linux and SGI in the zip (!).
1.42 (01/03/00) | Fixed problems with compiling on SGI (thanks to Thomas Sondergaard!). Added pngSetStandardOrientation (thanks to Scott Franke!).
1.43 (11/05/00) | Added debug library and fixed the crash when there wasn't a terminating png info structure (thanks to Dan Hawkins!).
1.44 (01/07/00) | Fixed release and debug libraries so they stop producing warnings and errors in MSDEV.
1.45 (10/07/00) | Fixed bug where the standard orientation flag was being ignored in pngLoadRawF (thanks to Mark B. Allan!).

Get the latest version from http://www.wyatt100.freeserve.co.uk/download.htm