The PNG Guide is an eBook based on Greg Roelofs' book, originally published by O'Reilly.



Alternative Approaches

It should go without saying that the program presented here is among the simplest of many possibilities. It would also have been possible to write it monolithically, either as a single readpng function or even as inlined code within main(), which is precisely how the sample code in the libpng documentation reads. Libpng allows user-defined I/O routines (in place of standard file I/O), custom memory allocators, and alternate error handlers to be installed, although there is currently no provision for an error-handling function that returns control to the libpng routine that called it.

There are also other options for the platform-dependent front ends, of course; reading an image from a file is often undesirable. One method in particular is worth mentioning, since it does not appear to be documented anywhere else at the time of this writing. On the 32-bit Windows platform, a ``private'' clipboard may be used to transfer PNG images between applications. The data format is simply the normal PNG stream, beginning with the signature bytes and ending with the IEND chunk. An application like rpng-win would register the private clipboard and then read PNG data from it in the usual way. The following code fragment outlines the essential steps:

    UINT clipbd_format = RegisterClipboardFormat("PNG");

    if (clipbd_format == 0) {
        /* call failed:  use GetLastError() for extended info */
    } else if (OpenClipboard(NULL)) {
        HANDLE handle = GetClipboardData(clipbd_format);

        if (handle == NULL) {
            /* call failed:  use GetLastError() for info */
        } else {
            int data_length = GlobalSize(handle);   /* upper bound */

            if (data_length == 0) {
                /* call failed:  use GetLastError() for info */
            } else {
                BYTE *data_ptr = GlobalLock(handle);

                if (data_ptr == NULL) {
                    /* call failed:  use GetLastError() for info */
                } else {

                    /*================================================*/
                    /* copy PNG data immediately, but don't flag an   */
                    /* error if there are some extra bytes after IEND */
                    /*================================================*/

                    if (GlobalUnlock(handle) == 0) {
                        /* call failed:  use GetLastError() for info */
                    }
                }
            }
        }
        if (CloseClipboard()) {
            /* call failed:  use GetLastError() for info */
        }
    } else {
        /* another window has the clipboard open */
        /* (can use GetOpenClipboardWindow() to get handle to it) */
    }

That one can do something like this in principle isn't new or unusual; what is new is that the "PNG" clipboard has already been implemented in some Microsoft apps, including Office 2000. All any other application needs in order to interoperate via this clipboard is its name and data format, which I've just described. Thanks to John Bowler for providing this information to the PNG Development Group.

In the next chapter, I'll look at a more radical alternative to the basic PNG decoder: a version that feeds libpng data at its own pace, rather than letting libpng read (and possibly wait for) as much data as it wants. Progressive viewers are at the heart of most online browsers, so we'll look at how to write one for PNG images.




Last Update: 2010-Nov-26