Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenexample.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
1.7.6.1
|