ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

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

Generated on Thu May 24 2012 04:19:31 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.