loading png into a texture

I found a function to load a PNG image, but its not working. I’m pretty sure I’m using the function properly, but whenever I load a png it is distorted with gray noise. I think the problem is with how I’m displaying the texture in my render loop, though, since everything else on the frame turns yellow when I load the image.

Here is my code:

BOOL PngLoadImage (char *fname, png_byte **ppbImageData, int *piWidth, int *piHeight, int *piChannels, png_color *pBkgColor)
{
    FILE           *pfFile;
    png_byte        pbSig[8];
    int             iBitDepth;
    int             iColorType;
    double          dGamma;
    png_color_16   *pBackground;
    png_uint_32     ulChannels;
    png_uint_32     ulRowBytes;
    png_byte       *pbImageData = *ppbImageData;
    png_byte      **ppbRowPointers = NULL;
    int             i;
	png_struct *png_ptr;
	png_info *info_ptr;
	png_uint_32 *pngUint32p = 0;

    // open the PNG input file

    if (!fname)
    {
        *ppbImageData = pbImageData = NULL;
        return FALSE;
    }

    if (!(pfFile = fopen(fname, "rb")))
    {
        *ppbImageData = pbImageData = NULL;
        return FALSE;
    }

    // first check the eight byte PNG signature

    fread(pbSig, 1, 8, pfFile);
    if (!png_check_sig(pbSig, 8))
    {
        *ppbImageData = pbImageData = NULL;
        return FALSE;
    }

    // create the two png(-info) structures

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
    {
        *ppbImageData = pbImageData = NULL;
        return FALSE;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        *ppbImageData = pbImageData = NULL;
        return FALSE;
    }

    // setjmp() must be called in every function that calls a PNG-reading libpng function

    if (setjmp(png_ptr->jmpbuf))
    {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        *ppbImageData = pbImageData = NULL;
        return FALSE;
    }

    // initialize the png structure

#if !defined(PNG_NO_STDIO)
    png_init_io(png_ptr, pfFile);
#else
    png_set_read_fn(png_ptr, (png_voidp)pfFile, png_read_data);
#endif

    png_set_sig_bytes(png_ptr, 8);

    // read all PNG info up to image data

    png_read_info(png_ptr, info_ptr);

    // get width, height, bit-depth and color-type

    png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)piWidth, (png_uint_32 *)piHeight, &iBitDepth, &iColorType,
        NULL, NULL, NULL);

    // expand images of all color-type and bit-depth to 3x8 bit RGB images
    // let the library process things like alpha, transparency, background

    if (iBitDepth == 16)
        png_set_strip_16(png_ptr);
    if (iColorType == PNG_COLOR_TYPE_PALETTE)
        png_set_expand(png_ptr);
    if (iBitDepth < 8)
        png_set_expand(png_ptr);
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_expand(png_ptr);
    if (iColorType == PNG_COLOR_TYPE_GRAY &#0124;&#0124;
        iColorType == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ptr);

    // set the background color to draw transparent and alpha images over.
    if (png_get_bKGD(png_ptr, info_ptr, &pBackground))
    {
        png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
        pBkgColor->red   = (byte) pBackground->red;
        pBkgColor->green = (byte) pBackground->green;
        pBkgColor->blue  = (byte) pBackground->blue;
    }
    else
    {
        pBkgColor = NULL;
    }

    // if required set gamma conversion
    if (png_get_gAMA(png_ptr, info_ptr, &dGamma))
        png_set_gamma(png_ptr, (double) 2.2, dGamma);

    // after the transformations have been registered update info_ptr data

    png_read_update_info(png_ptr, info_ptr);

    // get again width, height and the new bit-depth and color-type

    png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)piWidth, (png_uint_32 *)piHeight, &iBitDepth, &iColorType,
        NULL, NULL, NULL);


    // row_bytes is the width x number of channels

    ulRowBytes = png_get_rowbytes(png_ptr, info_ptr);
    ulChannels = png_get_channels(png_ptr, info_ptr);

    *piChannels = ulChannels;

    // now we can allocate memory to store the image

    if (pbImageData)
    {
        free (pbImageData);
        pbImageData = NULL;
    }
    if ((pbImageData = (png_byte *) malloc(ulRowBytes * (*piHeight) * sizeof(png_byte))) == NULL)
    {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        *ppbImageData = pbImageData = NULL;
        return FALSE;
    }
    *ppbImageData = pbImageData;

    // and allocate memory for an array of row-pointers

    if ((ppbRowPointers = (png_bytepp) malloc((*piHeight) * sizeof(png_bytep))) == NULL)
    {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        free(pbImageData);
        *ppbImageData = pbImageData = NULL;
        return FALSE;
    }

    // set the individual row-pointers to point at the correct offsets

    for (i = 0; i < (*piHeight); i++)
        ppbRowPointers[i] = pbImageData + i * ulRowBytes;

    // now we can go ahead and just read the whole image

    png_read_image(png_ptr, ppbRowPointers);

    // read the additional chuncks in the PNG file (not really needed)

    png_read_end(png_ptr, NULL);

    // and we're done

    free (ppbRowPointers);
    ppbRowPointers = NULL;

    // yepp, done

    fclose (pfFile);

    return TRUE;
}

// in main

	png_byte *png;
	int size = 128;
	int channels = 2;
	png_color col;

	PngLoadImage("font1.png", &png, &size, &size, &channels, &col); 
	if (png == NULL)
		exit(0);

	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	gluBuild2DMipmaps(GL_TEXTURE_2D, 3, size, size, GL_RGB, GL_UNSIGNED_BYTE, png);

// display callback
void ygeDraw(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, texture);

	glBegin(GL_QUADS);
		glTexCoord2d(0.0,0.0); glVertex2d(0.0,0.0);
		glTexCoord2d(1.0,0.0); glVertex2d(1.0,0.0);
		glTexCoord2d(1.0,1.0); glVertex2d(1.0,1.0);
		glTexCoord2d(0.0,1.0); glVertex2d(0.0,1.0);
	glEnd();

	glutSwapBuffers();
}

Can anyone help me out? Thank you for your time.

Sorry for not having the time to bugfix the code that you downloaded from somewhere on the internet for free and failed to get working :wink: Please try one of these libraries instead - they even come with working samples that you can copy/paste from :eek:

[http://freeimage.sourceforge.net/](http://freeimage.sourceforge.net/)    
[http://openil.sourceforge.net/](http://openil.sourceforge.net/)    

Cheers,