Sign in to follow this  
Kuroyume0161

Windows 64-bit PNG/PICT support

Recommended Posts

Since it seems that Apple has decided that making QuickTime (DLL/API/Codecs) Windows 64-bit compatible is a thing only for the distant future, I need alternative libs for PNG and PICT image file support in my C++ plugin versions that run in Windows XP Pro x64 and Vista 64-bit. The application for the API uses QuickTime to support reading these image file formats so it is broken in Windows 64-bit versions of the application. There are some caveats here: Exception handling is a bad thing - the plugin SDK, although C++, does not use or support exceptions. It may work - it may cause crashes. If I can avoid exception handling all the better. I say this realizing that libpng requires exception handling enabled for the lib project. zlib is already available as a lib for my plugin. I've read that libpng builds zlib for itself. Should I just redirect to my current zlib.lib or would that be catastrophic? paintlib is one option here as it supports PICT but it does use libpng for PNG support - again with the exception handling. Yeah, I can try it and see how stable it is but just realize that this is for thumbnail support and will be called many times - any instability will be swift and fatal. This goes to show that even the big guys (SoftImage, Maxon, AutoDesk, ...) place their dependencies on iffy third-party support. By not updating QuickTime, they are hurting them and everyone dependent upon them (plugin developers). I would never entrust my support of features to Apple... Thanks, Robert

Share this post


Link to post
Share on other sites
Quote:
Original post by Kuroyume0161
Exception handling is a bad thing - the plugin SDK, although C++, does not use or support exceptions. It may work - it may cause crashes. If I can avoid exception handling all the better. I say this realizing that libpng requires exception handling enabled for the lib project.

What do you mean by requires exception handling ? libpng is a 100% C library, it doesn't even know what an exception is. It (optionally) uses setjmp however, which basically is a glorified goto. While abominable, it can be easily wrapped in a reader/writer class, without ever affecting anything else in the code.

Quote:
Original post by Kuroyume0161
zlib is already available as a lib for my plugin. I've read that libpng builds zlib for itself. Should I just redirect to my current zlib.lib or would that be catastrophic?

libpng by itself doesn't build zlib, only the supplied makefiles (optionally) do. You can build libpng without rebuilding zlib, and simply link to a static or dynamic version of zlib you happen to have lying around somewhere.

Quote:
Original post by Kuroyume0161
This goes to show that even the big guys (SoftImage, Maxon, AutoDesk, ...) place their dependencies on iffy third-party support. By not updating QuickTime, they are hurting them and everyone dependent upon them (plugin developers). I would never entrust my support of features to Apple...

Well, libpng is a very good library. A lot of commercial software packages use it with success.

Share this post


Link to post
Share on other sites
Quote:
Original post by Yann L
What do you mean by requires exception handling ? libpng is a 100% C library, it doesn't even know what an exception is. It (optionally) uses setjmp however, which basically is a glorified goto. While abominable, it can be easily wrapped in a reader/writer class, without ever affecting anything else in the code.


Maybe I'm confusing libpng with paintlib. paintlib definitely requires exception handling. Since it supports PICT, it is the best course (and only from what I've not found online). I don't know of any other C/C++ lib that supports PICT file reading.

Quote:
libpng by itself doesn't build zlib, only the supplied makefiles (optionally) do. You can build libpng without rebuilding zlib, and simply link to a static or dynamic version of zlib you happen to have lying around somewhere.


That's good. I may try with the zlib (1.2.3) build and see if there are any complaints in the main plugin project having one version of zlib for paintlib and another for the other stuff. Since these should remain isolated it may work - or may conflict. Any thoughts there?

Quote:
Well, libpng is a very good library. A lot of commercial software packages use it with success.


Yep. I'm only driven to use it by Apple's lack of foresight though. What will they do when there are a hundred million users with Windows Vista 64-bit? (My thought - cave-in or lose a ton of business).

Thanks,
Robert

Share this post


Link to post
Share on other sites
Quote:
Original post by Kuroyume0161
Maybe I'm confusing libpng with paintlib. paintlib definitely requires exception handling. Since it supports PICT, it is the best course (and only from what I've not found online). I don't know of any other C/C++ lib that supports PICT file reading.

PICT, being primarily an Mac format, is rarely used on PC. It seems to support vector based images, so reading it is not trivial, and will most likely require a bytecode interpreter of some sort. Maybe you should look into the specification of the format. If the code syntax is similar to postscript or PDF, then you could adapt an existing interpreter, or write your own.

Now, even if paintlib requires exceptions doesn't mean that you need to enable them everywhere in your library. If you know what you are doing, then you can enable exceptions only for certain sub-libraries or even source files. Although doing this will require a great deal of care with your exception handlers, so to avoid memory leaks or crashes when an exception is thrown. Basically, you have to make sure that you stop the stack unwinding (ie. handle all possible exceptions) before an unwinding operation steps out of your plugin source, and into the host applications code.

Out of curiosity, what application are you working with ? If the SDK gets unstable by the simple fact of enabling exceptions, then this is a very bad sign - a sign of very bad design and programming from the side of the host app. Do you have access to its source ?

Quote:

That's good. I may try with the zlib (1.2.3) build and see if there are any complaints in the main plugin project having one version of zlib for paintlib and another for the other stuff. Since these should remain isolated it may work - or may conflict. Any thoughts there?

