Desperate to load PNG files. (MSVC 2008)

Hi,
I have a very happy openGL program that needs to switch from tga images to png for its textures. I have spent two days trying to find a png loadfile routine that will compile under MSVC Express 2008 without success.

Lodepng, soil, and SDL have all fallen by the wayside. Are they still being developed?

If anyone can point me in the direction of a working png loader, I would be extremely grateful!

Many thanks.

did you read this ?
http://bobobobo.wordpress.com/2009/03/02/how-to-use-libpng/

Oooh, not seen that one. Thank you!

I can’t believe it has taken me two days to get nowhere with png. It took about an hour to get working tga’s.

Appreciate the help :slight_smile:

Lodepng, soil, and SDL have all fallen by the wayside. Are they still being developed?

I don’t know what lodepng and soil are, but SDL had a release as recently as 2 months ago. So I don’t know where this “fallen by the wayside” stuff is coming from.

If anyone can point me in the direction of a working png loader

The very first hit in a Google search for “image loading library” was DevIL. It’s not being actively worked on, but it does function and is fairly bug-free.

My personal preference is the less popular but infinitely superior FreeImage.

How is this question related to advanced opengl coding?

From browsing the forum, this board appeared to be the most appropriate - even though I would agree that PNG’s technically have sfa to do with openGL.

Having come from many years coding dib’s in Delphi, returning to C and using openGl has been a steep curve. Not helped by those already ‘in the know’ being reluctant to share knowledge.

If a mod wishes to zap or move this thread then I certainly have no objection to that. This seemed to be the group best qualified to answer my query.

http://openil.sourceforge.net/

I’d advise this one :wink:
regards,

DevIL is being actively developed. Someone took it over about a year ago. Lots of bugs have been fixed, and it’s now a very clean and capable library (an enormous number of formats are supported). I prefer its interface to all others.
Fossil, this question could not be less appropriate for this forum. Anyone can see that. It’s almost the equivalent of asking where you can buy a decent garden spade on a Tivo forum. No wonder you’re having trouble getting ‘those in the know’ to help you.

Download libpng140 and zlib, add both libs to project. Then create this class:


// =========  LoadPng.h ========= 

#ifndef _LoadPng_h__
#define _LoadPng_h__

#include "png.h"

class CLoadPng
{
public:
	CLoadPng();
	virtual ~CLoadPng();

	bool Load(const char* fname);
	int GetWidht();
	int GetHeight();
	int GetBPP();
	unsigned char* GetData();

protected:
	png_uint_32 m_Width;
	png_uint_32 m_Height;
	int m_BPP;
	int m_iColorType;

	png_byte* m_Data;
};

#endif // _LoadPng_h__

// ========= LoadPng.cpp ========= 
#include <stdlib.h>
#include <png/LoadPng.h>

CLoadPng::CLoadPng()
{
	m_Width = 0;
	m_Height = 0;
	m_BPP = 0;
	m_iColorType = 0;
	m_Data = NULL;
}

CLoadPng::~CLoadPng()
{
	if (m_Data != NULL)
	{
		free(m_Data);
		m_Data = NULL;
	}
}

bool CLoadPng::Load( const char* fname )
{
	if (fname == NULL) return false;

	FILE* f = fopen(fname, "rb");
	if (f == NULL) return false;

	png_byte pbSig[8];
	fread(pbSig, 1, 8, f);
	if (png_sig_cmp(pbSig, 0, 8))
	{
		fclose(f);
		return false;
	}

	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)NULL, (png_error_ptr)NULL);
	if (!png_ptr)
	{
		fclose(f);
		return false;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		fclose(f);
		return false;
	}

	png_init_io(png_ptr, f);
	png_set_sig_bytes(png_ptr, 8);
	png_read_info(png_ptr, info_ptr);

	int iBitDepth;
	// get width, height, bit-depth and color-type
	png_get_IHDR(png_ptr, info_ptr, &m_Width, &m_Height, &iBitDepth, &m_iColorType, NULL, NULL, NULL);

	if (iBitDepth == 16) png_set_strip_16(png_ptr);
	if (m_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);

  // need to update info to reflect changes
	png_read_update_info(png_ptr, info_ptr);
	png_get_IHDR(png_ptr, info_ptr, &m_Width, &m_Height, &iBitDepth, &m_iColorType, NULL, NULL, NULL);

  // now we can read png
	png_uint_32 ulRowBytes = png_get_rowbytes(png_ptr, info_ptr);
	png_uint_32 ulChannels = png_get_channels(png_ptr, info_ptr);

	m_BPP = ulChannels;

	if (m_Data != NULL)
	{
		free(m_Data);
		m_Data = NULL;
	}

	if ((m_Data = (png_byte *) malloc(ulRowBytes * m_Height * sizeof(png_byte))) == NULL)
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		fclose(f);
		m_Width = m_Height = m_BPP = 0;
		return false;
	}

	png_byte   **ppbRowPointers = NULL;

	if ((ppbRowPointers = (png_bytepp) malloc(m_Height * sizeof(png_bytep))) == NULL)
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		fclose(f);
		free(m_Data);
		m_Data = NULL;
		m_Width = m_Height = m_BPP = 0;
		return false;
	}

	for (int i = 0; i < m_Height; i++) ppbRowPointers[i] = m_Data + i * ulRowBytes;

	png_read_image(png_ptr, ppbRowPointers);
	png_read_end(png_ptr, NULL);
	free (ppbRowPointers);
	ppbRowPointers = NULL;
	fclose(f);
	return true;
}

int CLoadPng::GetWidht()
{
	return m_Width;
}

int CLoadPng::GetHeight()
{
	return m_Height;
}

int CLoadPng::GetBPP()
{
	return m_BPP;
}

unsigned char* CLoadPng::GetData()
{
	return m_Data;
}


To use:


CLoadPng l;
if (l.Load("Test.png"))
{
 // image is loaded... use l.GetWidth(), l.GetHeight(), l.GetBPP() and l.GetData() to access image 
}

+1 for freeimage - simple, easy and works.

-1 for OpenIL (DevIL) - it’s simply been out of development for too long, the OpenGL-like interface is overthought (and overly complicated), and it is too buggy. Though it may have gotten better with recent development.

My thanks to all - all useful stuff.

I d/l devIL last night and that was very easily added to my existing code and worked ‘right out of the box’. And yes, it appears that it is still being developed.

Thanks Yooyo for the code snippet - I’ve put that to one side and it will certainly be used if I can resolve issues with zlib (my inexperience with MSVC I’m sure).

My apologies to those who think my post was inappropriate!

It’s not a big problem, it’s just etiquette. We programmers like things sorted into the right places! If this good practice weren’t observed (which it generally is, thankfully), the forums would be swamped with random questions and would become useless as a resource for others.
It’s also never a good idea to criticise people for not helping - it’s their prerogative, after all.
But as I say, it’s not a big deal at all - don’t take anything personally (not that I’m suggesting that you have).
Good luck, and stick with DevIL. It needs to gain some share back from FreeImage. I like a choice, but DevIL may disappear if people don’t use it.