Dark Bit Factory & Gravity

PROGRAMMING => C / C++ /C# => Topic started by: SoldierBoy on August 30, 2007

Title: C++ loading PNG files
Post by: SoldierBoy on August 30, 2007
ok, I've searched and searched and searched....and have yet to find a clean, usable, C++ PNG reader!!!!

What does everyone here use to load images in?

I'm really seeking just something easy.  Something that doesn't have a huge library attatched to it.

I'm using PixelToaster for my display buffer.  I'm happy with my performance at the moment, but want to do some additional testing.

HELP please? :)

BTW, I was a member here years ago....Hello Shockwave and Clyde and Everyone else!!!
SoldierBoy/ICC2007
Infinity Never Returned haha
Title: Re: C++ loading PNG files
Post by: Jim on August 30, 2007
You can use libpng+zlib, but that can be difficult.  Another possibility is to check out D3DX image loading.

Yet another possibility is I think Windows OleLoadPicture() can do it, here's a snippet out of some code I wrote
Code: [Select]
class Sprite
{
public:
~Sprite();
Sprite(const char *);
private:
void *read_bmp(const char *filename, long *lenp=NULL);
unsigned int *pix;
unsigned int width, height;
};
void *Sprite::read_bmp(const char *filename, long *lenp)
{
FILE *f;
long len;
void *file=NULL;

fopen_s(&f, filename, "rb");
if (f)
{
fseek(f, 0, SEEK_END);
len = ftell(f);
if (lenp) *lenp = len;
fseek(f, 0, SEEK_SET);

file = new char[len];
if (file)
fread(file, 1, len, f);

fclose(f);
}
return file;
}

Sprite::Sprite(const char *fname)
{
HDC hdc;
static struct
{
BITMAPINFO bmpi;
RGBQUAD masks[3];
} header;
IPicture *picture=NULL;
HBITMAP bmp;
ULONG cnt;

memset(&header.bmpi, 0, sizeof header.bmpi);
header.bmpi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

bmp = (HBITMAP)LoadImage(NULL, fname, IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);

if (!bmp)
{
IStream *istm;
HRESULT err;
HGLOBAL hMem;
void *lpMem;
long size;
void *img;

img = read_bmp(fname, &size);
assert(img);
hMem = GlobalAlloc(GMEM_MOVEABLE, size);
assert(hMem);
lpMem = GlobalLock(hMem);
assert(lpMem);
memcpy(lpMem, img, size);
GlobalUnlock(hMem);
delete [] img;

err = CreateStreamOnHGlobal(hMem, FALSE, &istm);
assert(err == S_OK);
err = OleLoadPicture(istm, size, TRUE, IID_IPicture, (void **)&picture);
GlobalFree(hMem);
assert(err == S_OK);
cnt = istm->Release();
picture->get_Handle((OLE_HANDLE*)&bmp);
}

hdc = GetDC(NULL);

GetDIBits(hdc, bmp, 0,0, NULL, &header.bmpi, 0);

width = header.bmpi.bmiHeader.biWidth;
height = header.bmpi.bmiHeader.biHeight;

pix = new unsigned int[width * height];
assert(pix != NULL);

header.bmpi.bmiHeader.biBitCount = 32;
GetDIBits(hdc, bmp, 0, height, pix, &header.bmpi, DIB_RGB_COLORS);

ReleaseDC(NULL, hdc);

if (picture)
cnt = picture->Release();
else
DeleteObject(bmp);

//bitmaps are stored upside down (doh!)
unsigned int *line0 = pix;
unsigned int *lineN = pix+(height-1)*width;
unsigned int *tmpln = new unsigned int[width];
unsigned int y;
for (y = 0; y < height/2; y++)
{
memcpy(tmpln, line0, width * sizeof *pix);
memcpy(line0, lineN, width * sizeof *pix);
memcpy(lineN, tmpln, width * sizeof *pix);
line0 += width;
lineN -= width;
}
delete [] tmpln;
}

That probably won't compile right out of the box, but it shows the technique.  It should load nearly all Windows format images too.

Welcome back to the forum!

Jim
Title: Re: C++ loading PNG files
Post by: SoldierBoy on August 30, 2007
Thanks Jim!  I was hoping you would reply! :)  And thank you for the welcome back.....

I was really hoping that someone had just a complete source file for reading, but oh well. :)

I initially went the libpng route, and even found a C++ wrapper for it, but then again, it was incomplete.....

Even just using libpng, seemed overtly complex. 

And the ultimate goal of this is to have 1 file exe, which seems to be the latest rage around here.

I'm not in this to make a 1k or 4k....haha.....so I don't really care about filesize too much.

I just want the cleanliness(???) of it all.

My job brought me into this C++ world.  So I thought I would try and bring C++ into my demo (hobby) world....hahaha

But I tell you what, its so tempting to jump into the FREEBASIC world, since even it has pnglib includes and samples.....

I'll most definately be checking out that source you posted.

Thank you!
SoldierBoy/ICC 1995-2007
Even non-Legends Live On!

Title: Re: C++ loading PNG files
Post by: Jim on August 30, 2007
You'll need these includes
Code: [Select]
#include <windows.h>
#include <ole2.h>
#include <ocidl.h>
#include <olectl.h>
#include <gl/gl.h>

#include <stdio.h>
#include <string.h>
#include <assert.h>

It's really simple then to load a png, you just have

Code: [Select]
Sprite *myimage;
myimage = new Sprite("file.png");

Then
myimage->img points to the 32bit pixels.

