Author Topic: C++ loading PNG files  (Read 24787 times)

0 Members and 1 Guest are viewing this topic.

Offline SoldierBoy

  • ZX 81
  • *
  • Posts: 10
  • Karma: 5
    • View Profile
C++ loading PNG files
« 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

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: C++ loading PNG files
« Reply #1 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
Challenge Trophies Won:

Offline SoldierBoy

  • ZX 81
  • *
  • Posts: 10
  • Karma: 5
    • View Profile
Re: C++ loading PNG files
« Reply #2 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!


Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: C++ loading PNG files
« Reply #3 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
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: C++ loading PNG files
« Reply #4 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.
Challenge Trophies Won:

Offline va!n

  • Pentium
  • *****
  • Posts: 1432
  • Karma: 109
    • View Profile
    • http://www.secretly.de
Re: C++ loading PNG files
« Reply #5 on: August 30, 2007 »
i think using the windows OLE stuff is the best way... and you dont have bloody filesizes ^^
- hp EliteBook 8540p, 4 GB RAM, Windows 8.1 x64
- Asus P5Q, Intel Q8200, 6 GB DDR2, Radeon 4870, Windows 8.1 x64
http://www.secretly.de
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: C++ loading PNG files
« Reply #6 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
Challenge Trophies Won:

Offline taj

  • Bytes hurt
  • DBF Aficionado
  • ******
  • Posts: 4810
  • Karma: 189
  • Scene there, done that.
    • View Profile
Re: C++ loading PNG files
« Reply #7 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 :-)
Challenge Trophies Won:

Offline SoldierBoy

  • ZX 81
  • *
  • Posts: 10
  • Karma: 5
    • View Profile
Re: C++ loading PNG files
« Reply #8 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


Offline SoldierBoy

  • ZX 81
  • *
  • Posts: 10
  • Karma: 5
    • View Profile
Re: C++ loading PNG files
« Reply #9 on: August 31, 2007 »
Helps if I actually attach the damn file...

Here it is.

SB/ICC207


Offline taj

  • Bytes hurt
  • DBF Aficionado
  • ******
  • Posts: 4810
  • Karma: 189
  • Scene there, done that.
    • View Profile
Re: C++ loading PNG files
« Reply #10 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
Challenge Trophies Won:

Offline va!n

  • Pentium
  • *****
  • Posts: 1432
  • Karma: 109
    • View Profile
    • http://www.secretly.de
Re: C++ loading PNG files
« Reply #11 on: August 31, 2007 »
@SoldierBoy:
Thanks and K++ for sharing your source.  :goodpost:
- hp EliteBook 8540p, 4 GB RAM, Windows 8.1 x64
- Asus P5Q, Intel Q8200, 6 GB DDR2, Radeon 4870, Windows 8.1 x64
http://www.secretly.de
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: C++ loading PNG files
« Reply #12 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
Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17409
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: C++ loading PNG files
« Reply #13 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.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline SoldierBoy

  • ZX 81
  • *
  • Posts: 10
  • Karma: 5
    • View Profile
Re: C++ loading PNG files
« Reply #14 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


Offline nystep

  • ZX 81
  • *
  • Posts: 19
  • Karma: 4
    • View Profile
Re: C++ loading PNG files
« Reply #15 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..

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: C++ loading PNG files
« Reply #16 on: September 18, 2007 »
Thanks for posting!

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: C++ loading PNG files
« Reply #17 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?.
« Last Edit: October 24, 2007 by ninogenio »
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: C++ loading PNG files
« Reply #18 on: October 24, 2007 »
JPG too, at the very least.

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: C++ loading PNG files
« Reply #19 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!
Challenge Trophies Won: