/src/FreeImage/Source/LibPNG/libpng-manual.txt
https://bitbucket.org/cabalistic/ogredeps/ · Plain Text · 4628 lines · 3570 code · 1058 blank · 0 comment · 0 complexity · 701b19a436624e206255c9cb8c4169b1 MD5 · raw file
Large files are truncated click here to view the full file
- libpng-manual.txt - A description on how to use and modify libpng
- libpng version 1.5.9 - February 18, 2012
- Updated and distributed by Glenn Randers-Pehrson
- <glennrp at users.sourceforge.net>
- Copyright (c) 1998-2011 Glenn Randers-Pehrson
- This document is released under the libpng license.
- For conditions of distribution and use, see the disclaimer
- and license in png.h
- Based on:
- libpng versions 0.97, January 1998, through 1.5.9 - February 18, 2012
- Updated and distributed by Glenn Randers-Pehrson
- Copyright (c) 1998-2011 Glenn Randers-Pehrson
- libpng 1.0 beta 6 version 0.96 May 28, 1997
- Updated and distributed by Andreas Dilger
- Copyright (c) 1996, 1997 Andreas Dilger
- libpng 1.0 beta 2 - version 0.88 January 26, 1996
- For conditions of distribution and use, see copyright
- notice in png.h. Copyright (c) 1995, 1996 Guy Eric
- Schalnat, Group 42, Inc.
- Updated/rewritten per request in the libpng FAQ
- Copyright (c) 1995, 1996 Frank J. T. Wojcik
- December 18, 1995 & January 20, 1996
- I. Introduction
- This file describes how to use and modify the PNG reference library
- (known as libpng) for your own use. There are five sections to this
- file: introduction, structures, reading, writing, and modification and
- configuration notes for various special platforms. In addition to this
- file, example.c is a good starting point for using the library, as
- it is heavily commented and should include everything most people
- will need. We assume that libpng is already installed; see the
- INSTALL file for instructions on how to install libpng.
- For examples of libpng usage, see the files "example.c", "pngtest.c",
- and the files in the "contrib" directory, all of which are included in
- the libpng distribution.
- Libpng was written as a companion to the PNG specification, as a way
- of reducing the amount of time and effort it takes to support the PNG
- file format in application programs.
- The PNG specification (second edition), November 2003, is available as
- a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at
- <http://www.w3.org/TR/2003/REC-PNG-20031110/
- The W3C and ISO documents have identical technical content.
- The PNG-1.2 specification is available at
- <http://www.libpng.org/pub/png/documents/>. It is technically equivalent
- to the PNG specification (second edition) but has some additional material.
- The PNG-1.0 specification is available
- as RFC 2083 <http://www.libpng.org/pub/png/documents/> and as a
- W3C Recommendation <http://www.w3.org/TR/REC.png.html>.
- Some additional chunks are described in the special-purpose public chunks
- documents at <http://www.libpng.org/pub/png/documents/>.
- Other information
- about PNG, and the latest version of libpng, can be found at the PNG home
- page, <http://www.libpng.org/pub/png/>.
- Most users will not have to modify the library significantly; advanced
- users may want to modify it more. All attempts were made to make it as
- complete as possible, while keeping the code easy to understand.
- Currently, this library only supports C. Support for other languages
- is being considered.
- Libpng has been designed to handle multiple sessions at one time,
- to be easily modifiable, to be portable to the vast majority of
- machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy
- to use. The ultimate goal of libpng is to promote the acceptance of
- the PNG file format in whatever way possible. While there is still
- work to be done (see the TODO file), libpng should cover the
- majority of the needs of its users.
- Libpng uses zlib for its compression and decompression of PNG files.
- Further information about zlib, and the latest version of zlib, can
- be found at the zlib home page, <http://www.info-zip.org/pub/infozip/zlib/>.
- The zlib compression utility is a general purpose utility that is
- useful for more than PNG files, and can be used without libpng.
- See the documentation delivered with zlib for more details.
- You can usually find the source files for the zlib utility wherever you
- find the libpng source files.
- Libpng is thread safe, provided the threads are using different
- instances of the structures. Each thread should have its own
- png_struct and png_info instances, and thus its own image.
- Libpng does not protect itself against two threads using the
- same instance of a structure.
- II. Structures
- There are two main structures that are important to libpng, png_struct
- and png_info. Both are internal structures that are no longer exposed
- in the libpng interface (as of libpng 1.5.0).
- The png_info structure is designed to provide information about the
- PNG file. At one time, the fields of png_info were intended to be
- directly accessible to the user. However, this tended to cause problems
- with applications using dynamically loaded libraries, and as a result
- a set of interface functions for png_info (the png_get_*() and png_set_*()
- functions) was developed, and direct access to the png_info fields was
- deprecated..
- The png_struct structure is the object used by the library to decode a
- single image. As of 1.5.0 this structure is also not exposed.
- Almost all libpng APIs require a pointer to a png_struct as the first argument.
- Many (in particular the png_set and png_get APIs) also require a pointer
- to png_info as the second argument. Some application visible macros
- defined in png.h designed for basic data access (reading and writing
- integers in the PNG format) don't take a png_info pointer, but it's almost
- always safe to assume that a (png_struct*) has to be passed to call an API
- function.
- You can have more than one png_info structure associated with an image,
- as illustrated in pngtest.c, one for information valid prior to the
- IDAT chunks and another (called "end_info" below) for things after them.
- The png.h header file is an invaluable reference for programming with libpng.
- And while I'm on the topic, make sure you include the libpng header file:
- #include <png.h>
- and also (as of libpng-1.5.0) the zlib header file, if you need it:
- #include <zlib.h>
- Types
- The png.h header file defines a number of integral types used by the
- APIs. Most of these are fairly obvious; for example types corresponding
- to integers of particular sizes and types for passing color values.
- One exception is how non-integral numbers are handled. For application
- convenience most APIs that take such numbers have C (double) arguments,
- however internally PNG, and libpng, use 32 bit signed integers and encode
- the value by multiplying by 100,000. As of libpng 1.5.0 a convenience
- macro PNG_FP_1 is defined in png.h along with a type (png_fixed_point)
- which is simply (png_int_32).
- All APIs that take (double) arguments also have a matching API that
- takes the corresponding fixed point integer arguments. The fixed point
- API has the same name as the floating point one with "_fixed" appended.
- The actual range of values permitted in the APIs is frequently less than
- the full range of (png_fixed_point) (-21474 to +21474). When APIs require
- a non-negative argument the type is recorded as png_uint_32 above. Consult
- the header file and the text below for more information.
- Special care must be take with sCAL chunk handling because the chunk itself
- uses non-integral values encoded as strings containing decimal floating point
- numbers. See the comments in the header file.
- Configuration
- The main header file function declarations are frequently protected by C
- preprocessing directives of the form:
- #ifdef PNG_feature_SUPPORTED
- declare-function
- #endif
- ...
- #ifdef PNG_feature_SUPPORTED
- use-function
- #endif
- The library can be built without support for these APIs, although a
- standard build will have all implemented APIs. Application programs
- should check the feature macros before using an API for maximum
- portability. From libpng 1.5.0 the feature macros set during the build
- of libpng are recorded in the header file "pnglibconf.h" and this file
- is always included by png.h.
- If you don't need to change the library configuration from the default, skip to
- the next section ("Reading").
- Notice that some of the makefiles in the 'scripts' directory and (in 1.5.0) all
- of the build project files in the 'projects' directory simply copy
- scripts/pnglibconf.h.prebuilt to pnglibconf.h. This means that these build
- systems do not permit easy auto-configuration of the library - they only
- support the default configuration.
- The easiest way to make minor changes to the libpng configuration when
- auto-configuration is supported is to add definitions to the command line
- using (typically) CPPFLAGS. For example:
- CPPFLAGS=-DPNG_NO_FLOATING_ARITHMETIC
- will change the internal libpng math implementation for gamma correction and
- other arithmetic calculations to fixed point, avoiding the need for fast
- floating point support. The result can be seen in the generated pnglibconf.h -
- make sure it contains the changed feature macro setting.
- If you need to make more extensive configuration changes - more than one or two
- feature macro settings - you can either add -DPNG_USER_CONFIG to the build
- command line and put a list of feature macro settings in pngusr.h or you can set
- DFA_XTRA (a makefile variable) to a file containing the same information in the
- form of 'option' settings.
- A. Changing pnglibconf.h
- A variety of methods exist to build libpng. Not all of these support
- reconfiguration of pnglibconf.h. To reconfigure pnglibconf.h it must either be
- rebuilt from scripts/pnglibconf.dfa using awk or it must be edited by hand.
- Hand editing is achieved by copying scripts/pnglibconf.h.prebuilt to
- pnglibconf.h and changing the lines defining the supported features, paying
- very close attention to the 'option' information in scripts/pnglibconf.dfa
- that describes those features and their requirements. This is easy to get
- wrong.
- B. Configuration using DFA_XTRA
- Rebuilding from pnglibconf.dfa is easy if a functioning 'awk', or a later
- variant such as 'nawk' or 'gawk', is available. The configure build will
- automatically find an appropriate awk and build pnglibconf.h.
- The scripts/pnglibconf.mak file contains a set of make rules for doing the
- same thing if configure is not used, and many of the makefiles in the scripts
- directory use this approach.
- When rebuilding simply write a new file containing changed options and set
- DFA_XTRA to the name of this file. This causes the build to append the new file
- to the end of scripts/pnglibconf.dfa. The pngusr.dfa file should contain lines
- of the following forms:
- everything = off
- This turns all optional features off. Include it at the start of pngusr.dfa to
- make it easier to build a minimal configuration. You will need to turn at least
- some features on afterward to enable either reading or writing code, or both.
- option feature on
- option feature off
- Enable or disable a single feature. This will automatically enable other
- features required by a feature that is turned on or disable other features that
- require a feature which is turned off. Conflicting settings will cause an error
- message to be emitted by awk.
- setting feature default value
- Changes the default value of setting 'feature' to 'value'. There are a small
- number of settings listed at the top of pnglibconf.h, they are documented in the
- source code. Most of these values have performance implications for the library
- but most of them have no visible effect on the API. Some can also be overridden
- from the API.
- This method of building a customized pnglibconf.h is illustrated in
- contrib/pngminim/*. See the "$(PNGCONF):" target in the makefile and
- pngusr.dfa in these directories.
- C. Configuration using PNG_USR_CONFIG
- If -DPNG_USR_CONFIG is added to the CFLAGS when pnglibconf.h is built the file
- pngusr.h will automatically be included before the options in
- scripts/pnglibconf.dfa are processed. Your pngusr.h file should contain only
- macro definitions turning features on or off or setting settings.
- Apart from the global setting "everything = off" all the options listed above
- can be set using macros in pngusr.h:
- #define PNG_feature_SUPPORTED
- is equivalent to:
- option feature on
- #define PNG_NO_feature
- is equivalent to:
- option feature off
- #define PNG_feature value
- is equivalent to:
- setting feature default value
- Notice that in both cases, pngusr.dfa and pngusr.h, the contents of the
- pngusr file you supply override the contents of scripts/pnglibconf.dfa
- If confusing or incomprehensible behavior results it is possible to
- examine the intermediate file pnglibconf.dfn to find the full set of
- dependency information for each setting and option. Simply locate the
- feature in the file and read the C comments that precede it.
- This method is also illustrated in the contrib/pngminim/* makefiles and
- pngusr.h.
- III. Reading
- We'll now walk you through the possible functions to call when reading
- in a PNG file sequentially, briefly explaining the syntax and purpose
- of each one. See example.c and png.h for more detail. While
- progressive reading is covered in the next section, you will still
- need some of the functions discussed in this section to read a PNG
- file.
- Setup
- You will want to do the I/O initialization(*) before you get into libpng,
- so if it doesn't work, you don't have much to undo. Of course, you
- will also want to insure that you are, in fact, dealing with a PNG
- file. Libpng provides a simple check to see if a file is a PNG file.
- To use it, pass in the first 1 to 8 bytes of the file to the function
- png_sig_cmp(), and it will return 0 (false) if the bytes match the
- corresponding bytes of the PNG signature, or nonzero (true) otherwise.
- Of course, the more bytes you pass in, the greater the accuracy of the
- prediction.
- If you are intending to keep the file pointer open for use in libpng,
- you must ensure you don't read more than 8 bytes from the beginning
- of the file, and you also have to make a call to png_set_sig_bytes_read()
- with the number of bytes you read from the beginning. Libpng will
- then only check the bytes (if any) that your program didn't read.
- (*): If you are not using the standard I/O functions, you will need
- to replace them with custom functions. See the discussion under
- Customizing libpng.
- FILE *fp = fopen(file_name, "rb");
- if (!fp)
- {
- return (ERROR);
- }
- fread(header, 1, number, fp);
- is_png = !png_sig_cmp(header, 0, number);
- if (!is_png)
- {
- return (NOT_PNG);
- }
- Next, png_struct and png_info need to be allocated and initialized. In
- order to ensure that the size of these structures is correct even with a
- dynamically linked libpng, there are functions to initialize and
- allocate the structures. We also pass the library version, optional
- pointers to error handling functions, and a pointer to a data struct for
- use by the error functions, if necessary (the pointer and functions can
- be NULL if the default error handlers are to be used). See the section
- on Changes to Libpng below regarding the old initialization functions.
- The structure allocation functions quietly return NULL if they fail to
- create the structure, so your application should check for that.
- png_structp png_ptr = png_create_read_struct
- (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
- user_error_fn, user_warning_fn);
- if (!png_ptr)
- return (ERROR);
- png_infop info_ptr = png_create_info_struct(png_ptr);
- if (!info_ptr)
- {
- png_destroy_read_struct(&png_ptr,
- (png_infopp)NULL, (png_infopp)NULL);
- return (ERROR);
- }
- If you want to use your own memory allocation routines,
- use a libpng that was built with PNG_USER_MEM_SUPPORTED defined, and use
- png_create_read_struct_2() instead of png_create_read_struct():
- png_structp png_ptr = png_create_read_struct_2
- (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
- user_error_fn, user_warning_fn, (png_voidp)
- user_mem_ptr, user_malloc_fn, user_free_fn);
- The error handling routines passed to png_create_read_struct()
- and the memory alloc/free routines passed to png_create_struct_2()
- are only necessary if you are not using the libpng supplied error
- handling and memory alloc/free functions.
- 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 longjmp buffer 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)))
- {
- png_destroy_read_struct(&png_ptr, &info_ptr,
- &end_info);
- fclose(fp);
- return (ERROR);
- }
- Pass (png_infopp)NULL instead of &end_info if you didn't create
- an end_info structure.
- If you would rather avoid the complexity of setjmp/longjmp issues,
- you can compile libpng with PNG_NO_SETJMP, in which case
- errors will result in a call to PNG_ABORT() which defaults to abort().
- You can #define PNG_ABORT() to a function that does something
- more useful than abort(), as long as your function does not
- return.
- Now you need to set up the input code. The default for libpng is to
- use the C function fread(). If you use this, you will need to pass a
- valid FILE * in the function png_init_io(). Be sure that the file is
- opened in binary mode. If you wish to handle reading data in another
- way, you need not call the png_init_io() function, but you must then
- implement the libpng I/O methods discussed in the Customizing Libpng
- section below.
- png_init_io(png_ptr, fp);
- If you had previously opened the file and read any of the signature from
- the beginning in order to see if this was a PNG file, you need to let
- libpng know that there are some bytes missing from the start of the file.
- png_set_sig_bytes(png_ptr, number);
- You can change the zlib compression buffer size to be used while
- reading compressed data with
- png_set_compression_buffer_size(png_ptr, buffer_size);
- where the default size is 8192 bytes. Note that the buffer size
- is changed immediately and the buffer is reallocated immediately,
- instead of setting a flag to be acted upon later.
- If you want CRC errors to be handled in a different manner than
- the default, use
- png_set_crc_action(png_ptr, crit_action, ancil_action);
- The values for png_set_crc_action() say how libpng is to handle CRC errors in
- ancillary and critical chunks, and whether to use the data contained
- therein. Note that it is impossible to "discard" data in a critical
- chunk.
- Choices for (int) crit_action are
- PNG_CRC_DEFAULT 0 error/quit
- PNG_CRC_ERROR_QUIT 1 error/quit
- PNG_CRC_WARN_USE 3 warn/use data
- PNG_CRC_QUIET_USE 4 quiet/use data
- PNG_CRC_NO_CHANGE 5 use the current value
- Choices for (int) ancil_action are
- PNG_CRC_DEFAULT 0 error/quit
- PNG_CRC_ERROR_QUIT 1 error/quit
- PNG_CRC_WARN_DISCARD 2 warn/discard data
- PNG_CRC_WARN_USE 3 warn/use data
- PNG_CRC_QUIET_USE 4 quiet/use data
- PNG_CRC_NO_CHANGE 5 use the current value
- Setting up callback code
- You can set up a callback function to handle any unknown chunks in the
- input stream. You must supply the function
- read_chunk_callback(png_structp png_ptr,
- png_unknown_chunkp chunk);
- {
- /* The unknown chunk structure contains your
- chunk data, along with similar data for any other
- unknown chunks: */
- png_byte name[5];
- png_byte *data;
- png_size_t size;
- /* Note that libpng has already taken care of
- the CRC handling */
- /* put your code here. Search for your chunk in the
- unknown chunk structure, process it, and return one
- of the following: */
- return (-n); /* chunk had an error */
- return (0); /* did not recognize */
- return (n); /* success */
- }
- (You can give your function another name that you like instead of
- "read_chunk_callback")
- To inform libpng about your function, use
- png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr,
- read_chunk_callback);
- This names not only the callback function, but also a user pointer that
- you can retrieve with
- png_get_user_chunk_ptr(png_ptr);
- If you call the png_set_read_user_chunk_fn() function, then all unknown
- chunks will be saved when read, in case your callback function will need
- one or more of them. This behavior can be changed with the
- png_set_keep_unknown_chunks() function, described below.
- At this point, you can set up a callback function that will be
- called after each row has been read, which you can use to control
- a progress meter or the like. It's demonstrated in pngtest.c.
- You must supply a function
- void read_row_callback(png_structp png_ptr,
- png_uint_32 row, int pass);
- {
- /* put your code here */
- }
- (You can give it another name that you like instead of "read_row_callback")
- To inform libpng about your function, use
- png_set_read_status_fn(png_ptr, read_row_callback);
- When this function is called the row has already been completely processed and
- the 'row' and 'pass' refer to the next row to be handled. For the
- non-interlaced case the row that was just handled is simply one less than the
- passed in row number, and pass will always be 0. For the interlaced case the
- same applies unless the row value is 0, in which case the row just handled was
- the last one from one of the preceding passes. Because interlacing may skip a
- pass you cannot be sure that the preceding pass is just 'pass-1', if you really
- need to know what the last pass is record (row,pass) from the callback and use
- the last recorded value each time.
- As with the user transform you can find the output row using the
- PNG_ROW_FROM_PASS_ROW macro.
- Unknown-chunk handling
- Now you get to set the way the library processes unknown chunks in the
- input PNG stream. Both known and unknown chunks will be read. Normal
- behavior is that known chunks will be parsed into information in
- various info_ptr members while unknown chunks will be discarded. This
- behavior can be wasteful if your application will never use some known
- chunk types. To change this, you can call:
- png_set_keep_unknown_chunks(png_ptr, keep,
- chunk_list, num_chunks);
- keep - 0: default unknown chunk handling
- 1: ignore; do not keep
- 2: keep only if safe-to-copy
- 3: keep even if unsafe-to-copy
- You can use these definitions:
- PNG_HANDLE_CHUNK_AS_DEFAULT 0
- PNG_HANDLE_CHUNK_NEVER 1
- PNG_HANDLE_CHUNK_IF_SAFE 2
- PNG_HANDLE_CHUNK_ALWAYS 3
- chunk_list - list of chunks affected (a byte string,
- five bytes per chunk, NULL or '\0' if
- num_chunks is 0)
- num_chunks - number of chunks affected; if 0, all
- unknown chunks are affected. If nonzero,
- only the chunks in the list are affected
- Unknown chunks declared in this way will be saved as raw data onto a
- list of png_unknown_chunk structures. If a chunk that is normally
- known to libpng is named in the list, it will be handled as unknown,
- according to the "keep" directive. If a chunk is named in successive
- instances of png_set_keep_unknown_chunks(), the final instance will
- take precedence. The IHDR and IEND chunks should not be named in
- chunk_list; if they are, libpng will process them normally anyway.
- If you know that your application will never make use of some particular
- chunks, use PNG_HANDLE_CHUNK_NEVER (or 1) as demonstrated below.
- Here is an example of the usage of png_set_keep_unknown_chunks(),
- where the private "vpAg" chunk will later be processed by a user chunk
- callback function:
- png_byte vpAg[5]={118, 112, 65, 103, (png_byte) '\0'};
- #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
- png_byte unused_chunks[]=
- {
- 104, 73, 83, 84, (png_byte) '\0', /* hIST */
- 105, 84, 88, 116, (png_byte) '\0', /* iTXt */
- 112, 67, 65, 76, (png_byte) '\0', /* pCAL */
- 115, 67, 65, 76, (png_byte) '\0', /* sCAL */
- 115, 80, 76, 84, (png_byte) '\0', /* sPLT */
- 116, 73, 77, 69, (png_byte) '\0', /* tIME */
- };
- #endif
- ...
- #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
- /* ignore all unknown chunks: */
- png_set_keep_unknown_chunks(read_ptr, 1, NULL, 0);
- /* except for vpAg: */
- png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1);
- /* also ignore unused known chunks: */
- png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks,
- (int)sizeof(unused_chunks)/5);
- #endif
- User limits
- The PNG specification allows the width and height of an image to be as
- large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns.
- Since very few applications really need to process such large images,
- we have imposed an arbitrary 1-million limit on rows and columns.
- Larger images will be rejected immediately with a png_error() call. If
- you wish to change this limit, you can use
- png_set_user_limits(png_ptr, width_max, height_max);
- to set your own limits, or use width_max = height_max = 0x7fffffffL
- to allow all valid dimensions (libpng may reject some very large images
- anyway because of potential buffer overflow conditions).
- You should put this statement after you create the PNG structure and
- before calling png_read_info(), png_read_png(), or png_process_data().
- When writing a PNG datastream, put this statement before calling
- png_write_info() or png_write_png().
- If you need to retrieve the limits that are being applied, use
- width_max = png_get_user_width_max(png_ptr);
- height_max = png_get_user_height_max(png_ptr);
- The PNG specification sets no limit on the number of ancillary chunks
- allowed in a PNG datastream. You can impose a limit on the total number
- of sPLT, tEXt, iTXt, zTXt, and unknown chunks that will be stored, with
- png_set_chunk_cache_max(png_ptr, user_chunk_cache_max);
- where 0x7fffffffL means unlimited. You can retrieve this limit with
- chunk_cache_max = png_get_chunk_cache_max(png_ptr);
- This limit also applies to the number of buffers that can be allocated
- by png_decompress_chunk() while decompressing iTXt, zTXt, and iCCP chunks.
- You can also set a limit on the amount of memory that a compressed chunk
- other than IDAT can occupy, with
- png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max);
- and you can retrieve the limit with
- chunk_malloc_max = png_get_chunk_malloc_max(png_ptr);
- Any chunks that would cause either of these limits to be exceeded will
- be ignored.
- Information about your system
- If you intend to display the PNG or to incorporate it in other image data you
- need to tell libpng information about your display or drawing surface so that
- libpng can convert the values in the image to match the display.
- From libpng-1.5.4 this information can be set before reading the PNG file
- header. In earlier versions png_set_gamma() existed but behaved incorrectly if
- called before the PNG file header had been read and png_set_alpha_mode() did not
- exist.
- If you need to support versions prior to libpng-1.5.4 test the version number
- as illustrated below using "PNG_LIBPNG_VER >= 10504" and follow the procedures
- described in the appropriate manual page.
- You give libpng the encoding expected by your system expressed as a 'gamma'
- value. You can also specify a default encoding for the PNG file in
- case the required information is missing from the file. By default libpng
- assumes that the PNG data matches your system, to keep this default call:
- png_set_gamma(png_ptr, screen_gamma, 1/screen_gamma/*file gamma*/);
- or you can use the fixed point equivalent:
- png_set_gamma_fixed(png_ptr, PNG_FP_1*screen_gamma, PNG_FP_1/screen_gamma);
- If you don't know the gamma for your system it is probably 2.2 - a good
- approximation to the IEC standard for display systems (sRGB). If images are
- too contrasty or washed out you got the value wrong - check your system
- documentation!
- Many systems permit the system gamma to be changed via a lookup table in the
- display driver, a few systems, including older Macs, change the response by
- default. As of 1.5.4 three special values are available to handle common
- situations:
- PNG_DEFAULT_sRGB: Indicates that the system conforms to the IEC 61966-2-1
- standard. This matches almost all systems.
- PNG_GAMMA_MAC_18: Indicates that the system is an older (pre Mac OS 10.6)
- Apple Macintosh system with the default settings.
- PNG_GAMMA_LINEAR: Just the fixed point value for 1.0 - indicates that the
- system expects data with no gamma encoding.
- You would use the linear (unencoded) value if you need to process the pixel
- values further because this avoids the need to decode and reencode each
- component value whenever arithmetic is performed. A lot of graphics software
- uses linear values for this reason, often with higher precision component values
- to preserve overall accuracy.
- The second thing you may need to tell libpng about is how your system handles
- alpha channel information. Some, but not all, PNG files contain an alpha
- channel. To display these files correctly you need to compose the data onto a
- suitable background, as described in the PNG specification.
- Libpng only supports composing onto a single color (using png_set_background;
- see below). Otherwise you must do the composition yourself and, in this case,
- you may need to call png_set_alpha_mode:
- #if PNG_LIBPNG_VER >= 10504
- png_set_alpha_mode(png_ptr, mode, screen_gamma);
- #else
- png_set_gamma(png_ptr, screen_gamma, 1.0/screen_gamma);
- #endif
- The screen_gamma value is the same as the argument to png_set_gamma; however,
- how it affects the output depends on the mode. png_set_alpha_mode() sets the
- file gamma default to 1/screen_gamma, so normally you don't need to call
- png_set_gamma. If you need different defaults call png_set_gamma() before
- png_set_alpha_mode() - if you call it after it will override the settings made
- by png_set_alpha_mode().
- The mode is as follows:
- PNG_ALPHA_PNG: The data is encoded according to the PNG specification. Red,
- green and blue, or gray, components are gamma encoded color
- values and are not premultiplied by the alpha value. The
- alpha value is a linear measure of the contribution of the
- pixel to the corresponding final output pixel.
- You should normally use this format if you intend to perform
- color correction on the color values; most, maybe all, color
- correction software has no handling for the alpha channel and,
- anyway, the math to handle pre-multiplied component values is
- unnecessarily complex.
- Before you do any arithmetic on the component values you need
- to remove the gamma encoding and multiply out the alpha
- channel. See the PNG specification for more detail. It is
- important to note that when an image with an alpha channel is
- scaled, linear encoded, pre-multiplied component values must
- be used!
- The remaining modes assume you don't need to do any further color correction or
- that if you do, your color correction software knows all about alpha (it
- probably doesn't!)
- PNG_ALPHA_STANDARD: The data libpng produces
- is encoded in the standard way
- assumed by most correctly written graphics software.
- The gamma encoding will be removed by libpng and the
- linear component values will be pre-multiplied by the
- alpha channel.
- With this format the final image must be re-encoded to
- match the display gamma before the image is displayed.
- If your system doesn't do that, yet still seems to
- perform arithmetic on the pixels without decoding them,
- it is broken - check out the modes below.
- With PNG_ALPHA_STANDARD libpng always produces linear
- component values, whatever screen_gamma you supply. The
- screen_gamma value is, however, used as a default for
- the file gamma if the PNG file has no gamma information.
- If you call png_set_gamma() after png_set_alpha_mode() you
- will override the linear encoding. Instead the
- pre-multiplied pixel values will be gamma encoded but
- the alpha channel will still be linear. This may
- actually match the requirements of some broken software,
- but it is unlikely.
- While linear 8-bit data is often used it has
- insufficient precision for any image with a reasonable
- dynamic range. To avoid problems, and if your software
- supports it, use png_set_expand_16() to force all
- components to 16 bits.
- PNG_ALPHA_OPTIMIZED: This mode is the same
- as PNG_ALPHA_STANDARD except that
- completely opaque pixels are gamma encoded according to
- the screen_gamma value. Pixels with alpha less than 1.0
- will still have linear components.
- Use this format if you have control over your
- compositing software and do don't do other arithmetic
- (such as scaling) on the data you get from libpng. Your
- compositing software can simply copy opaque pixels to
- the output but still has linear values for the
- non-opaque pixels.
- In normal compositing, where the alpha channel encodes
- partial pixel coverage (as opposed to broad area
- translucency), the inaccuracies of the 8-bit
- representation of non-opaque pixels are irrelevant.
- You can also try this format if your software is broken;
- it might look better.
- PNG_ALPHA_BROKEN: This is PNG_ALPHA_STANDARD;
- however, all component values,
- including the alpha channel are gamma encoded. This is
- an appropriate format to try if your software, or more
- likely hardware, is totally broken, i.e., if it performs
- linear arithmetic directly on gamma encoded values.
- In most cases of broken software or hardware the bug in the final display
- manifests as a subtle halo around composited parts of the image. You may not
- even perceive this as a halo; the composited part of the image may simply appear
- separate from the background, as though it had been cut out of paper and pasted
- on afterward.
- If you don't have to deal with bugs in software or hardware, or if you can fix
- them, there are three recommended ways of using png_set_alpha_mode():
- png_set_alpha_mode(png_ptr, PNG_ALPHA_PNG,
- screen_gamma);
- You can do color correction on the result (libpng does not currently
- support color correction internally). When you handle the alpha channel
- you need to undo the gamma encoding and multiply out the alpha.
- png_set_alpha_mode(png_ptr, PNG_ALPHA_STANDARD,
- screen_gamma);
- png_set_expand_16(png_ptr);
- If you are using the high level interface, don't call png_set_expand_16();
- instead pass PNG_TRANSFORM_EXPAND_16 to the interface.
- With this mode you can't do color correction, but you can do arithmetic,
- including composition and scaling, on the data without further processing.
- png_set_alpha_mode(png_ptr, PNG_ALPHA_OPTIMIZED,
- screen_gamma);
- You can avoid the expansion to 16-bit components with this mode, but you
- lose the ability to scale the image or perform other linear arithmetic.
- All you can do is compose the result onto a matching output. Since this
- mode is libpng-specific you also need to write your own composition
- software.
- If you don't need, or can't handle, the alpha channel you can call
- png_set_background() to remove it by compositing against a fixed color. Don't
- call png_set_strip_alpha() to do this - it will leave spurious pixel values in
- transparent parts of this image.
- png_set_background(png_ptr, &background_color,
- PNG_BACKGROUND_GAMMA_SCREEN, 0, 1);
- The background_color is an RGB or grayscale value according to the data format
- libpng will produce for you. Because you don't yet know the format of the PNG
- file, if you call png_set_background at this point you must arrange for the
- format produced by libpng to always have 8-bit or 16-bit components and then
- store the color as an 8-bit or 16-bit color as appropriate. The color contains
- separate gray and RGB component values, so you can let libpng produce gray or
- RGB output according to the input format, but low bit depth grayscale images
- must always be converted to at least 8-bit format. (Even though low bit depth
- grayscale images can't have an alpha channel they can have a transparent
- color!)
- You set the transforms you need later, either as flags to the high level
- interface or libpng API calls for the low level interface. For reference the
- settings and API calls required are:
- 8-bit values:
- PNG_TRANSFORM_SCALE_16 | PNG_EXPAND
- png_set_expand(png_ptr); png_set_scale_16(png_ptr);
- If you must get exactly the same inaccurate results
- produced by default in versions prior to libpng-1.5.4,
- use PNG_TRANSFORM_STRIP_16 and png_set_strip_16(png_ptr)
- instead.
- 16-bit values:
- PNG_TRANSFORM_EXPAND_16
- png_set_expand_16(png_ptr);
- In either case palette image data will be expanded to RGB. If you just want
- color data you can add PNG_TRANSFORM_GRAY_TO_RGB or png_set_gray_to_rgb(png_ptr)
- to the list.
- Calling png_set_background before the PNG file header is read will not work
- prior to libpng-1.5.4. Because the failure may result in unexpected warnings or
- errors it is therefore much safer to call png_set_background after the head has
- been read. Unfortunately this means that prior to libpng-1.5.4 it cannot be
- used with the high level interface.
- The high-level read interface
- At this point there are two ways to proceed; through the high-level
- read interface, or through a sequence of low-level read operations.
- You can use the high-level interface if (a) you are willing to read
- the entire image into memory, and (b) the input transformations
- you want to do are limited to the following set:
- PNG_TRANSFORM_IDENTITY No transformation
- PNG_TRANSFORM_SCALE_16 Strip 16-bit samples to
- 8-bit accurately
- PNG_TRANSFORM_STRIP_16 Chop 16-bit samples to
- 8-bit less accurately
- PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel
- PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit
- samples to bytes
- PNG_TRANSFORM_PACKSWAP Change order of packed
- pixels to LSB first
- PNG_TRANSFORM_EXPAND Perform set_expand()
- PNG_TRANSFORM_INVERT_MONO Invert monochrome images
- PNG_TRANSFORM_SHIFT Normalize pixels to the
- sBIT depth
- PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA
- to BGRA
- PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA
- to AG
- PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity
- to transparency
- PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples
- PNG_TRANSFORM_GRAY_TO_RGB Expand grayscale samples
- to RGB (or GA to RGBA)
- PNG_TRANSFORM_EXPAND_16 Expand samples to 16 bits
- (This excludes setting a background color, doing gamma transformation,
- quantizing, and setting filler.) If this is the case, simply do this:
- png_read_png(png_ptr, info_ptr, png_transforms, NULL)
- where png_transforms is an integer containing the bitwise OR of some
- set of transformation flags. This call is equivalent to png_read_info(),
- followed the set of transformations indicated by the transform mask,
- then png_read_image(), and finally png_read_end().
- (The final parameter of this call is not yet used. Someday it might point
- to transformation parameters required by some future input transform.)
- You must use png_transforms and not call any png_set_transform() functions
- when you use png_read_png().
- After you have called png_read_png(), you can retrieve the image data
- with
- row_pointers = png_get_rows(png_ptr, info_ptr);
- where row_pointers is an array of pointers to the pixel data for each row:
- png_bytep row_pointers[height];
- If you know your image size and pixel size ahead of time, you can allocate
- row_pointers prior to calling png_read_png() with
- if (height > PNG_UINT_32_MAX/png_sizeof(png_byte))
- png_error (png_ptr,
- "Image is too tall to process in memory");
- if (width > PNG_UINT_32_MAX/pixel_size)
- png_error (png_ptr,
- "Image is too wide to process in memory");
- row_pointers = png_malloc(png_ptr,
- height*png_sizeof(png_bytep));
- for (int i=0; i<height, i++)
- row_pointers[i]=NULL; /* security precaution */
- for (int i=0; i<height, i++)
- row_pointers[i]=png_malloc(png_ptr,
- width*pixel_size);
- png_set_rows(png_ptr, info_ptr, &row_pointers);
- Alternatively you could allocate your image in one big block and define
- row_pointers[i] to point into the proper places in your block.
- If you use png_set_rows(), the application is responsible for freeing
- row_pointers (and row_pointers[i], if they were separately allocated).
- If you don't allocate row_pointers ahead of time, png_read_png() will
- do it, and it'll be free'ed by libpng when you call png_destroy_*().
- The low-level read interface
- If you are going the low-level route, you are now ready to read all
- the file information up to the actual image data. You do this with a
- call to png_read_info().
- png_read_info(png_ptr, info_ptr);
- This will process all chunks up to but not including the image data.
- This also copies some of the data from the PNG file into the decode structure
- for use in later transformations. Important information copied in is:
- 1) The PNG file gamma from the gAMA chunk. This overwrites the default value
- provided by an earlier call to png_set_gamma or png_set_alpha_mode.
- 2) Prior to libpng-1.5.4 the background color from a bKGd chunk. This
- damages the information provided by an earlier call to png_set_background
- resulting in unexpected behavior. Libpng-1.5.4 no longer does this.
- 3) The number of significant bits in each component value. Libpng uses this to
- optimize gamma handling by reducing the internal lookup table sizes.
- 4) The transparent color information from a tRNS chunk. This can be modified by
- a later call to png_set_tRNS.
- Querying the info structure
- Functions are used to get the information from the info_ptr once it
- has been read. Note that these fields may not be completely filled
- in until png_read_end() has read the chunk data following the image.
- png_get_IHDR(png_ptr, info_ptr, &width, &height,
- &bit_depth, &color_type, &interlace_type,
- &compression_type, &filter_method);
- width - holds the width of the image
- in pixels (up to 2^31).
- height - holds the height of the image
- in pixels (up to 2^31).
- bit_depth - holds the bit depth of one of the
- image channels. (valid values are
- 1, 2, 4, 8, 16 and depend also on
- the color_type. See also
- significant bits (sBIT) below).
- color_type - describes which color/alpha channels
- are present.
- PNG_COLOR_TYPE_GRAY
- (bit depths 1, 2, 4, 8, 16)
- PNG_COLOR_TYPE_GRAY_ALPHA
- (bit depths 8, 16)
- PNG_COLOR_TYPE_PALETTE
- (bit depths 1, 2, 4, 8)
- PNG_COLOR_TYPE_RGB
- (bit_depths 8, 16)
- PNG_COLOR_TYPE_RGB_ALPHA
- (bit_depths 8, 16)
- PNG_COLOR_MASK_PALETTE
- PNG_COLOR_MASK_COLOR
- PNG_COLOR_MASK_ALPHA
- interlace_type - (PNG_INTERLACE_NONE or
- PNG_INTERLACE_ADAM7)
- compression_type - (must be PNG_COMPRESSION_TYPE_BASE
- for PNG 1.0)
- filter_method - (must be PNG_FILTER_TYPE_BASE
- for PNG 1.0, and can also be
- PNG_INTRAPIXEL_DIFFERENCING if
- the PNG datastream is embedded in
- a MNG-1.0 datastream)
- Any or all of interlace_type, compression_type, or
- filter_method can be NULL if you are
- not interested in their values.
- Note that png_get_IHDR() returns 32-bit data into
- the application's width and height variables.
- This is an unsafe situation if these are 16-bit
- variables. In such situations, the
- png_get_image_width() and png_get_image_height()
- functions described below are safer.
- width = png_get_image_width(png_ptr,
- info_ptr);
- height = png_get_image_height(png_ptr,
- info_ptr);
- bit_depth = png_get_bit_depth(png_ptr,
- info_ptr);
- color_type = png_get_color_type(png_ptr,
- info_ptr);
- interlace_type = png_get_interlace_type(png_ptr,
- info_ptr);
- compression_type = png_get_compression_type(png_ptr,
- info_ptr);
- filter_method = png_get_filter_type(png_ptr,
- info_ptr);
- channels = png_get_channels(png_ptr, info_ptr);
- channels - number of channels of info for the
- color type (valid values are 1 (GRAY,
- PALETTE), 2 (GRAY_ALPHA), 3 (RGB),
- 4 (RGB_ALPHA or RGB + filler byte))
- rowbytes = png_get_rowbytes(png_ptr, info_ptr);
- rowbytes - number of bytes needed to hold a row
- signature = png_get_signature(png_ptr, info_ptr);
- signature - holds the signature read from the
- file (if any). The data is kept in
- the same offset it would be if the
- whole signature were read (i.e. if an
- application had already read in 4
- bytes of signature before starting
- libpng, the remaining 4 bytes would
- be in signature[4] through signature[7]
- (see png_set_sig_bytes())).
- These are also important, but their validity depends on whether the chunk
- has been read. The png_get_valid(png_ptr, info_ptr, PNG_INFO_<chunk>) and
- png_get_<chunk>(png_ptr, info_ptr, ...) functions return non-zero if the
- data has been read, or zero if it is missing. The parameters to the
- png_get_<chunk> are set directly if they are simple data types, or a
- pointer into the info_ptr is returned for any complex types.
- png_get_PLTE(png_ptr, info_ptr, &palette,
- &num_palette);
- palette - the palette for the file
- (array of png_color)
- num_palette - number of entries in the palette
- png_get_gAMA(png_ptr, info_ptr, &file_gamma);
- png_get_gAMA_fixed(png_ptr, info_ptr, &int_file_gamma);
- file_gamma - the gamma at which the file is
- written (PNG_INFO_gAMA)
- int_file_gamma - 100,000 times the gamma at which the
- file is written
- png_get_cHRM(png_ptr, info_ptr, &white_x, &white_y, &red_x, &red_y,
- &green_x, &green_y, &blue_x, &blue_y)
- png_get_cHRM_XYZ(png_ptr, info_ptr, &red_X, &red_Y, &red_Z, &green_X,
- &green_Y, &green_Z, &blue_X, &blue_Y, &blue_Z)
- png_get_cHRM_fixed(png_ptr, info_ptr, &int_white_x, &int_white_y,
- &int_red_x, &int_red_y, &int_green_x, &int_green_y,
- &int_blue_x, &int_blue_y)
- png_get_cHRM_XYZ_fixed(png_ptr, info_ptr, &int_red_X, &int_red_Y,
- &int_red_Z, &int_green_X, &int_green_Y, &int_green_Z,
- &int_blue_X, &int_blue_Y, &int_blue_Z)
- {white,red,green,blue}_{x,y}
- A color space encoding specified using the chromaticities
- of the end points and the white point. (PNG_INFO_cHRM)
- {red,green,blue}_{X,Y,Z}
- A color space encoding specified using the encoding end
- points - the CIE tristimulus specification of the intended
- color of the red, green and blue channels in the PNG RGB
- data. The white point is simply the sum of the three end
- points. (PNG_INFO_cHRM)
- png_get_sRGB(png_ptr, info_ptr, &srgb_intent);
- file_srgb_intent - the rendering intent (PNG_INFO_sRGB)
- The presence of the sRGB chunk
- means that the pixel data is in the
- sRGB color space. This chunk also
- implies specific values of gAMA and
- cHRM.
- png_get_iCCP(png_ptr, info_ptr, &name,
- &compression_type, &profile, &proflen);
- name - The profile name.
- compression_type - The compression type; always
- PNG_COMPRESSION_TYPE_BASE for PNG 1.0.
- You may give NULL to this argument to
- ignore it.
- profile - International Color Consortium color
- profile data. May contain NULs.
- proflen - length of profile data in bytes.
- png_get_sBIT(png_ptr, info_ptr, &sig_bit);
- sig_bit - the number of significant bits for
- (PNG_INFO_sBIT) each of the gray,
- red, green, and blue channels,
- whichever are appropriate for the
- given color type (png_color_16)
- png_get_tRNS(png_ptr, info_ptr, &trans_alpha,
- &num_trans, &trans_color);
- trans_alpha - array of alpha (transparency)
- entries for palette (PNG_INFO_tRNS)
- num_trans - number of transparent entries
- (PNG_INFO_tRNS)
- trans_color - graylevel or color…