Windows 64-bit PNG/PICT support

Started by
17 comments, last by Yann L 16 years, 10 months ago
Quote:Original post by phil_t
Of course, this doesn't help you with PICT, and it does sound like XP users would need to install .NET 3.0.

No reason to introduce a .NET 3.0 dependency only for PNG support - libpng is perfectly suited to that task without any additional dependencies (except zlib). PICT is an entirely different matter however.
Advertisement
Now I'm very, very frustrated with paintLib. The installation information is not bad, but vague. The build information is pathetic. And some of the few folder references are incorrect and there is definitely a ton of missing information. I downloaded this bugger directly off of www.paintlib.de.

Not only did I need to change the line endings on several files (esp. the paintlib.dsp - a Windows Visual Studio file with Unix ends - strange?), there seems to be a good deal of missing files (plstdpch.cpp, plstdpch.h, pltrace.cpp, and so on). It is a shambles. I had to go to Koders.com to get a couple of the files - and they are newer additions which are not working. One has this:

typedef unsigned long long Mask;

This doesn't fly with Visual Studio - must be a Unixy thing.

zlib, libpng, and libjpeg static libs built without incident. But paintlib is a disaster - though I am indeed not using the other libs. But that doesn't excuse this seemingly overly complex build, some of the errors are just stupid, and missing source/header files are inexcusable!

Might just curb back to PNG support only and use libpng instead - even if it requires some more coding work.

Thanks all,
Robert

FTA: If any of you have links to pay-for libs that support PNG-PICT with one-time commerical usage payment - nothing like $1K or yearly licensing fees - I'd be very grateful. This was my original intent, the problem being finding the darn things. :)
Robert, I fully understand your frustration. I downloaded paintlib and looked at the source. It's a nightmare of bad design and horrific programming style. The fact that even the guy who wrote it doesn't want to maintain it anymore speaks for itself.

So, as far as I see it, you only have three choices left:

1) Somehow try to compile paintlib.
2) Drop PICT support entirely, and rely on libpng for PNG support.
3) Write a PICT decoder yourself.

For the first option, well good luck. This thing looks like highly hacked together open source. It's most certainly not industry ready by any quality standards, and I wouldn't trust it for a second in a comercial product. This could end up in a support nightmare, when your plugin crashes under weird conditions somewhere in the paintlib source. And since it isn't officially maintained anymore since 2005, you'd essentially be on your own.

The second option is obviously the easiest and most painless, but I don't know if the lack of PICT support is acceptable for your product.

If not, then the third might be your only real option. Apple published a very brief note about the PICT format here (from 1985 :) It doesn't look too hard, if you only decode the bitmap information and leave the vector data alone. Note that paintlib will also only decode bitmaps, and not vector images. If you must, you can look into plpictdec.cpp from paintlib to help you figuring out the format (if you manage to look at that source long enough without ripping your eyes out...)

Unfortunately I'm not aware of any commercial grade image libraries capable of reading PICT, except Quicktime. Honestly, I have never ever encountered this format on the PC before.

Good luck !
Quote:Original post by Yann L
Robert, I fully understand your frustration. I downloaded paintlib and looked at the source. It's a nightmare of bad design and horrific programming style. The fact that even the guy who wrote it doesn't want to maintain it anymore speaks for itself.

So, as far as I see it, you only have three choices left:

1) Somehow try to compile paintlib.
2) Drop PICT support entirely, and rely on libpng for PNG support.
3) Write a PICT decoder yourself.

For the first option, well good luck. This thing looks like highly hacked together open source. It's most certainly not industry ready by any quality standards, and I wouldn't trust it for a second in a comercial product. This could end up in a support nightmare, when your plugin crashes under weird conditions somewhere in the paintlib source. And since it isn't officially maintained anymore since 2005, you'd essentially be on your own.

The second option is obviously the easiest and most painless, but I don't know if the lack of PICT support is acceptable for your product.

If not, then the third might be your only real option. Apple published a very brief note about the PICT format here (from 1985 :) It doesn't look too hard, if you only decode the bitmap information and leave the vector data alone. Note that paintlib will also only decode bitmaps, and not vector images. If you must, you can look into plpictdec.cpp from paintlib to help you figuring out the format (if you manage to look at that source long enough without ripping your eyes out...)

Unfortunately I'm not aware of any commercial grade image libraries capable of reading PICT, except Quicktime. Honestly, I have never ever encountered this format on the PC before.

Good luck !


Yann, thank you very much for your help and good advice! And thank you for verifying the lack of usefulness of paintlib.

I'll probably opt for libpng for PNG and hold off on PICT for a while. PICT is a very rare format to see on Windows for sure but in this case it is ubiquitous so there will definitely need to be some level of support for it eventually. Currently, Windows 64-bit users can't see any of the thumbnails as these are the only two formats Poser supports for them and neither works without QuickTime in Cinema 4D - Poser uses its own dlls for various file format support here. I'm pretty certain that only bitmap information is of importance and can ignore any vector concerns therein.

I'll check out that Apple document and the plpictdec.cpp. I have been trying to find code for reading PICT, but it is difficult to find code that isn't tied to Mac programming somehow. Even the now aging book "Encyclopedia of Graphics File Formats" mentions PICT only in passing.

Thank you very much,
Robert
Okay, I'm just setting up the basic class code to load the PNG file. But I'm a little confused by the error handling of libpng. There seems to be two modes: default which calls abort() (don't want that!) and with some form of exception handling (don't want that either).

