example.c
Go to the documentation of this file.
00001 
00002 #if 0 /* in case someone actually tries to compile this */
00003 
00004 /* example.c - an example of using libpng
00005  * Last changed in libpng 1.2.32 [September 18, 2008]
00006  * This file has been placed in the public domain by the authors.
00007  * Maintained 1998-2008 Glenn Randers-Pehrson
00008  * Maintained 1996, 1997 Andreas Dilger)
00009  * Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
00010  */
00011 
00012 /* This is an example of how to use libpng to read and write PNG files.
00013  * The file libpng.txt is much more verbose then this.  If you have not
00014  * read it, do so first.  This was designed to be a starting point of an
00015  * implementation.  This is not officially part of libpng, is hereby placed
00016  * in the public domain, and therefore does not require a copyright notice.
00017  *
00018  * This file does not currently compile, because it is missing certain
00019  * parts, like allocating memory to hold an image.  You will have to
00020  * supply these parts to get it to compile.  For an example of a minimal
00021  * working PNG reader/writer, see pngtest.c, included in this distribution;
00022  * see also the programs in the contrib directory.
00023  */
00024 
00025 #include "png.h"
00026 
00027  /* The png_jmpbuf() macro, used in error handling, became available in
00028   * libpng version 1.0.6.  If you want to be able to run your code with older
00029   * versions of libpng, you must define the macro yourself (but only if it
00030   * is not already defined by libpng!).
00031   */
00032 
00033 #ifndef png_jmpbuf
00034 #  define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
00035 #endif
00036 
00037 /* Check to see if a file is a PNG file using png_sig_cmp().  png_sig_cmp()
00038  * returns zero if the image is a PNG and nonzero if it isn't a PNG.
00039  *
00040  * The function check_if_png() shown here, but not used, returns nonzero (true)
00041  * if the file can be opened and is a PNG, 0 (false) otherwise.
00042  *
00043  * If this call is successful, and you are going to keep the file open,
00044  * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once
00045  * you have created the png_ptr, so that libpng knows your application
00046  * has read that many bytes from the start of the file.  Make sure you
00047  * don't call png_set_sig_bytes() with more than 8 bytes read or give it
00048  * an incorrect number of bytes read, or you will either have read too
00049  * many bytes (your fault), or you are telling libpng to read the wrong
00050  * number of magic bytes (also your fault).
00051  *
00052  * Many applications already read the first 2 or 4 bytes from the start
00053  * of the image to determine the file type, so it would be easiest just
00054  * to pass the bytes to png_sig_cmp() or even skip that if you know
00055  * you have a PNG file, and call png_set_sig_bytes().
00056  */
00057 #define PNG_BYTES_TO_CHECK 4
00058 int check_if_png(char *file_name, FILE **fp)
00059 {
00060    char buf[PNG_BYTES_TO_CHECK];
00061 
00062    /* Open the prospective PNG file. */
00063    if ((*fp = fopen(file_name, "rb")) == NULL)
00064       return 0;
00065 
00066    /* Read in some of the signature bytes */
00067    if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK)
00068       return 0;
00069 
00070    /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
00071       Return nonzero (true) if they match */
00072 
00073    return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
00074 }
00075 
00076 /* Read a PNG file.  You may want to return an error code if the read
00077  * fails (depending upon the failure).  There are two "prototypes" given
00078  * here - one where we are given the filename, and we need to open the
00079  * file, and the other where we are given an open file (possibly with
00080  * some or all of the magic bytes read - see comments above).
00081  */
00082 #ifdef open_file /* prototype 1 */
00083 void read_png(char *file_name)  /* We need to open the file */
00084 {
00085    png_structp png_ptr;
00086    png_infop info_ptr;
00087    unsigned int sig_read = 0;
00088    png_uint_32 width, height;
00089    int bit_depth, color_type, interlace_type;
00090    FILE *fp;
00091 
00092    if ((fp = fopen(file_name, "rb")) == NULL)
00093       return (ERROR);
00094 #else no_open_file /* prototype 2 */
00095 void read_png(FILE *fp, unsigned int sig_read)  /* file is already open */
00096 {
00097    png_structp png_ptr;
00098    png_infop info_ptr;
00099    png_uint_32 width, height;
00100    int bit_depth, color_type, interlace_type;
00101 #endif no_open_file /* only use one prototype! */
00102 
00103    /* Create and initialize the png_struct with the desired error handler
00104     * functions.  If you want to use the default stderr and longjump method,
00105     * you can supply NULL for the last three parameters.  We also supply the
00106     * the compiler header file version, so that we know if the application
00107     * was compiled with a compatible version of the library.  REQUIRED
00108     */
00109    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
00110       png_voidp user_error_ptr, user_error_fn, user_warning_fn);
00111 
00112    if (png_ptr == NULL)
00113    {
00114       fclose(fp);
00115       return (ERROR);
00116    }
00117 
00118    /* Allocate/initialize the memory for image information.  REQUIRED. */
00119    info_ptr = png_create_info_struct(png_ptr);
00120    if (info_ptr == NULL)
00121    {
00122       fclose(fp);
00123       png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
00124       return (ERROR);
00125    }
00126 
00127    /* Set error handling if you are using the setjmp/longjmp method (this is
00128     * the normal method of doing things with libpng).  REQUIRED unless you
00129     * set up your own error handlers in the png_create_read_struct() earlier.
00130     */
00131 
00132    if (setjmp(png_jmpbuf(png_ptr)))
00133    {
00134       /* Free all of the memory associated with the png_ptr and info_ptr */
00135       png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
00136       fclose(fp);
00137       /* If we get here, we had a problem reading the file */
00138       return (ERROR);
00139    }
00140 
00141    /* One of the following I/O initialization methods is REQUIRED */
00142 #ifdef streams /* PNG file I/O method 1 */
00143    /* Set up the input control if you are using standard C streams */
00144    png_init_io(png_ptr, fp);
00145 
00146 #else no_streams /* PNG file I/O method 2 */
00147    /* If you are using replacement read functions, instead of calling
00148     * png_init_io() here you would call:
00149     */
00150    png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn);
00151    /* where user_io_ptr is a structure you want available to the callbacks */
00152 #endif no_streams /* Use only one I/O method! */
00153 
00154    /* If we have already read some of the signature */
00155    png_set_sig_bytes(png_ptr, sig_read);
00156 
00157 #ifdef hilevel
00158    /*
00159     * If you have enough memory to read in the entire image at once,
00160     * and you need to specify only transforms that can be controlled
00161     * with one of the PNG_TRANSFORM_* bits (this presently excludes
00162     * dithering, filling, setting background, and doing gamma
00163     * adjustment), then you can read the entire image (including
00164     * pixels) into the info structure with this call:
00165     */
00166    png_read_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL);
00167 #else
00168    /* OK, you're doing it the hard way, with the lower-level functions */
00169 
00170    /* The call to png_read_info() gives us all of the information from the
00171     * PNG file before the first IDAT (image data chunk).  REQUIRED
00172     */
00173    png_read_info(png_ptr, info_ptr);
00174 
00175    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
00176        &interlace_type, int_p_NULL, int_p_NULL);
00177 
00178 /* Set up the data transformations you want.  Note that these are all
00179  * optional.  Only call them if you want/need them.  Many of the
00180  * transformations only work on specific types of images, and many
00181  * are mutually exclusive.
00182  */
00183 
00184    /* tell libpng to strip 16 bit/color files down to 8 bits/color */
00185    png_set_strip_16(png_ptr);
00186 
00187    /* Strip alpha bytes from the input data without combining with the
00188     * background (not recommended).
00189     */
00190    png_set_strip_alpha(png_ptr);
00191 
00192    /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
00193     * byte into separate bytes (useful for paletted and grayscale images).
00194     */
00195    png_set_packing(png_ptr);
00196 
00197    /* Change the order of packed pixels to least significant bit first
00198     * (not useful if you are using png_set_packing). */
00199    png_set_packswap(png_ptr);
00200 
00201    /* Expand paletted colors into true RGB triplets */
00202    if (color_type == PNG_COLOR_TYPE_PALETTE)
00203       png_set_palette_to_rgb(png_ptr);
00204 
00205    /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
00206    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
00207       png_set_gray_1_2_4_to_8(png_ptr);
00208 
00209    /* Expand paletted or RGB images with transparency to full alpha channels
00210     * so the data will be available as RGBA quartets.
00211     */
00212    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
00213       png_set_tRNS_to_alpha(png_ptr);
00214 
00215    /* Set the background color to draw transparent and alpha images over.
00216     * It is possible to set the red, green, and blue components directly
00217     * for paletted images instead of supplying a palette index.  Note that
00218     * even if the PNG file supplies a background, you are not required to
00219     * use it - you should use the (solid) application background if it has one.
00220     */
00221 
00222    png_color_16 my_background, *image_background;
00223 
00224    if (png_get_bKGD(png_ptr, info_ptr, &image_background))
00225       png_set_background(png_ptr, image_background,
00226                          PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
00227    else
00228       png_set_background(png_ptr, &my_background,
00229                          PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
00230 
00231    /* Some suggestions as to how to get a screen gamma value */
00232 
00233    /* Note that screen gamma is the display_exponent, which includes
00234     * the CRT_exponent and any correction for viewing conditions */
00235    if (/* We have a user-defined screen gamma value */)
00236    {
00237       screen_gamma = user-defined screen_gamma;
00238    }
00239    /* This is one way that applications share the same screen gamma value */
00240    else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
00241    {
00242       screen_gamma = atof(gamma_str);
00243    }
00244    /* If we don't have another value */
00245    else
00246    {
00247       screen_gamma = 2.2;  /* A good guess for a PC monitors in a dimly
00248                               lit room */
00249       screen_gamma = 1.7 or 1.0;  /* A good guess for Mac systems */
00250    }
00251 
00252    /* Tell libpng to handle the gamma conversion for you.  The final call
00253     * is a good guess for PC generated images, but it should be configurable
00254     * by the user at run time by the user.  It is strongly suggested that
00255     * your application support gamma correction.
00256     */
00257 
00258    int intent;
00259 
00260    if (png_get_sRGB(png_ptr, info_ptr, &intent))
00261       png_set_gamma(png_ptr, screen_gamma, 0.45455);
00262    else
00263    {
00264       double image_gamma;
00265       if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
00266          png_set_gamma(png_ptr, screen_gamma, image_gamma);
00267       else
00268          png_set_gamma(png_ptr, screen_gamma, 0.45455);
00269    }
00270 
00271    /* Dither RGB files down to 8 bit palette or reduce palettes
00272     * to the number of colors available on your screen.
00273     */
00274    if (color_type & PNG_COLOR_MASK_COLOR)
00275    {
00276       int num_palette;
00277       png_colorp palette;
00278 
00279       /* This reduces the image to the application supplied palette */
00280       if (/* we have our own palette */)
00281       {
00282          /* An array of colors to which the image should be dithered */
00283          png_color std_color_cube[MAX_SCREEN_COLORS];
00284 
00285          png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS,
00286             MAX_SCREEN_COLORS, png_uint_16p_NULL, 0);
00287       }
00288       /* This reduces the image to the palette supplied in the file */
00289       else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette))
00290       {
00291          png_uint_16p histogram = NULL;
00292 
00293          png_get_hIST(png_ptr, info_ptr, &histogram);
00294 
00295          png_set_dither(png_ptr, palette, num_palette,
00296                         max_screen_colors, histogram, 0);
00297       }
00298    }
00299 
00300    /* invert monochrome files to have 0 as white and 1 as black */
00301    png_set_invert_mono(png_ptr);
00302 
00303    /* If you want to shift the pixel values from the range [0,255] or
00304     * [0,65535] to the original [0,7] or [0,31], or whatever range the
00305     * colors were originally in:
00306     */
00307    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
00308    {
00309       png_color_8p sig_bit;
00310 
00311       png_get_sBIT(png_ptr, info_ptr, &sig_bit);
00312       png_set_shift(png_ptr, sig_bit);
00313    }
00314 
00315    /* flip the RGB pixels to BGR (or RGBA to BGRA) */
00316    if (color_type & PNG_COLOR_MASK_COLOR)
00317       png_set_bgr(png_ptr);
00318 
00319    /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
00320    png_set_swap_alpha(png_ptr);
00321 
00322    /* swap bytes of 16 bit files to least significant byte first */
00323    png_set_swap(png_ptr);
00324 
00325    /* Add filler (or alpha) byte (before/after each RGB triplet) */
00326    png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
00327 
00328    /* Turn on interlace handling.  REQUIRED if you are not using
00329     * png_read_image().  To see how to handle interlacing passes,
00330     * see the png_read_row() method below:
00331     */
00332    number_passes = png_set_interlace_handling(png_ptr);
00333 
00334    /* Optional call to gamma correct and add the background to the palette
00335     * and update info structure.  REQUIRED if you are expecting libpng to
00336     * update the palette for you (ie you selected such a transform above).
00337     */
00338    png_read_update_info(png_ptr, info_ptr);
00339 
00340    /* Allocate the memory to hold the image using the fields of info_ptr. */
00341 
00342    /* The easiest way to read the image: */
00343    png_bytep row_pointers[height];
00344 
00345    for (row = 0; row < height; row++)
00346    {
00347       row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr,
00348          info_ptr));
00349    }
00350 
00351    /* Now it's time to read the image.  One of these methods is REQUIRED */
00352 #ifdef entire /* Read the entire image in one go */
00353    png_read_image(png_ptr, row_pointers);
00354 
00355 #else no_entire /* Read the image one or more scanlines at a time */
00356    /* The other way to read images - deal with interlacing: */
00357 
00358    for (pass = 0; pass < number_passes; pass++)
00359    {
00360 #ifdef single /* Read the image a single row at a time */
00361       for (y = 0; y < height; y++)
00362       {
00363          png_read_rows(png_ptr, &row_pointers[y], png_bytepp_NULL, 1);
00364       }
00365 
00366 #else no_single /* Read the image several rows at a time */
00367       for (y = 0; y < height; y += number_of_rows)
00368       {
00369 #ifdef sparkle /* Read the image using the "sparkle" effect. */
00370          png_read_rows(png_ptr, &row_pointers[y], png_bytepp_NULL,
00371             number_of_rows);
00372 #else no_sparkle /* Read the image using the "rectangle" effect */
00373          png_read_rows(png_ptr, png_bytepp_NULL, &row_pointers[y],
00374             number_of_rows);
00375 #endif no_sparkle /* use only one of these two methods */
00376       }
00377 
00378       /* if you want to display the image after every pass, do
00379          so here */
00380 #endif no_single /* use only one of these two methods */
00381    }
00382 #endif no_entire /* use only one of these two methods */
00383 
00384    /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
00385    png_read_end(png_ptr, info_ptr);
00386 #endif hilevel
00387 
00388    /* At this point you have read the entire image */
00389 
00390    /* clean up after the read, and free any memory allocated - REQUIRED */
00391    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
00392 
00393    /* close the file */
00394    fclose(fp);
00395 
00396    /* that's it */
00397    return (OK);
00398 }
00399 
00400 /* progressively read a file */
00401 
00402 int
00403 initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr)
00404 {
00405    /* Create and initialize the png_struct with the desired error handler
00406     * functions.  If you want to use the default stderr and longjump method,
00407     * you can supply NULL for the last three parameters.  We also check that
00408     * the library version is compatible in case we are using dynamically
00409     * linked libraries.
00410     */
00411    *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
00412        png_voidp user_error_ptr, user_error_fn, user_warning_fn);
00413 
00414    if (*png_ptr == NULL)
00415    {
00416       *info_ptr = NULL;
00417       return (ERROR);
00418    }
00419 
00420    *info_ptr = png_create_info_struct(png_ptr);
00421 
00422    if (*info_ptr == NULL)
00423    {
00424       png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL);
00425       return (ERROR);
00426    }
00427 
00428    if (setjmp(png_jmpbuf((*png_ptr))))
00429    {
00430       png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL);
00431       return (ERROR);
00432    }
00433 
00434    /* This one's new.  You will need to provide all three
00435     * function callbacks, even if you aren't using them all.
00436     * If you aren't using all functions, you can specify NULL
00437     * parameters.  Even when all three functions are NULL,
00438     * you need to call png_set_progressive_read_fn().
00439     * These functions shouldn't be dependent on global or
00440     * static variables if you are decoding several images
00441     * simultaneously.  You should store stream specific data
00442     * in a separate struct, given as the second parameter,
00443     * and retrieve the pointer from inside the callbacks using
00444     * the function png_get_progressive_ptr(png_ptr).
00445     */
00446    png_set_progressive_read_fn(*png_ptr, (void *)stream_data,
00447       info_callback, row_callback, end_callback);
00448 
00449    return (OK);
00450 }
00451 
00452 int
00453 process_data(png_structp *png_ptr, png_infop *info_ptr,
00454    png_bytep buffer, png_uint_32 length)
00455 {
00456    if (setjmp(png_jmpbuf((*png_ptr))))
00457    {
00458       /* Free the png_ptr and info_ptr memory on error */
00459       png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL);
00460       return (ERROR);
00461    }
00462 
00463    /* This one's new also.  Simply give it chunks of data as
00464     * they arrive from the data stream (in order, of course).
00465     * On Segmented machines, don't give it any more than 64K.
00466     * The library seems to run fine with sizes of 4K, although
00467     * you can give it much less if necessary (I assume you can
00468     * give it chunks of 1 byte, but I haven't tried with less
00469     * than 256 bytes yet).  When this function returns, you may
00470     * want to display any rows that were generated in the row
00471     * callback, if you aren't already displaying them there.
00472     */
00473    png_process_data(*png_ptr, *info_ptr, buffer, length);
00474    return (OK);
00475 }
00476 
00477 info_callback(png_structp png_ptr, png_infop info)
00478 {
00479 /* do any setup here, including setting any of the transformations
00480  * mentioned in the Reading PNG files section.  For now, you _must_
00481  * call either png_start_read_image() or png_read_update_info()
00482  * after all the transformations are set (even if you don't set
00483  * any).  You may start getting rows before png_process_data()
00484  * returns, so this is your last chance to prepare for that.
00485  */
00486 }
00487 
00488 row_callback(png_structp png_ptr, png_bytep new_row,
00489    png_uint_32 row_num, int pass)
00490 {
00491 /*
00492  * This function is called for every row in the image.  If the
00493  * image is interlaced, and you turned on the interlace handler,
00494  * this function will be called for every row in every pass.
00495  *
00496  * In this function you will receive a pointer to new row data from
00497  * libpng called new_row that is to replace a corresponding row (of
00498  * the same data format) in a buffer allocated by your application.
00499  *
00500  * The new row data pointer new_row may be NULL, indicating there is
00501  * no new data to be replaced (in cases of interlace loading).
00502  *
00503  * If new_row is not NULL then you need to call
00504  * png_progressive_combine_row() to replace the corresponding row as
00505  * shown below:
00506  */
00507    /* Check if row_num is in bounds. */
00508    if ((row_num >= 0) && (row_num < height))
00509    {
00510      /* Get pointer to corresponding row in our
00511       * PNG read buffer.
00512       */
00513      png_bytep old_row = ((png_bytep *)our_data)[row_num];
00514 
00515      /* If both rows are allocated then copy the new row
00516       * data to the corresponding row data.
00517       */
00518      if ((old_row != NULL) && (new_row != NULL))
00519      png_progressive_combine_row(png_ptr, old_row, new_row);
00520    }
00521 /*
00522  * The rows and passes are called in order, so you don't really
00523  * need the row_num and pass, but I'm supplying them because it
00524  * may make your life easier.
00525  *
00526  * For the non-NULL rows of interlaced images, you must call
00527  * png_progressive_combine_row() passing in the new row and the
00528  * old row, as demonstrated above.  You can call this function for
00529  * NULL rows (it will just return) and for non-interlaced images
00530  * (it just does the png_memcpy for you) if it will make the code
00531  * easier.  Thus, you can just do this for all cases:
00532  */
00533 
00534    png_progressive_combine_row(png_ptr, old_row, new_row);
00535 
00536 /* where old_row is what was displayed for previous rows.  Note
00537  * that the first pass (pass == 0 really) will completely cover
00538  * the old row, so the rows do not have to be initialized.  After
00539  * the first pass (and only for interlaced images), you will have
00540  * to pass the current row as new_row, and the function will combine
00541  * the old row and the new row.
00542  */
00543 }
00544 
00545 end_callback(png_structp png_ptr, png_infop info)
00546 {
00547 /* this function is called when the whole image has been read,
00548  * including any chunks after the image (up to and including
00549  * the IEND).  You will usually have the same info chunk as you
00550  * had in the header, although some data may have been added
00551  * to the comments and time fields.
00552  *
00553  * Most people won't do much here, perhaps setting a flag that
00554  * marks the image as finished.
00555  */
00556 }
00557 
00558 /* write a png file */
00559 void write_png(char *file_name /* , ... other image information ... */)
00560 {
00561    FILE *fp;
00562    png_structp png_ptr;
00563    png_infop info_ptr;
00564    png_colorp palette;
00565 
00566    /* open the file */
00567    fp = fopen(file_name, "wb");
00568    if (fp == NULL)
00569       return (ERROR);
00570 
00571    /* Create and initialize the png_struct with the desired error handler
00572     * functions.  If you want to use the default stderr and longjump method,
00573     * you can supply NULL for the last three parameters.  We also check that
00574     * the library version is compatible with the one used at compile time,
00575     * in case we are using dynamically linked libraries.  REQUIRED.
00576     */
00577    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
00578       png_voidp user_error_ptr, user_error_fn, user_warning_fn);
00579 
00580    if (png_ptr == NULL)
00581    {
00582       fclose(fp);
00583       return (ERROR);
00584    }
00585 
00586    /* Allocate/initialize the image information data.  REQUIRED */
00587    info_ptr = png_create_info_struct(png_ptr);
00588    if (info_ptr == NULL)
00589    {
00590       fclose(fp);
00591       png_destroy_write_struct(&png_ptr,  png_infopp_NULL);
00592       return (ERROR);
00593    }
00594 
00595    /* Set error handling.  REQUIRED if you aren't supplying your own
00596     * error handling functions in the png_create_write_struct() call.
00597     */
00598    if (setjmp(png_jmpbuf(png_ptr)))
00599    {
00600       /* If we get here, we had a problem reading the file */
00601       fclose(fp);
00602       png_destroy_write_struct(&png_ptr, &info_ptr);
00603       return (ERROR);
00604    }
00605 
00606    /* One of the following I/O initialization functions is REQUIRED */
00607 #ifdef streams /* I/O initialization method 1 */
00608    /* set up the output control if you are using standard C streams */
00609    png_init_io(png_ptr, fp);
00610 #else no_streams /* I/O initialization method 2 */
00611    /* If you are using replacement write functions, instead of calling
00612     * png_init_io() here you would call */
00613    png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn,
00614       user_IO_flush_function);
00615    /* where user_io_ptr is a structure you want available to the callbacks */
00616 #endif no_streams /* only use one initialization method */
00617 
00618 #ifdef hilevel
00619    /* This is the easy way.  Use it if you already have all the
00620     * image info living info in the structure.  You could "|" many
00621     * PNG_TRANSFORM flags into the png_transforms integer here.
00622     */
00623    png_write_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL);
00624 #else
00625    /* This is the hard way */
00626 
00627    /* Set the image information here.  Width and height are up to 2^31,
00628     * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
00629     * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
00630     * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
00631     * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
00632     * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
00633     * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
00634     */
00635    png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_???,
00636       PNG_INTERLACE_????, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
00637 
00638    /* set the palette if there is one.  REQUIRED for indexed-color images */
00639    palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH
00640              * png_sizeof(png_color));
00641    /* ... set palette colors ... */
00642    png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);
00643    /* You must not free palette here, because png_set_PLTE only makes a link to
00644       the palette that you malloced.  Wait until you are about to destroy
00645       the png structure. */
00646 
00647    /* optional significant bit chunk */
00648    /* if we are dealing with a grayscale image then */
00649    sig_bit.gray = true_bit_depth;
00650    /* otherwise, if we are dealing with a color image then */
00651    sig_bit.red = true_red_bit_depth;
00652    sig_bit.green = true_green_bit_depth;
00653    sig_bit.blue = true_blue_bit_depth;
00654    /* if the image has an alpha channel then */
00655    sig_bit.alpha = true_alpha_bit_depth;
00656    png_set_sBIT(png_ptr, info_ptr, sig_bit);
00657 
00658 
00659    /* Optional gamma chunk is strongly suggested if you have any guess
00660     * as to the correct gamma of the image.
00661     */
00662    png_set_gAMA(png_ptr, info_ptr, gamma);
00663 
00664    /* Optionally write comments into the image */
00665    text_ptr[0].key = "Title";
00666    text_ptr[0].text = "Mona Lisa";
00667    text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
00668    text_ptr[1].key = "Author";
00669    text_ptr[1].text = "Leonardo DaVinci";
00670    text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
00671    text_ptr[2].key = "Description";
00672    text_ptr[2].text = "<long text>";
00673    text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
00674 #ifdef PNG_iTXt_SUPPORTED
00675    text_ptr[0].lang = NULL;
00676    text_ptr[1].lang = NULL;
00677    text_ptr[2].lang = NULL;
00678 #endif
00679    png_set_text(png_ptr, info_ptr, text_ptr, 3);
00680 
00681    /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
00682    /* note that if sRGB is present the gAMA and cHRM chunks must be ignored
00683     * on read and must be written in accordance with the sRGB profile */
00684 
00685    /* Write the file header information.  REQUIRED */
00686    png_write_info(png_ptr, info_ptr);
00687 
00688    /* If you want, you can write the info in two steps, in case you need to
00689     * write your private chunk ahead of PLTE:
00690     *
00691     *   png_write_info_before_PLTE(write_ptr, write_info_ptr);
00692     *   write_my_chunk();
00693     *   png_write_info(png_ptr, info_ptr);
00694     *
00695     * However, given the level of known- and unknown-chunk support in 1.1.0
00696     * and up, this should no longer be necessary.
00697     */
00698 
00699    /* Once we write out the header, the compression type on the text
00700     * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
00701     * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
00702     * at the end.
00703     */
00704 
00705    /* set up the transformations you want.  Note that these are
00706     * all optional.  Only call them if you want them.
00707     */
00708 
00709    /* invert monochrome pixels */
00710    png_set_invert_mono(png_ptr);
00711 
00712    /* Shift the pixels up to a legal bit depth and fill in
00713     * as appropriate to correctly scale the image.
00714     */
00715    png_set_shift(png_ptr, &sig_bit);
00716 
00717    /* pack pixels into bytes */
00718    png_set_packing(png_ptr);
00719 
00720    /* swap location of alpha bytes from ARGB to RGBA */
00721    png_set_swap_alpha(png_ptr);
00722 
00723    /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
00724     * RGB (4 channels -> 3 channels). The second parameter is not used.
00725     */
00726    png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
00727 
00728    /* flip BGR pixels to RGB */
00729    png_set_bgr(png_ptr);
00730 
00731    /* swap bytes of 16-bit files to most significant byte first */
00732    png_set_swap(png_ptr);
00733 
00734    /* swap bits of 1, 2, 4 bit packed pixel formats */
00735    png_set_packswap(png_ptr);
00736 
00737    /* turn on interlace handling if you are not using png_write_image() */
00738    if (interlacing)
00739       number_passes = png_set_interlace_handling(png_ptr);
00740    else
00741       number_passes = 1;
00742 
00743    /* The easiest way to write the image (you may have a different memory
00744     * layout, however, so choose what fits your needs best).  You need to
00745     * use the first method if you aren't handling interlacing yourself.
00746     */
00747    png_uint_32 k, height, width;
00748    png_byte image[height][width*bytes_per_pixel];
00749    png_bytep row_pointers[height];
00750 
00751    if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
00752      png_error (png_ptr, "Image is too tall to process in memory");
00753 
00754    for (k = 0; k < height; k++)
00755      row_pointers[k] = image + k*width*bytes_per_pixel;
00756 
00757    /* One of the following output methods is REQUIRED */
00758 #ifdef entire /* write out the entire image data in one call */
00759    png_write_image(png_ptr, row_pointers);
00760 
00761    /* the other way to write the image - deal with interlacing */
00762 
00763 #else no_entire /* write out the image data by one or more scanlines */
00764    /* The number of passes is either 1 for non-interlaced images,
00765     * or 7 for interlaced images.
00766     */
00767    for (pass = 0; pass < number_passes; pass++)
00768    {
00769       /* Write a few rows at a time. */
00770       png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows);
00771 
00772       /* If you are only writing one row at a time, this works */
00773       for (y = 0; y < height; y++)
00774       {
00775          png_write_rows(png_ptr, &row_pointers[y], 1);
00776       }
00777    }
00778 #endif no_entire /* use only one output method */
00779 
00780    /* You can write optional chunks like tEXt, zTXt, and tIME at the end
00781     * as well.  Shouldn't be necessary in 1.1.0 and up as all the public
00782     * chunks are supported and you can use png_set_unknown_chunks() to
00783     * register unknown chunks into the info structure to be written out.
00784     */
00785 
00786    /* It is REQUIRED to call this to finish writing the rest of the file */
00787    png_write_end(png_ptr, info_ptr);
00788 #endif hilevel
00789 
00790    /* If you png_malloced a palette, free it here (don't free info_ptr->palette,
00791       as recommended in versions 1.0.5m and earlier of this example; if
00792       libpng mallocs info_ptr->palette, libpng will free it).  If you
00793       allocated it with malloc() instead of png_malloc(), use free() instead
00794       of png_free(). */
00795    png_free(png_ptr, palette);
00796    palette = NULL;
00797 
00798    /* Similarly, if you png_malloced any data that you passed in with
00799       png_set_something(), such as a hist or trans array, free it here,
00800       when you can be sure that libpng is through with it. */
00801    png_free(png_ptr, trans);
00802    trans = NULL;
00803 
00804    /* clean up after the write, and free any memory allocated */
00805    png_destroy_write_struct(&png_ptr, &info_ptr);
00806 
00807    /* close the file */
00808    fclose(fp);
00809 
00810    /* that's it */
00811    return (OK);
00812 }
00813 
00814 #endif /* if 0 */


openhrp3
Author(s): AIST, General Robotix Inc., Nakamura Lab of Dept. of Mechano Informatics at University of Tokyo
autogenerated on Thu Apr 11 2019 03:30:16