As long as you link to static zlibs from different modules (ie. libs), there should be no conflict. It will obviously use more memory though. Linking to different dynamic versions zlib is a no-go, as you can imagine.

Share this post


Link to post
Share on other sites
Quote:
Original post by Yann L
PICT, being primarily an Mac format, is rarely used on PC. It seems to support vector based images, so reading it is not trivial, and will most likely require a bytecode interpreter of some sort. Maybe you should look into the specification of the format. If the code syntax is similar to postscript or PDF, then you could adapt an existing interpreter, or write your own.


I wish more rarely. ;) The plugin involves use of Poser libraries which mainly use PNG and RSR (a file on Windows and Resource data on Mac) for thumbnail images of the content. The RSR always embeds a PICT image as a resource here. Unfortunately, there has been some back and forth - Poser itself now uses PNG (and replaces RSRs with them), but some content providers have decided that RSR is better (one is the biggest provider). If you have Poser installed and visit the library content in the Library browser then PNG files are automatically created. But that doesn't suit me as there are users with earlier versions of Poser that don't do that, no Poser (maybe DAZ|Studio), or don't open Poser and get the necessary RSR->PNG conversions.

Quote:
Out of curiosity, what application are you working with ? If the SDK gets unstable by the simple fact of enabling exceptions, then this is a very bad sign - a sign of very bad design and programming from the side of the host app. Do you have access to its source ?


Maxon Cinema 4D. Most of the exception handling instability is exhibited on MacOS X (Universal Binary - Xcode). To my knowledge, it has not caused any problems on the Windows or Mac PPC (CodeWarrior) builds - so this could be a good thing as this fix is explicitly for Windows 64-bit. Only one of the third-party libs utilized it and it was a simple process to change the exceptions into error returns to resolve the instability. paintlib, on the other hand, would be a major task to convert as it is a very much larger library and uses exceptions frequently. Don't really want to mess with it to that extent.

The API is pretty clean but their lack of exception handling criteria is upsetting for someone from a Java background. Though it must be admitted that I'm pushing the API pretty hard as well - there are already a dozen or more plugins in this plugin suite and two third-party libs. Now there'll be a few more (paintlib, libpng, and libjpeg (for JPEG-encoded PICTs)).

Quote:
As long as you link to static zlibs from different modules (ie. libs), there should be no conflict. It will obviously use more memory though. Linking to different dynamic versions zlib is a no-go, as you can imagine.


Good. Yes, this will be a static lib not a dynamic one for sure. Size doesn't matter (well, in this case anyway). Shouldn't increase much - what's a 100KB on a plugin that is 1.5MB already.

Thanks much,
Robert

Share this post


Link to post
Share on other sites
Quote:
Original post by let_bound
ImageMagick can read and write PICT images, as well as a a whole lot of other formats.

GraphicsMagick — a fork of ImageMagick — can handle that format as well.


But ImageMagick is an *application* unto itself and requires an install *and* configuration, even to use the MagicWand API interface (if I misread this, please provide a link) - seems about the same for GraphicsMagick. In essence, these are applications with API interfaces for use in other apps. I will not play 'tech support' for either if users don't install it or misconfigure it (etc.) - many of my users are not native English speakers and I have enough trouble doing my own tech support. ;)

Also similar to QuickTime in this respect. I really don't want to tie to anything external that could be missing or change over time - no matter how well supported. This is why I fought hard to build my own zlib lib in Xcode as too many users were having difficulties with the use of 'expected' libz.dylibs either unfound or varying in version. This comes *with* the MacOS X system and they still can't nail down a version, a location, proper support for a variety of possible code configurations. My build works no matter what.

Thanks,
Robert

Share this post


Link to post
Share on other sites
Well, for PNG you could use the windowscodecs stuff:
http://msdn2.microsoft.com/en-us/library/ms736014.aspx

Although it looks like it requires .NET 3.0 to be installed on XP:
"Windows XP Service Pack 2 (SP2) with Microsoft .Net 3.0, Windows Vista"

Share this post


Link to post
Share on other sites
Quote:
Original post by phil_t
Well, for PNG you could use the windowscodecs stuff:
http://msdn2.microsoft.com/en-us/library/ms736014.aspx

Although it looks like it requires .NET 3.0 to be installed on XP:
"Windows XP Service Pack 2 (SP2) with Microsoft .Net 3.0, Windows Vista"


Hmmm. I have Visual Studio 2005 Pro for building for the 64-bit environment. .Net 3.0 could be a concern if it is a required component install for the users to get the functionality. As long as it is something available for Vista and x64 as a component install that wouldn't be a big problem.

But would this work under Windows XP Pro x64 and Vista 64-bit as it says 'Win32' rather explicitly? This is for a 64-bit application running on Windows 64-bit.

I don't 'do' Windows API programming - avoid it like the plague (same for MacOS - but I've had to do some to get at Resource data for this particular plugin). That's why I went from C to Java. C++ for the plugin SDK was non-optional. :)

Actually, I should be saying 'plugins'. There are Ltd and Pro versions, two separate products which have similar issues with PNG-PICT.

Thanks,
Robert

Share this post


Link to post
Share on other sites
I assume it works on 64 bit. The 32 in Win32 doesn't refer to the processor architecture (well, not anymore at least... I guess it was important when we went from 16bit to 32bit).

Of course, this doesn't help you with PICT, and it does sound like XP users would need to install .NET 3.0.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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. :)

Share this post


Link to post
Share on other sites
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 !

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this