Since none of the functions return, I'm not exactly clear on how you would go about setting an error value to check *and* circumvent the abort() protocol. libpng might be good, but I disagree with the behavior that on any error the default application behavior should be to exit. I handle much worse situations and keep on truckin' (nice terrorizing error dialog for user, stop process with error, clean up, back to normal) - as long as it isn't a show stopper. :)

Thanks,
Robert
Quote:Original post by Kuroyume0161
Since none of the functions return, I'm not exactly clear on how you would go about setting an error value to check *and* circumvent the abort() protocol. libpng might be good, but I disagree with the behavior that on any error the default application behavior should be to exit.

abort() is the default error handler, you have to override it with your own.

As I mentioned above, libpng is using setjmp() for that. That's a kind of old-school exception handling, a relict from the pre-OOP days. It has nothing in common with modern C++ exception handling except for the name. Essentially, it's nothing more than a global goto with some stack push/pop magic so that the stack frames don't go out of sync when jumping out of a deep function.

There's an example provided with the libpng docs:
Quote:
When libpng encounters an error, it expects to longjmp back
to your routine. Therefore, you will need to call setjmp and pass
your png_jmpbuf(png_ptr). If you read the file from different
routines, you will need to update the jmpbuf field every time you enter
a new routine that will call a png_*() function.

See your documentation of setjmp/longjmp for your compiler for more
information on setjmp/longjmp. See the discussion on libpng error
handling in the Customizing Libpng section below for more information
on the libpng error handling. If an error occurs, and libpng longjmp's
back to your setjmp, you will want to call png_destroy_read_struct() to
free any memory.

if (setjmp(png_jmpbuf(png_ptr)))
{
// This is where you end up, whenever libpng encounters an error !
// Think of it as your error handler. Clean up libpng here and return
// your own error code to the calling function.

png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return( YOUR_ERROR_CODE );
}

I added a few clarifictions in bold.

Just as a reminder, setjmp/longjmp are considered evil by todays standards. But they work quite well in the context of libpng, and won't interfere with your C++ code.
Quote:Original post by Yann L
abort() is the default error handler, you have to override it with your own.

As I mentioned above, libpng is using setjmp() for that. That's a kind of old-school exception handling, a relict from the pre-OOP days. It has nothing in common with modern C++ exception handling except for the name. Essentially, it's nothing more than a global goto with some stack push/pop magic so that the stack frames don't go out of sync when jumping out of a deep function.

There's an example provided with the libpng docs:
Quote:
When libpng encounters an error, it expects to longjmp back
to your routine. Therefore, you will need to call setjmp and pass
your png_jmpbuf(png_ptr). If you read the file from different
routines, you will need to update the jmpbuf field every time you enter
a new routine that will call a png_*() function.

See your documentation of setjmp/longjmp for your compiler for more
information on setjmp/longjmp. See the discussion on libpng error
handling in the Customizing Libpng section below for more information
on the libpng error handling. If an error occurs, and libpng longjmp's
back to your setjmp, you will want to call png_destroy_read_struct() to
free any memory.

if (setjmp(png_jmpbuf(png_ptr)))
{
// This is where you end up, whenever libpng encounters an error !
// Think of it as your error handler. Clean up libpng here and return
// your own error code to the calling function.

png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return( YOUR_ERROR_CODE );
}

I added a few clarifictions in bold.

Just as a reminder, setjmp/longjmp are considered evil by todays standards. But they work quite well in the context of libpng, and won't interfere with your C++ code.


Yes, very old school. ;) I remember this stuff from, eh hem, late-80s/early-90s C coding. That's what frightened me about this alternative to abort() - wasn't sure that it would be 'stable' in a 64-bit C++ environment.

Unfortunately, I missed that bit in the tome of a readme file. I went directly to the Customizing Libpng part where it was a bit more confusing on the process.

Luckily, there is a good example in the 'contrib\visupng' folder which sets up pseudo exception handling with setjmp/longjmp. So far the code has built cleanly and now I'm going to start making connections to see how robust *my* interpretation of the code is in reading the PNG file. Then it will be a matter of putting the image data into the bitmap used by the plugin API - it would be really nice if it were basically a one-to-one relationship but won't be banking on it.

As an aside, I noticed that there is an alternative PNG read/write code available here at GameDev called LodePNG. From what I've read about it, it is somewhat limited and in its infancy so decided not to mess about with it. But it is interesting that the coder has been able to support even zlib compression without zlib - albeit slower.

Once again, your patience and assistance are grately appreciated!

Hopefully the testing will go smoothly and I can finally move onto the myriad features requiring my attention (IK, magnets, point at, and so on).

Thank you very much,
Robert
Dang! is libpng fast!! ;)

The thumbnails are loaded about 10 times faster than using the default Cinema 4D QuickTime support! And with alphas!

No, I'm not just going to use this for 64-bit Windows, I'm going to make it the default PNG loader for thumbnails ~period~. :)

Funny thing is that an alpha channel has to be added to the Cinema 4D bitmap and the rgba set for each individual pixel - and it's still this fast. Methinks that I'm going to drop Maxon a note about switching from QuickTime to libpng for PNG support - with a comparison to show cause.

Yann, thank you so much!

No longer frustrated but elated instead,
Robert
Quote:Original post by Kuroyume0161
Dang! is libpng fast!! ;)

The thumbnails are loaded about 10 times faster than using the default Cinema 4D QuickTime support! And with alphas!

Told you that libpng was good [wink] Glad to hear it worked out well though.

Quote:Original post by Kuroyume0161
Yann, thank you so much!

You're welcome.

This topic is closed to new replies.

Advertisement