Jim
Title: Re: C++ loading PNG files
Post by: ninogenio on August 30, 2007
i have done it the hard way with libpng and zlib before give me till later and ill post up a working loader its a bit of a faffle doing it this way though.
Title: Re: C++ loading PNG files
Post by: va!n on August 30, 2007
i think using the windows OLE stuff is the best way... and you dont have bloody filesizes ^^
Title: Re: C++ loading PNG files
Post by: ninogenio on August 30, 2007
here is one the hard way its done in dev c using jims double buffered gdi window libpng and zlib ive made it as simple as i can and its fairly practical.

hope it helps.

http://dbfinteractive.com/index.php?action=tpmod;dl=item64
Title: Re: C++ loading PNG files
Post by: taj on August 30, 2007
D3DX loads pngs, jpgs and of course :-P bmps. Given its 3-4 lines of code to setup DX and 2-3 lines of code to load an image, I dont think it gets any smaller or easier.

Then you go into dll hell of course :-)
Title: Re: C++ loading PNG files
Post by: SoldierBoy on August 31, 2007
Thanks for everybody's help!

Jim, nenogenio, va!n, chris

Thanks guys, I'm going to look at both of those options!

Thanks again.

This is how I ended up doing it:
included this file into my project: http://nothings.org/stb_image.c

and wrote this function to load a .png and put into my buffer:

Code: [Select]
bool loadPNG( std::string filename,  int & width, int & height, int &bitdepth, vector<Pixel> & pixels){

unsigned int index = 0;

unsigned char *data = stbi_load((char *)filename.c_str(), &width, &height, &bitdepth, 0);
if (!data) return false;
// convert 24 bit image pixels to floating point color

pixels.resize( width * height );

for ( int y = 0; y < height; ++y )
{
for ( int x = 0; x < width; ++x )
{
Pixel & pixel = pixels[index];

pixel.r = data[index*3+0] * 1.0f / 255.0f;
pixel.g = data[index*3+1] * 1.0f / 255.0f;
pixel.b = data[index*3+2] * 1.0f / 255.0f;
pixel.a = data[index*3+3] * 1.0f / 255.0f;

++index;

}
}

return true;
}



I've attatched the stb_image.c file to this post.  Maybe it will of some use to others....

Thanks!
SoldierBoy/ICC2007

Title: Re: C++ loading PNG files
Post by: SoldierBoy on August 31, 2007
Helps if I actually attach the damn file...

Here it is.

SB/ICC207

Title: Re: C++ loading PNG files
Post by: taj on August 31, 2007
Interesting find soldier boy (karma++). My guess is STB stands for set top box which is my business. We only ever use PNG and JPG so this code is very cool for us. It could save loads of space over libpng and libjpg which are just overkill and hellishly difficult to use.

Chris
Title: Re: C++ loading PNG files
Post by: va!n on August 31, 2007
@SoldierBoy:
Thanks and K++ for sharing your source.  :goodpost:
Title: Re: C++ loading PNG files
Post by: Jim on September 01, 2007
Wow!  Cracking bit of code that!  I wrote one for jpeg a few years ago, which is about 10th the size of jpeg6b (but slower), but this does PNG and TGA too :D
K+
Jim
Title: Re: C++ loading PNG files
Post by: Shockwave on September 01, 2007
How to get a load of good Karma and make a lot of programmers happy in one hit!
Thanks very much for posting the code, it will help a lot of people as everyone needs to load pictures at some point.
Title: Re: C++ loading PNG files
Post by: SoldierBoy on September 04, 2007
Thanks for the Karma guys!

I take no credit for the code, its just some random shit that Google found.

But thanks for Sean Barrett for the public domain code that we can all use.

Look for more from me, when I get these Pixels Toasting.....

SoldierBoy/ICC 2007

Title: Re: C++ loading PNG files
Post by: nystep on September 17, 2007
wow :)

i've been fighting with libpng and zlib, and more recently with the free independant jpeg group to get a png and jpeg reader. It took aaaages to make the png low level reader work fine. I can't beleive that it can be made so simple in OLE. great work Jim.

just in case you're interrested, my image loader stands there, but it requires external libraries of course :/ :
http://glsilent.svn.sourceforge.net/viewvc/glsilent/src/img/img_Image.cxx?revision=10&view=markup

you can feel free of browsing also arround all my engine sources. i doubt the opengl wrapper will make anyone interrested, this engine is getting old fashioned. I've been thinking of doing some redesign from scratch, but i don't know if i should make a software 3d engine and play with it on symbian/psp/nds, or switch to managed dx and c#.

wait and see..
Title: Re: C++ loading PNG files
Post by: Jim on September 18, 2007
Thanks for posting!

Jim
Title: Re: C++ loading PNG files
Post by: ninogenio on October 24, 2007
@jim ive implimented your olepicture loader and it all builds fine but when i run it get an assert error from olepictureload so i think the my stream isnt in the right format but my png images are all just 24 bit microsoft paint png`s that my libpng loader works fine with.

it says in msdn that olepictureload can only be used for BMP (bitmap), WMF (metafile), or ICO (icon) format but im guessing you can pass it others?.
Title: Re: C++ loading PNG files
Post by: Jim on October 24, 2007
JPG too, at the very least.

Jim
Title: Re: C++ loading PNG files
Post by: ninogenio on October 24, 2007
i must have screwd up my png images then, ill do some other test`s, cheers for the great loader btw!
Title: Re: C++ loading PNG files
Post by: Jim on October 24, 2007
Man, I can't swear it loads png...

Jim
Title: Re: C++ loading PNG files
Post by: ninogenio on October 24, 2007
yeah it loads jpg but not png which is a bit of a shame , but even jpg is cool!