pngwrite.c

Go to the documentation of this file.
00001 
00002 /* pngwrite.c - general routines to write a PNG file
00003  *
00004  * Last changed in libpng 1.2.15 January 5, 2007
00005  * For conditions of distribution and use, see copyright notice in png.h
00006  * Copyright (c) 1998-2007 Glenn Randers-Pehrson
00007  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
00008  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
00009  */
00010 
00011 /* get internal access to png.h */
00012 #define PNG_INTERNAL
00013 #include "png.h"
00014 #ifdef PNG_WRITE_SUPPORTED
00015 
00016 /* Writes all the PNG information.  This is the suggested way to use the
00017  * library.  If you have a new chunk to add, make a function to write it,
00018  * and put it in the correct location here.  If you want the chunk written
00019  * after the image data, put it in png_write_end().  I strongly encourage
00020  * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
00021  * the chunk, as that will keep the code from breaking if you want to just
00022  * write a plain PNG file.  If you have long comments, I suggest writing
00023  * them in png_write_end(), and compressing them.
00024  */
00025 void PNGAPI
00026 png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
00027 {
00028    png_debug(1, "in png_write_info_before_PLTE\n");
00029    if (png_ptr == NULL || info_ptr == NULL)
00030       return;
00031    if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
00032    {
00033    png_write_sig(png_ptr); /* write PNG signature */
00034 #if defined(PNG_MNG_FEATURES_SUPPORTED)
00035    if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted))
00036    {
00037       png_warning(png_ptr,"MNG features are not allowed in a PNG datastream");
00038       png_ptr->mng_features_permitted=0;
00039    }
00040 #endif
00041    /* write IHDR information. */
00042    png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
00043       info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
00044       info_ptr->filter_type,
00045 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
00046       info_ptr->interlace_type);
00047 #else
00048       0);
00049 #endif
00050    /* the rest of these check to see if the valid field has the appropriate
00051       flag set, and if it does, writes the chunk. */
00052 #if defined(PNG_WRITE_gAMA_SUPPORTED)
00053    if (info_ptr->valid & PNG_INFO_gAMA)
00054    {
00055 #  ifdef PNG_FLOATING_POINT_SUPPORTED
00056       png_write_gAMA(png_ptr, info_ptr->gamma);
00057 #else
00058 #ifdef PNG_FIXED_POINT_SUPPORTED
00059       png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma);
00060 #  endif
00061 #endif
00062    }
00063 #endif
00064 #if defined(PNG_WRITE_sRGB_SUPPORTED)
00065    if (info_ptr->valid & PNG_INFO_sRGB)
00066       png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
00067 #endif
00068 #if defined(PNG_WRITE_iCCP_SUPPORTED)
00069    if (info_ptr->valid & PNG_INFO_iCCP)
00070       png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
00071                      info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
00072 #endif
00073 #if defined(PNG_WRITE_sBIT_SUPPORTED)
00074    if (info_ptr->valid & PNG_INFO_sBIT)
00075       png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
00076 #endif
00077 #if defined(PNG_WRITE_cHRM_SUPPORTED)
00078    if (info_ptr->valid & PNG_INFO_cHRM)
00079    {
00080 #ifdef PNG_FLOATING_POINT_SUPPORTED
00081       png_write_cHRM(png_ptr,
00082          info_ptr->x_white, info_ptr->y_white,
00083          info_ptr->x_red, info_ptr->y_red,
00084          info_ptr->x_green, info_ptr->y_green,
00085          info_ptr->x_blue, info_ptr->y_blue);
00086 #else
00087 #  ifdef PNG_FIXED_POINT_SUPPORTED
00088       png_write_cHRM_fixed(png_ptr,
00089          info_ptr->int_x_white, info_ptr->int_y_white,
00090          info_ptr->int_x_red, info_ptr->int_y_red,
00091          info_ptr->int_x_green, info_ptr->int_y_green,
00092          info_ptr->int_x_blue, info_ptr->int_y_blue);
00093 #  endif
00094 #endif
00095    }
00096 #endif
00097 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
00098    if (info_ptr->unknown_chunks_num)
00099    {
00100        png_unknown_chunk *up;
00101 
00102        png_debug(5, "writing extra chunks\n");
00103 
00104        for (up = info_ptr->unknown_chunks;
00105             up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
00106             up++)
00107        {
00108          int keep=png_handle_as_unknown(png_ptr, up->name);
00109          if (keep != PNG_HANDLE_CHUNK_NEVER &&
00110             up->location && !(up->location & PNG_HAVE_PLTE) &&
00111             !(up->location & PNG_HAVE_IDAT) &&
00112             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
00113             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
00114          {
00115             png_write_chunk(png_ptr, up->name, up->data, up->size);
00116          }
00117        }
00118    }
00119 #endif
00120       png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
00121    }
00122 }
00123 
00124 void PNGAPI
00125 png_write_info(png_structp png_ptr, png_infop info_ptr)
00126 {
00127 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
00128    int i;
00129 #endif
00130 
00131    png_debug(1, "in png_write_info\n");
00132 
00133    if (png_ptr == NULL || info_ptr == NULL)
00134       return;
00135 
00136    png_write_info_before_PLTE(png_ptr, info_ptr);
00137 
00138    if (info_ptr->valid & PNG_INFO_PLTE)
00139       png_write_PLTE(png_ptr, info_ptr->palette,
00140          (png_uint_32)info_ptr->num_palette);
00141    else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
00142       png_error(png_ptr, "Valid palette required for paletted images");
00143 
00144 #if defined(PNG_WRITE_tRNS_SUPPORTED)
00145    if (info_ptr->valid & PNG_INFO_tRNS)
00146       {
00147 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
00148          /* invert the alpha channel (in tRNS) */
00149          if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
00150             info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
00151          {
00152             int j;
00153             for (j=0; j<(int)info_ptr->num_trans; j++)
00154                info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]);
00155          }
00156 #endif
00157       png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values),
00158          info_ptr->num_trans, info_ptr->color_type);
00159       }
00160 #endif
00161 #if defined(PNG_WRITE_bKGD_SUPPORTED)
00162    if (info_ptr->valid & PNG_INFO_bKGD)
00163       png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
00164 #endif
00165 #if defined(PNG_WRITE_hIST_SUPPORTED)
00166    if (info_ptr->valid & PNG_INFO_hIST)
00167       png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
00168 #endif
00169 #if defined(PNG_WRITE_oFFs_SUPPORTED)
00170    if (info_ptr->valid & PNG_INFO_oFFs)
00171       png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
00172          info_ptr->offset_unit_type);
00173 #endif
00174 #if defined(PNG_WRITE_pCAL_SUPPORTED)
00175    if (info_ptr->valid & PNG_INFO_pCAL)
00176       png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
00177          info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
00178          info_ptr->pcal_units, info_ptr->pcal_params);
00179 #endif
00180 #if defined(PNG_WRITE_sCAL_SUPPORTED)
00181    if (info_ptr->valid & PNG_INFO_sCAL)
00182 #if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
00183       png_write_sCAL(png_ptr, (int)info_ptr->scal_unit,
00184           info_ptr->scal_pixel_width, info_ptr->scal_pixel_height);
00185 #else
00186 #ifdef PNG_FIXED_POINT_SUPPORTED
00187       png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
00188           info_ptr->scal_s_width, info_ptr->scal_s_height);
00189 #else
00190       png_warning(png_ptr,
00191           "png_write_sCAL not supported; sCAL chunk not written.");
00192 #endif
00193 #endif
00194 #endif
00195 #if defined(PNG_WRITE_pHYs_SUPPORTED)
00196    if (info_ptr->valid & PNG_INFO_pHYs)
00197       png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
00198          info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
00199 #endif
00200 #if defined(PNG_WRITE_tIME_SUPPORTED)
00201    if (info_ptr->valid & PNG_INFO_tIME)
00202    {
00203       png_write_tIME(png_ptr, &(info_ptr->mod_time));
00204       png_ptr->mode |= PNG_WROTE_tIME;
00205    }
00206 #endif
00207 #if defined(PNG_WRITE_sPLT_SUPPORTED)
00208    if (info_ptr->valid & PNG_INFO_sPLT)
00209      for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
00210        png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
00211 #endif
00212 #if defined(PNG_WRITE_TEXT_SUPPORTED)
00213    /* Check to see if we need to write text chunks */
00214    for (i = 0; i < info_ptr->num_text; i++)
00215    {
00216       png_debug2(2, "Writing header text chunk %d, type %d\n", i,
00217          info_ptr->text[i].compression);
00218       /* an internationalized chunk? */
00219       if (info_ptr->text[i].compression > 0)
00220       {
00221 #if defined(PNG_WRITE_iTXt_SUPPORTED)
00222           /* write international chunk */
00223           png_write_iTXt(png_ptr,
00224                          info_ptr->text[i].compression,
00225                          info_ptr->text[i].key,
00226                          info_ptr->text[i].lang,
00227                          info_ptr->text[i].lang_key,
00228                          info_ptr->text[i].text);
00229 #else
00230           png_warning(png_ptr, "Unable to write international text");
00231 #endif
00232           /* Mark this chunk as written */
00233           info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
00234       }
00235       /* If we want a compressed text chunk */
00236       else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
00237       {
00238 #if defined(PNG_WRITE_zTXt_SUPPORTED)
00239          /* write compressed chunk */
00240          png_write_zTXt(png_ptr, info_ptr->text[i].key,
00241             info_ptr->text[i].text, 0,
00242             info_ptr->text[i].compression);
00243 #else
00244          png_warning(png_ptr, "Unable to write compressed text");
00245 #endif
00246          /* Mark this chunk as written */
00247          info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
00248       }
00249       else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
00250       {
00251 #if defined(PNG_WRITE_tEXt_SUPPORTED)
00252          /* write uncompressed chunk */
00253          png_write_tEXt(png_ptr, info_ptr->text[i].key,
00254                          info_ptr->text[i].text,
00255                          0);
00256 #else
00257          png_warning(png_ptr, "Unable to write uncompressed text");
00258 #endif
00259          /* Mark this chunk as written */
00260          info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
00261       }
00262    }
00263 #endif
00264 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
00265    if (info_ptr->unknown_chunks_num)
00266    {
00267        png_unknown_chunk *up;
00268 
00269        png_debug(5, "writing extra chunks\n");
00270 
00271        for (up = info_ptr->unknown_chunks;
00272             up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
00273             up++)
00274        {
00275          int keep=png_handle_as_unknown(png_ptr, up->name);
00276          if (keep != PNG_HANDLE_CHUNK_NEVER &&
00277             up->location && (up->location & PNG_HAVE_PLTE) &&
00278             !(up->location & PNG_HAVE_IDAT) &&
00279             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
00280             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
00281          {
00282             png_write_chunk(png_ptr, up->name, up->data, up->size);
00283          }
00284        }
00285    }
00286 #endif
00287 }
00288 
00289 /* Writes the end of the PNG file.  If you don't want to write comments or
00290  * time information, you can pass NULL for info.  If you already wrote these
00291  * in png_write_info(), do not write them again here.  If you have long
00292  * comments, I suggest writing them here, and compressing them.
00293  */
00294 void PNGAPI
00295 png_write_end(png_structp png_ptr, png_infop info_ptr)
00296 {
00297    png_debug(1, "in png_write_end\n");
00298    if (png_ptr == NULL)
00299       return;
00300    if (!(png_ptr->mode & PNG_HAVE_IDAT))
00301       png_error(png_ptr, "No IDATs written into file");
00302 
00303    /* see if user wants us to write information chunks */
00304    if (info_ptr != NULL)
00305    {
00306 #if defined(PNG_WRITE_TEXT_SUPPORTED)
00307       int i; /* local index variable */
00308 #endif
00309 #if defined(PNG_WRITE_tIME_SUPPORTED)
00310       /* check to see if user has supplied a time chunk */
00311       if ((info_ptr->valid & PNG_INFO_tIME) &&
00312          !(png_ptr->mode & PNG_WROTE_tIME))
00313          png_write_tIME(png_ptr, &(info_ptr->mod_time));
00314 #endif
00315 #if defined(PNG_WRITE_TEXT_SUPPORTED)
00316       /* loop through comment chunks */
00317       for (i = 0; i < info_ptr->num_text; i++)
00318       {
00319          png_debug2(2, "Writing trailer text chunk %d, type %d\n", i,
00320             info_ptr->text[i].compression);
00321          /* an internationalized chunk? */
00322          if (info_ptr->text[i].compression > 0)
00323          {
00324 #if defined(PNG_WRITE_iTXt_SUPPORTED)
00325              /* write international chunk */
00326              png_write_iTXt(png_ptr,
00327                          info_ptr->text[i].compression,
00328                          info_ptr->text[i].key,
00329                          info_ptr->text[i].lang,
00330                          info_ptr->text[i].lang_key,
00331                          info_ptr->text[i].text);
00332 #else
00333              png_warning(png_ptr, "Unable to write international text");
00334 #endif
00335              /* Mark this chunk as written */
00336              info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
00337          }
00338          else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
00339          {
00340 #if defined(PNG_WRITE_zTXt_SUPPORTED)
00341             /* write compressed chunk */
00342             png_write_zTXt(png_ptr, info_ptr->text[i].key,
00343                info_ptr->text[i].text, 0,
00344                info_ptr->text[i].compression);
00345 #else
00346             png_warning(png_ptr, "Unable to write compressed text");
00347 #endif
00348             /* Mark this chunk as written */
00349             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
00350          }
00351          else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
00352          {
00353 #if defined(PNG_WRITE_tEXt_SUPPORTED)
00354             /* write uncompressed chunk */
00355             png_write_tEXt(png_ptr, info_ptr->text[i].key,
00356                info_ptr->text[i].text, 0);
00357 #else
00358             png_warning(png_ptr, "Unable to write uncompressed text");
00359 #endif
00360 
00361             /* Mark this chunk as written */
00362             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
00363          }
00364       }
00365 #endif
00366 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
00367    if (info_ptr->unknown_chunks_num)
00368    {
00369        png_unknown_chunk *up;
00370 
00371        png_debug(5, "writing extra chunks\n");
00372 
00373        for (up = info_ptr->unknown_chunks;
00374             up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
00375             up++)
00376        {
00377          int keep=png_handle_as_unknown(png_ptr, up->name);
00378          if (keep != PNG_HANDLE_CHUNK_NEVER &&
00379             up->location && (up->location & PNG_AFTER_IDAT) &&
00380             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
00381             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
00382          {
00383             png_write_chunk(png_ptr, up->name, up->data, up->size);
00384          }
00385        }
00386    }
00387 #endif
00388    }
00389 
00390    png_ptr->mode |= PNG_AFTER_IDAT;
00391 
00392    /* write end of PNG file */
00393    png_write_IEND(png_ptr);
00394 }
00395 
00396 #if defined(PNG_WRITE_tIME_SUPPORTED)
00397 #if !defined(_WIN32_WCE)
00398 /* "time.h" functions are not supported on WindowsCE */
00399 void PNGAPI
00400 png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
00401 {
00402    png_debug(1, "in png_convert_from_struct_tm\n");
00403    ptime->year = (png_uint_16)(1900 + ttime->tm_year);
00404    ptime->month = (png_byte)(ttime->tm_mon + 1);
00405    ptime->day = (png_byte)ttime->tm_mday;
00406    ptime->hour = (png_byte)ttime->tm_hour;
00407    ptime->minute = (png_byte)ttime->tm_min;
00408    ptime->second = (png_byte)ttime->tm_sec;
00409 }
00410 
00411 void PNGAPI
00412 png_convert_from_time_t(png_timep ptime, time_t ttime)
00413 {
00414    struct tm *tbuf;
00415 
00416    png_debug(1, "in png_convert_from_time_t\n");
00417    tbuf = gmtime(&ttime);
00418    png_convert_from_struct_tm(ptime, tbuf);
00419 }
00420 #endif
00421 #endif
00422 
00423 /* Initialize png_ptr structure, and allocate any memory needed */
00424 png_structp PNGAPI
00425 png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr,
00426    png_error_ptr error_fn, png_error_ptr warn_fn)
00427 {
00428 #ifdef PNG_USER_MEM_SUPPORTED
00429    return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
00430       warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL));
00431 }
00432 
00433 /* Alternate initialize png_ptr structure, and allocate any memory needed */
00434 png_structp PNGAPI
00435 png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
00436    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
00437    png_malloc_ptr malloc_fn, png_free_ptr free_fn)
00438 {
00439 #endif /* PNG_USER_MEM_SUPPORTED */
00440    png_structp png_ptr;
00441 #ifdef PNG_SETJMP_SUPPORTED
00442 #ifdef USE_FAR_KEYWORD
00443    jmp_buf jmpbuf;
00444 #endif
00445 #endif
00446    int i;
00447    png_debug(1, "in png_create_write_struct\n");
00448 #ifdef PNG_USER_MEM_SUPPORTED
00449    png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
00450       (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
00451 #else
00452    png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
00453 #endif /* PNG_USER_MEM_SUPPORTED */
00454    if (png_ptr == NULL)
00455       return (NULL);
00456 
00457    /* added at libpng-1.2.6 */
00458 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
00459    png_ptr->user_width_max=PNG_USER_WIDTH_MAX;
00460    png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;
00461 #endif
00462 
00463 #ifdef PNG_SETJMP_SUPPORTED
00464 #ifdef USE_FAR_KEYWORD
00465    if (setjmp(jmpbuf))
00466 #else
00467    if (setjmp(png_ptr->jmpbuf))
00468 #endif
00469    {
00470       png_free(png_ptr, png_ptr->zbuf);
00471       png_ptr->zbuf=NULL;
00472       png_destroy_struct(png_ptr);
00473       return (NULL);
00474    }
00475 #ifdef USE_FAR_KEYWORD
00476    png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf));
00477 #endif
00478 #endif
00479 
00480 #ifdef PNG_USER_MEM_SUPPORTED
00481    png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
00482 #endif /* PNG_USER_MEM_SUPPORTED */
00483    png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
00484 
00485    i=0;
00486    do
00487    {
00488      if(user_png_ver[i] != png_libpng_ver[i])
00489         png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
00490    } while (png_libpng_ver[i++]);
00491 
00492    if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
00493    {
00494      /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
00495       * we must recompile any applications that use any older library version.
00496       * For versions after libpng 1.0, we will be compatible, so we need
00497       * only check the first digit.
00498       */
00499      if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
00500          (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
00501          (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
00502      {
00503 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
00504         char msg[80];
00505         if (user_png_ver)
00506         {
00507           png_snprintf(msg, 80,
00508              "Application was compiled with png.h from libpng-%.20s",
00509              user_png_ver);
00510           png_warning(png_ptr, msg);
00511         }
00512         png_snprintf(msg, 80,
00513            "Application  is  running with png.c from libpng-%.20s",
00514            png_libpng_ver);
00515         png_warning(png_ptr, msg);
00516 #endif
00517 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
00518         png_ptr->flags=0;
00519 #endif
00520         png_error(png_ptr,
00521            "Incompatible libpng version in application and library");
00522      }
00523    }
00524 
00525    /* initialize zbuf - compression buffer */
00526    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
00527    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
00528       (png_uint_32)png_ptr->zbuf_size);
00529 
00530    png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL,
00531       png_flush_ptr_NULL);
00532 
00533 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
00534    png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
00535       1, png_doublep_NULL, png_doublep_NULL);
00536 #endif
00537 
00538 #ifdef PNG_SETJMP_SUPPORTED
00539 /* Applications that neglect to set up their own setjmp() and then encounter
00540    a png_error() will longjmp here.  Since the jmpbuf is then meaningless we
00541    abort instead of returning. */
00542 #ifdef USE_FAR_KEYWORD
00543    if (setjmp(jmpbuf))
00544       PNG_ABORT();
00545    png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf));
00546 #else
00547    if (setjmp(png_ptr->jmpbuf))
00548       PNG_ABORT();
00549 #endif
00550 #endif
00551    return (png_ptr);
00552 }
00553 
00554 /* Initialize png_ptr structure, and allocate any memory needed */
00555 #if defined(PNG_1_0_X) || defined(PNG_1_2_X)
00556 /* Deprecated. */
00557 #undef png_write_init
00558 void PNGAPI
00559 png_write_init(png_structp png_ptr)
00560 {
00561    /* We only come here via pre-1.0.7-compiled applications */
00562    png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0);
00563 }
00564 
00565 void PNGAPI
00566 png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver,
00567    png_size_t png_struct_size, png_size_t png_info_size)
00568 {
00569    /* We only come here via pre-1.0.12-compiled applications */
00570    if(png_ptr == NULL) return;
00571 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
00572    if(png_sizeof(png_struct) > png_struct_size ||
00573       png_sizeof(png_info) > png_info_size)
00574    {
00575       char msg[80];
00576       png_ptr->warning_fn=NULL;
00577       if (user_png_ver)
00578       {
00579         png_snprintf(msg, 80,
00580            "Application was compiled with png.h from libpng-%.20s",
00581            user_png_ver);
00582         png_warning(png_ptr, msg);
00583       }
00584       png_snprintf(msg, 80,
00585          "Application  is  running with png.c from libpng-%.20s",
00586          png_libpng_ver);
00587       png_warning(png_ptr, msg);
00588    }
00589 #endif
00590    if(png_sizeof(png_struct) > png_struct_size)
00591      {
00592        png_ptr->error_fn=NULL;
00593 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
00594        png_ptr->flags=0;
00595 #endif
00596        png_error(png_ptr,
00597        "The png struct allocated by the application for writing is too small.");
00598      }
00599    if(png_sizeof(png_info) > png_info_size)
00600      {
00601        png_ptr->error_fn=NULL;
00602 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
00603        png_ptr->flags=0;
00604 #endif
00605        png_error(png_ptr,
00606        "The info struct allocated by the application for writing is too small.");
00607      }
00608    png_write_init_3(&png_ptr, user_png_ver, png_struct_size);
00609 }
00610 #endif /* PNG_1_0_X || PNG_1_2_X */
00611 
00612 
00613 void PNGAPI
00614 png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
00615    png_size_t png_struct_size)
00616 {
00617    png_structp png_ptr=*ptr_ptr;
00618 #ifdef PNG_SETJMP_SUPPORTED
00619    jmp_buf tmp_jmp; /* to save current jump buffer */
00620 #endif
00621 
00622    int i = 0;
00623 
00624    if (png_ptr == NULL)
00625       return;
00626 
00627    do
00628    {
00629      if (user_png_ver[i] != png_libpng_ver[i])
00630      {
00631 #ifdef PNG_LEGACY_SUPPORTED
00632        png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
00633 #else
00634        png_ptr->warning_fn=NULL;
00635        png_warning(png_ptr,
00636      "Application uses deprecated png_write_init() and should be recompiled.");
00637        break;
00638 #endif
00639      }
00640    } while (png_libpng_ver[i++]);
00641 
00642    png_debug(1, "in png_write_init_3\n");
00643 
00644 #ifdef PNG_SETJMP_SUPPORTED
00645    /* save jump buffer and error functions */
00646    png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf));
00647 #endif
00648 
00649    if (png_sizeof(png_struct) > png_struct_size)
00650      {
00651        png_destroy_struct(png_ptr);
00652        png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
00653        *ptr_ptr = png_ptr;
00654      }
00655 
00656    /* reset all variables to 0 */
00657    png_memset(png_ptr, 0, png_sizeof (png_struct));
00658 
00659    /* added at libpng-1.2.6 */
00660 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
00661    png_ptr->user_width_max=PNG_USER_WIDTH_MAX;
00662    png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;
00663 #endif
00664 
00665 #ifdef PNG_SETJMP_SUPPORTED
00666    /* restore jump buffer */
00667    png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf));
00668 #endif
00669 
00670    png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL,
00671       png_flush_ptr_NULL);
00672 
00673    /* initialize zbuf - compression buffer */
00674    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
00675    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
00676       (png_uint_32)png_ptr->zbuf_size);
00677 
00678 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
00679    png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
00680       1, png_doublep_NULL, png_doublep_NULL);
00681 #endif
00682 }
00683 
00684 /* Write a few rows of image data.  If the image is interlaced,
00685  * either you will have to write the 7 sub images, or, if you
00686  * have called png_set_interlace_handling(), you will have to
00687  * "write" the image seven times.
00688  */
00689 void PNGAPI
00690 png_write_rows(png_structp png_ptr, png_bytepp row,
00691    png_uint_32 num_rows)
00692 {
00693    png_uint_32 i; /* row counter */
00694    png_bytepp rp; /* row pointer */
00695 
00696    png_debug(1, "in png_write_rows\n");
00697 
00698    if (png_ptr == NULL)
00699       return;
00700 
00701    /* loop through the rows */
00702    for (i = 0, rp = row; i < num_rows; i++, rp++)
00703    {
00704       png_write_row(png_ptr, *rp);
00705    }
00706 }
00707 
00708 /* Write the image.  You only need to call this function once, even
00709  * if you are writing an interlaced image.
00710  */
00711 void PNGAPI
00712 png_write_image(png_structp png_ptr, png_bytepp image)
00713 {
00714    png_uint_32 i; /* row index */
00715    int pass, num_pass; /* pass variables */
00716    png_bytepp rp; /* points to current row */
00717 
00718    if (png_ptr == NULL)
00719       return;
00720 
00721    png_debug(1, "in png_write_image\n");
00722 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
00723    /* intialize interlace handling.  If image is not interlaced,
00724       this will set pass to 1 */
00725    num_pass = png_set_interlace_handling(png_ptr);
00726 #else
00727    num_pass = 1;
00728 #endif
00729    /* loop through passes */
00730    for (pass = 0; pass < num_pass; pass++)
00731    {
00732       /* loop through image */
00733       for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
00734       {
00735          png_write_row(png_ptr, *rp);
00736       }
00737    }
00738 }
00739 
00740 /* called by user to write a row of image data */
00741 void PNGAPI
00742 png_write_row(png_structp png_ptr, png_bytep row)
00743 {
00744    if (png_ptr == NULL)
00745       return;
00746    png_debug2(1, "in png_write_row (row %ld, pass %d)\n",
00747       png_ptr->row_number, png_ptr->pass);
00748 
00749    /* initialize transformations and other stuff if first time */
00750    if (png_ptr->row_number == 0 && png_ptr->pass == 0)
00751    {
00752    /* make sure we wrote the header info */
00753    if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
00754       png_error(png_ptr,
00755          "png_write_info was never called before png_write_row.");
00756 
00757    /* check for transforms that have been set but were defined out */
00758 #if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
00759    if (png_ptr->transformations & PNG_INVERT_MONO)
00760       png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined.");
00761 #endif
00762 #if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
00763    if (png_ptr->transformations & PNG_FILLER)
00764       png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined.");
00765 #endif
00766 #if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED)
00767    if (png_ptr->transformations & PNG_PACKSWAP)
00768       png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined.");
00769 #endif
00770 #if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
00771    if (png_ptr->transformations & PNG_PACK)
00772       png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined.");
00773 #endif
00774 #if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
00775    if (png_ptr->transformations & PNG_SHIFT)
00776       png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined.");
00777 #endif
00778 #if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
00779    if (png_ptr->transformations & PNG_BGR)
00780       png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined.");
00781 #endif
00782 #if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
00783    if (png_ptr->transformations & PNG_SWAP_BYTES)
00784       png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined.");
00785 #endif
00786 
00787       png_write_start_row(png_ptr);
00788    }
00789 
00790 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
00791    /* if interlaced and not interested in row, return */
00792    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
00793    {
00794       switch (png_ptr->pass)
00795       {
00796          case 0:
00797             if (png_ptr->row_number & 0x07)
00798             {
00799                png_write_finish_row(png_ptr);
00800                return;
00801             }
00802             break;
00803          case 1:
00804             if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
00805             {
00806                png_write_finish_row(png_ptr);
00807                return;
00808             }
00809             break;
00810          case 2:
00811             if ((png_ptr->row_number & 0x07) != 4)
00812             {
00813                png_write_finish_row(png_ptr);
00814                return;
00815             }
00816             break;
00817          case 3:
00818             if ((png_ptr->row_number & 0x03) || png_ptr->width < 3)
00819             {
00820                png_write_finish_row(png_ptr);
00821                return;
00822             }
00823             break;
00824          case 4:
00825             if ((png_ptr->row_number & 0x03) != 2)
00826             {
00827                png_write_finish_row(png_ptr);
00828                return;
00829             }
00830             break;
00831          case 5:
00832             if ((png_ptr->row_number & 0x01) || png_ptr->width < 2)
00833             {
00834                png_write_finish_row(png_ptr);
00835                return;
00836             }
00837             break;
00838          case 6:
00839             if (!(png_ptr->row_number & 0x01))
00840             {
00841                png_write_finish_row(png_ptr);
00842                return;
00843             }
00844             break;
00845       }
00846    }
00847 #endif
00848 
00849    /* set up row info for transformations */
00850    png_ptr->row_info.color_type = png_ptr->color_type;
00851    png_ptr->row_info.width = png_ptr->usr_width;
00852    png_ptr->row_info.channels = png_ptr->usr_channels;
00853    png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
00854    png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
00855       png_ptr->row_info.channels);
00856 
00857    png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
00858       png_ptr->row_info.width);
00859 
00860    png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type);
00861    png_debug1(3, "row_info->width = %lu\n", png_ptr->row_info.width);
00862    png_debug1(3, "row_info->channels = %d\n", png_ptr->row_info.channels);
00863    png_debug1(3, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth);
00864    png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth);
00865    png_debug1(3, "row_info->rowbytes = %lu\n", png_ptr->row_info.rowbytes);
00866 
00867    /* Copy user's row into buffer, leaving room for filter byte. */
00868    png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row,
00869       png_ptr->row_info.rowbytes);
00870 
00871 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
00872    /* handle interlacing */
00873    if (png_ptr->interlaced && png_ptr->pass < 6 &&
00874       (png_ptr->transformations & PNG_INTERLACE))
00875    {
00876       png_do_write_interlace(&(png_ptr->row_info),
00877          png_ptr->row_buf + 1, png_ptr->pass);
00878       /* this should always get caught above, but still ... */
00879       if (!(png_ptr->row_info.width))
00880       {
00881          png_write_finish_row(png_ptr);
00882          return;
00883       }
00884    }
00885 #endif
00886 
00887    /* handle other transformations */
00888    if (png_ptr->transformations)
00889       png_do_write_transformations(png_ptr);
00890 
00891 #if defined(PNG_MNG_FEATURES_SUPPORTED)
00892    /* Write filter_method 64 (intrapixel differencing) only if
00893     * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
00894     * 2. Libpng did not write a PNG signature (this filter_method is only
00895     *    used in PNG datastreams that are embedded in MNG datastreams) and
00896     * 3. The application called png_permit_mng_features with a mask that
00897     *    included PNG_FLAG_MNG_FILTER_64 and
00898     * 4. The filter_method is 64 and
00899     * 5. The color_type is RGB or RGBA
00900     */
00901    if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
00902       (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
00903    {
00904       /* Intrapixel differencing */
00905       png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1);
00906    }
00907 #endif
00908 
00909    /* Find a filter if necessary, filter the row and write it out. */
00910    png_write_find_filter(png_ptr, &(png_ptr->row_info));
00911 
00912    if (png_ptr->write_row_fn != NULL)
00913       (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
00914 }
00915 
00916 #if defined(PNG_WRITE_FLUSH_SUPPORTED)
00917 /* Set the automatic flush interval or 0 to turn flushing off */
00918 void PNGAPI
00919 png_set_flush(png_structp png_ptr, int nrows)
00920 {
00921    png_debug(1, "in png_set_flush\n");
00922    if (png_ptr == NULL)
00923       return;
00924    png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
00925 }
00926 
00927 /* flush the current output buffers now */
00928 void PNGAPI
00929 png_write_flush(png_structp png_ptr)
00930 {
00931    int wrote_IDAT;
00932 
00933    png_debug(1, "in png_write_flush\n");
00934    if (png_ptr == NULL)
00935       return;
00936    /* We have already written out all of the data */
00937    if (png_ptr->row_number >= png_ptr->num_rows)
00938      return;
00939 
00940    do
00941    {
00942       int ret;
00943 
00944       /* compress the data */
00945       ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH);
00946       wrote_IDAT = 0;
00947 
00948       /* check for compression errors */
00949       if (ret != Z_OK)
00950       {
00951          if (png_ptr->zstream.msg != NULL)
00952             png_error(png_ptr, png_ptr->zstream.msg);
00953          else
00954             png_error(png_ptr, "zlib error");
00955       }
00956 
00957       if (!(png_ptr->zstream.avail_out))
00958       {
00959          /* write the IDAT and reset the zlib output buffer */
00960          png_write_IDAT(png_ptr, png_ptr->zbuf,
00961                         png_ptr->zbuf_size);
00962          png_ptr->zstream.next_out = png_ptr->zbuf;
00963          png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
00964          wrote_IDAT = 1;
00965       }
00966    } while(wrote_IDAT == 1);
00967 
00968    /* If there is any data left to be output, write it into a new IDAT */
00969    if (png_ptr->zbuf_size != png_ptr->zstream.avail_out)
00970    {
00971       /* write the IDAT and reset the zlib output buffer */
00972       png_write_IDAT(png_ptr, png_ptr->zbuf,
00973                      png_ptr->zbuf_size - png_ptr->zstream.avail_out);
00974       png_ptr->zstream.next_out = png_ptr->zbuf;
00975       png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
00976    }
00977    png_ptr->flush_rows = 0;
00978    png_flush(png_ptr);
00979 }
00980 #endif /* PNG_WRITE_FLUSH_SUPPORTED */
00981 
00982 /* free all memory used by the write */
00983 void PNGAPI
00984 png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
00985 {
00986    png_structp png_ptr = NULL;
00987    png_infop info_ptr = NULL;
00988 #ifdef PNG_USER_MEM_SUPPORTED
00989    png_free_ptr free_fn = NULL;
00990    png_voidp mem_ptr = NULL;
00991 #endif
00992 
00993    png_debug(1, "in png_destroy_write_struct\n");
00994    if (png_ptr_ptr != NULL)
00995    {
00996       png_ptr = *png_ptr_ptr;
00997 #ifdef PNG_USER_MEM_SUPPORTED
00998       free_fn = png_ptr->free_fn;
00999       mem_ptr = png_ptr->mem_ptr;
01000 #endif
01001    }
01002 
01003    if (info_ptr_ptr != NULL)
01004       info_ptr = *info_ptr_ptr;
01005 
01006    if (info_ptr != NULL)
01007    {
01008       png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
01009 
01010 #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
01011       if (png_ptr->num_chunk_list)
01012       {
01013          png_free(png_ptr, png_ptr->chunk_list);
01014          png_ptr->chunk_list=NULL;
01015          png_ptr->num_chunk_list=0;
01016       }
01017 #endif
01018 
01019 #ifdef PNG_USER_MEM_SUPPORTED
01020       png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
01021          (png_voidp)mem_ptr);
01022 #else
01023       png_destroy_struct((png_voidp)info_ptr);
01024 #endif
01025       *info_ptr_ptr = NULL;
01026    }
01027 
01028    if (png_ptr != NULL)
01029    {
01030       png_write_destroy(png_ptr);
01031 #ifdef PNG_USER_MEM_SUPPORTED
01032       png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
01033          (png_voidp)mem_ptr);
01034 #else
01035       png_destroy_struct((png_voidp)png_ptr);
01036 #endif
01037       *png_ptr_ptr = NULL;
01038    }
01039 }
01040 
01041 
01042 /* Free any memory used in png_ptr struct (old method) */
01043 void /* PRIVATE */
01044 png_write_destroy(png_structp png_ptr)
01045 {
01046 #ifdef PNG_SETJMP_SUPPORTED
01047    jmp_buf tmp_jmp; /* save jump buffer */
01048 #endif
01049    png_error_ptr error_fn;
01050    png_error_ptr warning_fn;
01051    png_voidp error_ptr;
01052 #ifdef PNG_USER_MEM_SUPPORTED
01053    png_free_ptr free_fn;
01054 #endif
01055 
01056    png_debug(1, "in png_write_destroy\n");
01057    /* free any memory zlib uses */
01058    deflateEnd(&png_ptr->zstream);
01059 
01060    /* free our memory.  png_free checks NULL for us. */
01061    png_free(png_ptr, png_ptr->zbuf);
01062    png_free(png_ptr, png_ptr->row_buf);
01063    png_free(png_ptr, png_ptr->prev_row);
01064    png_free(png_ptr, png_ptr->sub_row);
01065    png_free(png_ptr, png_ptr->up_row);
01066    png_free(png_ptr, png_ptr->avg_row);
01067    png_free(png_ptr, png_ptr->paeth_row);
01068 
01069 #if defined(PNG_TIME_RFC1123_SUPPORTED)
01070    png_free(png_ptr, png_ptr->time_buffer);
01071 #endif
01072 
01073 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
01074    png_free(png_ptr, png_ptr->prev_filters);
01075    png_free(png_ptr, png_ptr->filter_weights);
01076    png_free(png_ptr, png_ptr->inv_filter_weights);
01077    png_free(png_ptr, png_ptr->filter_costs);
01078    png_free(png_ptr, png_ptr->inv_filter_costs);
01079 #endif
01080 
01081 #ifdef PNG_SETJMP_SUPPORTED
01082    /* reset structure */
01083    png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf));
01084 #endif
01085 
01086    error_fn = png_ptr->error_fn;
01087    warning_fn = png_ptr->warning_fn;
01088    error_ptr = png_ptr->error_ptr;
01089 #ifdef PNG_USER_MEM_SUPPORTED
01090    free_fn = png_ptr->free_fn;
01091 #endif
01092 
01093    png_memset(png_ptr, 0, png_sizeof (png_struct));
01094 
01095    png_ptr->error_fn = error_fn;
01096    png_ptr->warning_fn = warning_fn;
01097    png_ptr->error_ptr = error_ptr;
01098 #ifdef PNG_USER_MEM_SUPPORTED
01099    png_ptr->free_fn = free_fn;
01100 #endif
01101 
01102 #ifdef PNG_SETJMP_SUPPORTED
01103    png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf));
01104 #endif
01105 }
01106 
01107 /* Allow the application to select one or more row filters to use. */
01108 void PNGAPI
01109 png_set_filter(png_structp png_ptr, int method, int filters)
01110 {
01111    png_debug(1, "in png_set_filter\n");
01112    if (png_ptr == NULL)
01113       return;
01114 #if defined(PNG_MNG_FEATURES_SUPPORTED)
01115    if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
01116       (method == PNG_INTRAPIXEL_DIFFERENCING))
01117          method = PNG_FILTER_TYPE_BASE;
01118 #endif
01119    if (method == PNG_FILTER_TYPE_BASE)
01120    {
01121       switch (filters & (PNG_ALL_FILTERS | 0x07))
01122       {
01123 #ifndef PNG_NO_WRITE_FILTER
01124          case 5:
01125          case 6:
01126          case 7: png_warning(png_ptr, "Unknown row filter for method 0");
01127 #endif /* PNG_NO_WRITE_FILTER */
01128          case PNG_FILTER_VALUE_NONE:
01129               png_ptr->do_filter=PNG_FILTER_NONE; break;
01130 #ifndef PNG_NO_WRITE_FILTER
01131          case PNG_FILTER_VALUE_SUB:
01132               png_ptr->do_filter=PNG_FILTER_SUB; break;
01133          case PNG_FILTER_VALUE_UP:
01134               png_ptr->do_filter=PNG_FILTER_UP; break;
01135          case PNG_FILTER_VALUE_AVG:
01136               png_ptr->do_filter=PNG_FILTER_AVG; break;
01137          case PNG_FILTER_VALUE_PAETH:
01138               png_ptr->do_filter=PNG_FILTER_PAETH; break;
01139          default: png_ptr->do_filter = (png_byte)filters; break;
01140 #else
01141          default: png_warning(png_ptr, "Unknown row filter for method 0");
01142 #endif /* PNG_NO_WRITE_FILTER */
01143       }
01144 
01145       /* If we have allocated the row_buf, this means we have already started
01146        * with the image and we should have allocated all of the filter buffers
01147        * that have been selected.  If prev_row isn't already allocated, then
01148        * it is too late to start using the filters that need it, since we
01149        * will be missing the data in the previous row.  If an application
01150        * wants to start and stop using particular filters during compression,
01151        * it should start out with all of the filters, and then add and
01152        * remove them after the start of compression.
01153        */
01154       if (png_ptr->row_buf != NULL)
01155       {
01156 #ifndef PNG_NO_WRITE_FILTER
01157          if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL)
01158          {
01159             png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
01160               (png_ptr->rowbytes + 1));
01161             png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
01162          }
01163 
01164          if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL)
01165          {
01166             if (png_ptr->prev_row == NULL)
01167             {
01168                png_warning(png_ptr, "Can't add Up filter after starting");
01169                png_ptr->do_filter &= ~PNG_FILTER_UP;
01170             }
01171             else
01172             {
01173                png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
01174                   (png_ptr->rowbytes + 1));
01175                png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
01176             }
01177          }
01178 
01179          if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL)
01180          {
01181             if (png_ptr->prev_row == NULL)
01182             {
01183                png_warning(png_ptr, "Can't add Average filter after starting");
01184                png_ptr->do_filter &= ~PNG_FILTER_AVG;
01185             }
01186             else
01187             {
01188                png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
01189                   (png_ptr->rowbytes + 1));
01190                png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
01191             }
01192          }
01193 
01194          if ((png_ptr->do_filter & PNG_FILTER_PAETH) &&
01195              png_ptr->paeth_row == NULL)
01196          {
01197             if (png_ptr->prev_row == NULL)
01198             {
01199                png_warning(png_ptr, "Can't add Paeth filter after starting");
01200                png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH);
01201             }
01202             else
01203             {
01204                png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
01205                   (png_ptr->rowbytes + 1));
01206                png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
01207             }
01208          }
01209 
01210          if (png_ptr->do_filter == PNG_NO_FILTERS)
01211 #endif /* PNG_NO_WRITE_FILTER */
01212             png_ptr->do_filter = PNG_FILTER_NONE;
01213       }
01214    }
01215    else
01216       png_error(png_ptr, "Unknown custom filter method");
01217 }
01218 
01219 /* This allows us to influence the way in which libpng chooses the "best"
01220  * filter for the current scanline.  While the "minimum-sum-of-absolute-
01221  * differences metric is relatively fast and effective, there is some
01222  * question as to whether it can be improved upon by trying to keep the
01223  * filtered data going to zlib more consistent, hopefully resulting in
01224  * better compression.
01225  */
01226 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)      /* GRR 970116 */
01227 void PNGAPI
01228 png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
01229    int num_weights, png_doublep filter_weights,
01230    png_doublep filter_costs)
01231 {
01232    int i;
01233 
01234    png_debug(1, "in png_set_filter_heuristics\n");
01235    if (png_ptr == NULL)
01236       return;
01237    if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)
01238    {
01239       png_warning(png_ptr, "Unknown filter heuristic method");
01240       return;
01241    }
01242 
01243    if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT)
01244    {
01245       heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED;
01246    }
01247 
01248    if (num_weights < 0 || filter_weights == NULL ||
01249       heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED)
01250    {
01251       num_weights = 0;
01252    }
01253 
01254    png_ptr->num_prev_filters = (png_byte)num_weights;
01255    png_ptr->heuristic_method = (png_byte)heuristic_method;
01256 
01257    if (num_weights > 0)
01258    {
01259       if (png_ptr->prev_filters == NULL)
01260       {
01261          png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
01262             (png_uint_32)(png_sizeof(png_byte) * num_weights));
01263 
01264          /* To make sure that the weighting starts out fairly */
01265          for (i = 0; i < num_weights; i++)
01266          {
01267             png_ptr->prev_filters[i] = 255;
01268          }
01269       }
01270 
01271       if (png_ptr->filter_weights == NULL)
01272       {
01273          png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
01274             (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
01275 
01276          png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
01277             (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
01278          for (i = 0; i < num_weights; i++)
01279          {
01280             png_ptr->inv_filter_weights[i] =
01281             png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
01282          }
01283       }
01284 
01285       for (i = 0; i < num_weights; i++)
01286       {
01287          if (filter_weights[i] < 0.0)
01288          {
01289             png_ptr->inv_filter_weights[i] =
01290             png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
01291          }
01292          else
01293          {
01294             png_ptr->inv_filter_weights[i] =
01295                (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5);
01296             png_ptr->filter_weights[i] =
01297                (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5);
01298          }
01299       }
01300    }
01301 
01302    /* If, in the future, there are other filter methods, this would
01303     * need to be based on png_ptr->filter.
01304     */
01305    if (png_ptr->filter_costs == NULL)
01306    {
01307       png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
01308          (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
01309 
01310       png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
01311          (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
01312 
01313       for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
01314       {
01315          png_ptr->inv_filter_costs[i] =
01316          png_ptr->filter_costs[i] = PNG_COST_FACTOR;
01317       }
01318    }
01319 
01320    /* Here is where we set the relative costs of the different filters.  We
01321     * should take the desired compression level into account when setting
01322     * the costs, so that Paeth, for instance, has a high relative cost at low
01323     * compression levels, while it has a lower relative cost at higher
01324     * compression settings.  The filter types are in order of increasing
01325     * relative cost, so it would be possible to do this with an algorithm.
01326     */
01327    for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
01328    {
01329       if (filter_costs == NULL || filter_costs[i] < 0.0)
01330       {
01331          png_ptr->inv_filter_costs[i] =
01332          png_ptr->filter_costs[i] = PNG_COST_FACTOR;
01333       }
01334       else if (filter_costs[i] >= 1.0)
01335       {
01336          png_ptr->inv_filter_costs[i] =
01337             (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5);
01338          png_ptr->filter_costs[i] =
01339             (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5);
01340       }
01341    }
01342 }
01343 #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
01344 
01345 void PNGAPI
01346 png_set_compression_level(png_structp png_ptr, int level)
01347 {
01348    png_debug(1, "in png_set_compression_level\n");
01349    if (png_ptr == NULL)
01350       return;
01351    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
01352    png_ptr->zlib_level = level;
01353 }
01354 
01355 void PNGAPI
01356 png_set_compression_mem_level(png_structp png_ptr, int mem_level)
01357 {
01358    png_debug(1, "in png_set_compression_mem_level\n");
01359    if (png_ptr == NULL)
01360       return;
01361    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
01362    png_ptr->zlib_mem_level = mem_level;
01363 }
01364 
01365 void PNGAPI
01366 png_set_compression_strategy(png_structp png_ptr, int strategy)
01367 {
01368    png_debug(1, "in png_set_compression_strategy\n");
01369    if (png_ptr == NULL)
01370       return;
01371    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
01372    png_ptr->zlib_strategy = strategy;
01373 }
01374 
01375 void PNGAPI
01376 png_set_compression_window_bits(png_structp png_ptr, int window_bits)
01377 {
01378    if (png_ptr == NULL)
01379       return;
01380    if (window_bits > 15)
01381       png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
01382    else if (window_bits < 8)
01383       png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
01384 #ifndef WBITS_8_OK
01385    /* avoid libpng bug with 256-byte windows */
01386    if (window_bits == 8)
01387      {
01388        png_warning(png_ptr, "Compression window is being reset to 512");
01389        window_bits=9;
01390      }
01391 #endif
01392    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
01393    png_ptr->zlib_window_bits = window_bits;
01394 }
01395 
01396 void PNGAPI
01397 png_set_compression_method(png_structp png_ptr, int method)
01398 {
01399    png_debug(1, "in png_set_compression_method\n");
01400    if (png_ptr == NULL)
01401       return;
01402    if (method != 8)
01403       png_warning(png_ptr, "Only compression method 8 is supported by PNG");
01404    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
01405    png_ptr->zlib_method = method;
01406 }
01407 
01408 void PNGAPI
01409 png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn)
01410 {
01411    if (png_ptr == NULL)
01412       return;
01413    png_ptr->write_row_fn = write_row_fn;
01414 }
01415 
01416 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
01417 void PNGAPI
01418 png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
01419    write_user_transform_fn)
01420 {
01421    png_debug(1, "in png_set_write_user_transform_fn\n");
01422    if (png_ptr == NULL)
01423       return;
01424    png_ptr->transformations |= PNG_USER_TRANSFORM;
01425    png_ptr->write_user_transform_fn = write_user_transform_fn;
01426 }
01427 #endif
01428 
01429 
01430 #if defined(PNG_INFO_IMAGE_SUPPORTED)
01431 void PNGAPI
01432 png_write_png(png_structp png_ptr, png_infop info_ptr,
01433               int transforms, voidp params)
01434 {
01435    if (png_ptr == NULL || info_ptr == NULL)
01436       return;
01437 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
01438    /* invert the alpha channel from opacity to transparency */
01439    if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
01440        png_set_invert_alpha(png_ptr);
01441 #endif
01442 
01443    /* Write the file header information. */
01444    png_write_info(png_ptr, info_ptr);
01445 
01446    /* ------ these transformations don't touch the info structure ------- */
01447 
01448 #if defined(PNG_WRITE_INVERT_SUPPORTED)
01449    /* invert monochrome pixels */
01450    if (transforms & PNG_TRANSFORM_INVERT_MONO)
01451        png_set_invert_mono(png_ptr);
01452 #endif
01453 
01454 #if defined(PNG_WRITE_SHIFT_SUPPORTED)
01455    /* Shift the pixels up to a legal bit depth and fill in
01456     * as appropriate to correctly scale the image.
01457     */
01458    if ((transforms & PNG_TRANSFORM_SHIFT)
01459                && (info_ptr->valid & PNG_INFO_sBIT))
01460        png_set_shift(png_ptr, &info_ptr->sig_bit);
01461 #endif
01462 
01463 #if defined(PNG_WRITE_PACK_SUPPORTED)
01464    /* pack pixels into bytes */
01465    if (transforms & PNG_TRANSFORM_PACKING)
01466        png_set_packing(png_ptr);
01467 #endif
01468 
01469 #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
01470    /* swap location of alpha bytes from ARGB to RGBA */
01471    if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
01472        png_set_swap_alpha(png_ptr);
01473 #endif
01474 
01475 #if defined(PNG_WRITE_FILLER_SUPPORTED)
01476    /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
01477     * RGB (4 channels -> 3 channels). The second parameter is not used.
01478     */
01479    if (transforms & PNG_TRANSFORM_STRIP_FILLER)
01480        png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
01481 #endif
01482 
01483 #if defined(PNG_WRITE_BGR_SUPPORTED)
01484    /* flip BGR pixels to RGB */
01485    if (transforms & PNG_TRANSFORM_BGR)
01486        png_set_bgr(png_ptr);
01487 #endif
01488 
01489 #if defined(PNG_WRITE_SWAP_SUPPORTED)
01490    /* swap bytes of 16-bit files to most significant byte first */
01491    if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
01492        png_set_swap(png_ptr);
01493 #endif
01494 
01495 #if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
01496    /* swap bits of 1, 2, 4 bit packed pixel formats */
01497    if (transforms & PNG_TRANSFORM_PACKSWAP)
01498        png_set_packswap(png_ptr);
01499 #endif
01500 
01501    /* ----------------------- end of transformations ------------------- */
01502 
01503    /* write the bits */
01504    if (info_ptr->valid & PNG_INFO_IDAT)
01505        png_write_image(png_ptr, info_ptr->row_pointers);
01506 
01507    /* It is REQUIRED to call this to finish writing the rest of the file */
01508    png_write_end(png_ptr, info_ptr);
01509 
01510    transforms = transforms; /* quiet compiler warnings */
01511    params = params;
01512 }
01513 #endif
01514 #endif /* PNG_WRITE_SUPPORTED */

Generated on Tue Jul 5 14:13:31 2011 for ROOT_528-00b_version by  doxygen 1.5.1