pngwrite.c
上传用户:jnfxsk
上传日期:2022-06-16
资源大小:3675k
文件大小:48k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /* pngwrite.c - general routines to write a PNG file
  2.  *
  3.  * libpng 1.2.8 - December 3, 2004
  4.  * For conditions of distribution and use, see copyright notice in png.h
  5.  * Copyright (c) 1998-2004 Glenn Randers-Pehrson
  6.  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  7.  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  8.  */
  9. /* get internal access to png.h */
  10. #define PNG_INTERNAL
  11. #include "png.h"
  12. #ifdef PNG_WRITE_SUPPORTED
  13. /* Writes all the PNG information.  This is the suggested way to use the
  14.  * library.  If you have a new chunk to add, make a function to write it,
  15.  * and put it in the correct location here.  If you want the chunk written
  16.  * after the image data, put it in png_write_end().  I strongly encourage
  17.  * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
  18.  * the chunk, as that will keep the code from breaking if you want to just
  19.  * write a plain PNG file.  If you have long comments, I suggest writing
  20.  * them in png_write_end(), and compressing them.
  21.  */
  22. void PNGAPI
  23. png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
  24. {
  25.    png_debug(1, "in png_write_info_before_PLTEn");
  26.    if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
  27.    {
  28.    png_write_sig(png_ptr); /* write PNG signature */
  29. #if defined(PNG_MNG_FEATURES_SUPPORTED)
  30.    if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted))
  31.    {
  32.       png_warning(png_ptr,"MNG features are not allowed in a PNG datastreamn");
  33.       png_ptr->mng_features_permitted=0;
  34.    }
  35. #endif
  36.    /* write IHDR information. */
  37.    png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
  38.       info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
  39.       info_ptr->filter_type,
  40. #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
  41.       info_ptr->interlace_type);
  42. #else
  43.       0);
  44. #endif
  45.    /* the rest of these check to see if the valid field has the appropriate
  46.       flag set, and if it does, writes the chunk. */
  47. #if defined(PNG_WRITE_gAMA_SUPPORTED)
  48.    if (info_ptr->valid & PNG_INFO_gAMA)
  49.    {
  50. #  ifdef PNG_FLOATING_POINT_SUPPORTED
  51.       png_write_gAMA(png_ptr, info_ptr->gamma);
  52. #else
  53. #ifdef PNG_FIXED_POINT_SUPPORTED
  54.       png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma);
  55. #  endif
  56. #endif
  57.    }
  58. #endif
  59. #if defined(PNG_WRITE_sRGB_SUPPORTED)
  60.    if (info_ptr->valid & PNG_INFO_sRGB)
  61.       png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
  62. #endif
  63. #if defined(PNG_WRITE_iCCP_SUPPORTED)
  64.    if (info_ptr->valid & PNG_INFO_iCCP)
  65.       png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
  66.                      info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
  67. #endif
  68. #if defined(PNG_WRITE_sBIT_SUPPORTED)
  69.    if (info_ptr->valid & PNG_INFO_sBIT)
  70.       png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
  71. #endif
  72. #if defined(PNG_WRITE_cHRM_SUPPORTED)
  73.    if (info_ptr->valid & PNG_INFO_cHRM)
  74.    {
  75. #ifdef PNG_FLOATING_POINT_SUPPORTED
  76.       png_write_cHRM(png_ptr,
  77.          info_ptr->x_white, info_ptr->y_white,
  78.          info_ptr->x_red, info_ptr->y_red,
  79.          info_ptr->x_green, info_ptr->y_green,
  80.          info_ptr->x_blue, info_ptr->y_blue);
  81. #else
  82. #  ifdef PNG_FIXED_POINT_SUPPORTED
  83.       png_write_cHRM_fixed(png_ptr,
  84.          info_ptr->int_x_white, info_ptr->int_y_white,
  85.          info_ptr->int_x_red, info_ptr->int_y_red,
  86.          info_ptr->int_x_green, info_ptr->int_y_green,
  87.          info_ptr->int_x_blue, info_ptr->int_y_blue);
  88. #  endif
  89. #endif
  90.    }
  91. #endif
  92. #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
  93.    if (info_ptr->unknown_chunks_num)
  94.    {
  95.        png_unknown_chunk *up;
  96.        png_debug(5, "writing extra chunksn");
  97.        for (up = info_ptr->unknown_chunks;
  98.             up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
  99.             up++)
  100.        {
  101.          int keep=png_handle_as_unknown(png_ptr, up->name);
  102.          if (keep != PNG_HANDLE_CHUNK_NEVER &&
  103.             up->location && !(up->location & PNG_HAVE_PLTE) &&
  104.             !(up->location & PNG_HAVE_IDAT) &&
  105.             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
  106.             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
  107.          {
  108.             png_write_chunk(png_ptr, up->name, up->data, up->size);
  109.          }
  110.        }
  111.    }
  112. #endif
  113.       png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
  114.    }
  115. }
  116. void PNGAPI
  117. png_write_info(png_structp png_ptr, png_infop info_ptr)
  118. {
  119. #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
  120.    int i;
  121. #endif
  122.    png_debug(1, "in png_write_infon");
  123.    png_write_info_before_PLTE(png_ptr, info_ptr);
  124.    if (info_ptr->valid & PNG_INFO_PLTE)
  125.       png_write_PLTE(png_ptr, info_ptr->palette,
  126.          (png_uint_32)info_ptr->num_palette);
  127.    else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  128.       png_error(png_ptr, "Valid palette required for paletted imagesn");
  129. #if defined(PNG_WRITE_tRNS_SUPPORTED)
  130.    if (info_ptr->valid & PNG_INFO_tRNS)
  131.       {
  132. #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
  133.          /* invert the alpha channel (in tRNS) */
  134.          if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
  135.             info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  136.          {
  137.             int j;
  138.             for (j=0; j<(int)info_ptr->num_trans; j++)
  139.                info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]);
  140.          }
  141. #endif
  142.       png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values),
  143.          info_ptr->num_trans, info_ptr->color_type);
  144.       }
  145. #endif
  146. #if defined(PNG_WRITE_bKGD_SUPPORTED)
  147.    if (info_ptr->valid & PNG_INFO_bKGD)
  148.       png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
  149. #endif
  150. #if defined(PNG_WRITE_hIST_SUPPORTED)
  151.    if (info_ptr->valid & PNG_INFO_hIST)
  152.       png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
  153. #endif
  154. #if defined(PNG_WRITE_oFFs_SUPPORTED)
  155.    if (info_ptr->valid & PNG_INFO_oFFs)
  156.       png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
  157.          info_ptr->offset_unit_type);
  158. #endif
  159. #if defined(PNG_WRITE_pCAL_SUPPORTED)
  160.    if (info_ptr->valid & PNG_INFO_pCAL)
  161.       png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
  162.          info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
  163.          info_ptr->pcal_units, info_ptr->pcal_params);
  164. #endif
  165. #if defined(PNG_WRITE_sCAL_SUPPORTED)
  166.    if (info_ptr->valid & PNG_INFO_sCAL)
  167. #if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
  168.       png_write_sCAL(png_ptr, (int)info_ptr->scal_unit,
  169.           info_ptr->scal_pixel_width, info_ptr->scal_pixel_height);
  170. #else
  171. #ifdef PNG_FIXED_POINT_SUPPORTED
  172.       png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
  173.           info_ptr->scal_s_width, info_ptr->scal_s_height);
  174. #else
  175.       png_warning(png_ptr,
  176.           "png_write_sCAL not supported; sCAL chunk not written.n");
  177. #endif
  178. #endif
  179. #endif
  180. #if defined(PNG_WRITE_pHYs_SUPPORTED)
  181.    if (info_ptr->valid & PNG_INFO_pHYs)
  182.       png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
  183.          info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
  184. #endif
  185. #if defined(PNG_WRITE_tIME_SUPPORTED)
  186.    if (info_ptr->valid & PNG_INFO_tIME)
  187.    {
  188.       png_write_tIME(png_ptr, &(info_ptr->mod_time));
  189.       png_ptr->mode |= PNG_WROTE_tIME;
  190.    }
  191. #endif
  192. #if defined(PNG_WRITE_sPLT_SUPPORTED)
  193.    if (info_ptr->valid & PNG_INFO_sPLT)
  194.      for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
  195.        png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
  196. #endif
  197. #if defined(PNG_WRITE_TEXT_SUPPORTED)
  198.    /* Check to see if we need to write text chunks */
  199.    for (i = 0; i < info_ptr->num_text; i++)
  200.    {
  201.       png_debug2(2, "Writing header text chunk %d, type %dn", i,
  202.          info_ptr->text[i].compression);
  203.       /* an internationalized chunk? */
  204.       if (info_ptr->text[i].compression > 0)
  205.       {
  206. #if defined(PNG_WRITE_iTXt_SUPPORTED)
  207.           /* write international chunk */
  208.           png_write_iTXt(png_ptr,
  209.                          info_ptr->text[i].compression,
  210.                          info_ptr->text[i].key,
  211.                          info_ptr->text[i].lang,
  212.                          info_ptr->text[i].lang_key,
  213.                          info_ptr->text[i].text);
  214. #else
  215.           png_warning(png_ptr, "Unable to write international textn");
  216. #endif
  217.           /* Mark this chunk as written */
  218.           info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
  219.       }
  220.       /* If we want a compressed text chunk */
  221.       else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
  222.       {
  223. #if defined(PNG_WRITE_zTXt_SUPPORTED)
  224.          /* write compressed chunk */
  225.          png_write_zTXt(png_ptr, info_ptr->text[i].key,
  226.             info_ptr->text[i].text, 0,
  227.             info_ptr->text[i].compression);
  228. #else
  229.          png_warning(png_ptr, "Unable to write compressed textn");
  230. #endif
  231.          /* Mark this chunk as written */
  232.          info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
  233.       }
  234.       else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
  235.       {
  236. #if defined(PNG_WRITE_tEXt_SUPPORTED)
  237.          /* write uncompressed chunk */
  238.          png_write_tEXt(png_ptr, info_ptr->text[i].key,
  239.                          info_ptr->text[i].text,
  240.                          0);
  241. #else
  242.          png_warning(png_ptr, "Unable to write uncompressed textn");
  243. #endif
  244.          /* Mark this chunk as written */
  245.          info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
  246.       }
  247.    }
  248. #endif
  249. #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
  250.    if (info_ptr->unknown_chunks_num)
  251.    {
  252.        png_unknown_chunk *up;
  253.        png_debug(5, "writing extra chunksn");
  254.        for (up = info_ptr->unknown_chunks;
  255.             up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
  256.             up++)
  257.        {
  258.          int keep=png_handle_as_unknown(png_ptr, up->name);
  259.          if (keep != PNG_HANDLE_CHUNK_NEVER &&
  260.             up->location && (up->location & PNG_HAVE_PLTE) &&
  261.             !(up->location & PNG_HAVE_IDAT) &&
  262.             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
  263.             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
  264.          {
  265.             png_write_chunk(png_ptr, up->name, up->data, up->size);
  266.          }
  267.        }
  268.    }
  269. #endif
  270. }
  271. /* Writes the end of the PNG file.  If you don't want to write comments or
  272.  * time information, you can pass NULL for info.  If you already wrote these
  273.  * in png_write_info(), do not write them again here.  If you have long
  274.  * comments, I suggest writing them here, and compressing them.
  275.  */
  276. void PNGAPI
  277. png_write_end(png_structp png_ptr, png_infop info_ptr)
  278. {
  279.    png_debug(1, "in png_write_endn");
  280.    if (!(png_ptr->mode & PNG_HAVE_IDAT))
  281.       png_error(png_ptr, "No IDATs written into file");
  282.    /* see if user wants us to write information chunks */
  283.    if (info_ptr != NULL)
  284.    {
  285. #if defined(PNG_WRITE_TEXT_SUPPORTED)
  286.       int i; /* local index variable */
  287. #endif
  288. #if defined(PNG_WRITE_tIME_SUPPORTED)
  289.       /* check to see if user has supplied a time chunk */
  290.       if ((info_ptr->valid & PNG_INFO_tIME) &&
  291.          !(png_ptr->mode & PNG_WROTE_tIME))
  292.          png_write_tIME(png_ptr, &(info_ptr->mod_time));
  293. #endif
  294. #if defined(PNG_WRITE_TEXT_SUPPORTED)
  295.       /* loop through comment chunks */
  296.       for (i = 0; i < info_ptr->num_text; i++)
  297.       {
  298.          png_debug2(2, "Writing trailer text chunk %d, type %dn", i,
  299.             info_ptr->text[i].compression);
  300.          /* an internationalized chunk? */
  301.          if (info_ptr->text[i].compression > 0)
  302.          {
  303. #if defined(PNG_WRITE_iTXt_SUPPORTED)
  304.              /* write international chunk */
  305.              png_write_iTXt(png_ptr,
  306.                          info_ptr->text[i].compression,
  307.                          info_ptr->text[i].key,
  308.                          info_ptr->text[i].lang,
  309.                          info_ptr->text[i].lang_key,
  310.                          info_ptr->text[i].text);
  311. #else
  312.              png_warning(png_ptr, "Unable to write international textn");
  313. #endif
  314.              /* Mark this chunk as written */
  315.              info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
  316.          }
  317.          else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
  318.          {
  319. #if defined(PNG_WRITE_zTXt_SUPPORTED)
  320.             /* write compressed chunk */
  321.             png_write_zTXt(png_ptr, info_ptr->text[i].key,
  322.                info_ptr->text[i].text, 0,
  323.                info_ptr->text[i].compression);
  324. #else
  325.             png_warning(png_ptr, "Unable to write compressed textn");
  326. #endif
  327.             /* Mark this chunk as written */
  328.             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
  329.          }
  330.          else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
  331.          {
  332. #if defined(PNG_WRITE_tEXt_SUPPORTED)
  333.             /* write uncompressed chunk */
  334.             png_write_tEXt(png_ptr, info_ptr->text[i].key,
  335.                info_ptr->text[i].text, 0);
  336. #else
  337.             png_warning(png_ptr, "Unable to write uncompressed textn");
  338. #endif
  339.             /* Mark this chunk as written */
  340.             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
  341.          }
  342.       }
  343. #endif
  344. #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
  345.    if (info_ptr->unknown_chunks_num)
  346.    {
  347.        png_unknown_chunk *up;
  348.        png_debug(5, "writing extra chunksn");
  349.        for (up = info_ptr->unknown_chunks;
  350.             up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
  351.             up++)
  352.        {
  353.          int keep=png_handle_as_unknown(png_ptr, up->name);
  354.          if (keep != PNG_HANDLE_CHUNK_NEVER &&
  355.             up->location && (up->location & PNG_AFTER_IDAT) &&
  356.             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
  357.             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
  358.          {
  359.             png_write_chunk(png_ptr, up->name, up->data, up->size);
  360.          }
  361.        }
  362.    }
  363. #endif
  364.    }
  365.    png_ptr->mode |= PNG_AFTER_IDAT;
  366.    /* write end of PNG file */
  367.    png_write_IEND(png_ptr);
  368. #if 0
  369. /* This flush, added in libpng-1.0.8,  causes some applications to crash
  370.    because they do not set png_ptr->output_flush_fn */
  371.    png_flush(png_ptr);
  372. #endif
  373. }
  374. #if defined(PNG_WRITE_tIME_SUPPORTED)
  375. #if !defined(_WIN32_WCE)
  376. /* "time.h" functions are not supported on WindowsCE */
  377. void PNGAPI
  378. png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
  379. {
  380.    png_debug(1, "in png_convert_from_struct_tmn");
  381.    ptime->year = (png_uint_16)(1900 + ttime->tm_year);
  382.    ptime->month = (png_byte)(ttime->tm_mon + 1);
  383.    ptime->day = (png_byte)ttime->tm_mday;
  384.    ptime->hour = (png_byte)ttime->tm_hour;
  385.    ptime->minute = (png_byte)ttime->tm_min;
  386.    ptime->second = (png_byte)ttime->tm_sec;
  387. }
  388. void PNGAPI
  389. png_convert_from_time_t(png_timep ptime, time_t ttime)
  390. {
  391.    struct tm *tbuf;
  392.    png_debug(1, "in png_convert_from_time_tn");
  393.    tbuf = gmtime(&ttime);
  394.    png_convert_from_struct_tm(ptime, tbuf);
  395. }
  396. #endif
  397. #endif
  398. /* Initialize png_ptr structure, and allocate any memory needed */
  399. png_structp PNGAPI
  400. png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr,
  401.    png_error_ptr error_fn, png_error_ptr warn_fn)
  402. {
  403. #ifdef PNG_USER_MEM_SUPPORTED
  404.    return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
  405.       warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL));
  406. }
  407. /* Alternate initialize png_ptr structure, and allocate any memory needed */
  408. png_structp PNGAPI
  409. png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
  410.    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
  411.    png_malloc_ptr malloc_fn, png_free_ptr free_fn)
  412. {
  413. #endif /* PNG_USER_MEM_SUPPORTED */
  414.    png_structp png_ptr;
  415. #ifdef PNG_SETJMP_SUPPORTED
  416. #ifdef USE_FAR_KEYWORD
  417.    jmp_buf jmpbuf;
  418. #endif
  419. #endif
  420.    int i;
  421.    png_debug(1, "in png_create_write_structn");
  422. #ifdef PNG_USER_MEM_SUPPORTED
  423.    png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
  424.       (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
  425. #else
  426.    png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
  427. #endif /* PNG_USER_MEM_SUPPORTED */
  428.    if (png_ptr == NULL)
  429.       return (NULL);
  430. #if !defined(PNG_1_0_X)
  431. #ifdef PNG_ASSEMBLER_CODE_SUPPORTED
  432.    png_init_mmx_flags(png_ptr);   /* 1.2.0 addition */
  433. #endif
  434. #endif /* PNG_1_0_X */
  435.    /* added at libpng-1.2.6 */
  436. #ifdef PNG_SET_USER_LIMITS_SUPPORTED
  437.    png_ptr->user_width_max=PNG_USER_WIDTH_MAX;
  438.    png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;
  439. #endif
  440. #ifdef PNG_SETJMP_SUPPORTED
  441. #ifdef USE_FAR_KEYWORD
  442.    if (setjmp(jmpbuf))
  443. #else
  444.    if (setjmp(png_ptr->jmpbuf))
  445. #endif
  446.    {
  447.       png_free(png_ptr, png_ptr->zbuf);
  448.       png_ptr->zbuf=NULL;
  449.       png_destroy_struct(png_ptr);
  450.       return (NULL);
  451.    }
  452. #ifdef USE_FAR_KEYWORD
  453.    png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf));
  454. #endif
  455. #endif
  456. #ifdef PNG_USER_MEM_SUPPORTED
  457.    png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
  458. #endif /* PNG_USER_MEM_SUPPORTED */
  459.    png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
  460.    i=0;
  461.    do
  462.    {
  463.      if(user_png_ver[i] != png_libpng_ver[i])
  464.         png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
  465.    } while (png_libpng_ver[i++]);
  466.    if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
  467.    {
  468.      /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
  469.       * we must recompile any applications that use any older library version.
  470.       * For versions after libpng 1.0, we will be compatible, so we need
  471.       * only check the first digit.
  472.       */
  473.      if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
  474.          (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
  475.          (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
  476.      {
  477. #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
  478.         char msg[80];
  479.         if (user_png_ver)
  480.         {
  481.           sprintf(msg, "Application was compiled with png.h from libpng-%.20s",
  482.              user_png_ver);
  483.           png_warning(png_ptr, msg);
  484.         }
  485.         sprintf(msg, "Application  is  running with png.c from libpng-%.20s",
  486.            png_libpng_ver);
  487.         png_warning(png_ptr, msg);
  488. #endif
  489. #ifdef PNG_ERROR_NUMBERS_SUPPORTED
  490.         png_ptr->flags=0;
  491. #endif
  492.         png_error(png_ptr,
  493.            "Incompatible libpng version in application and library");
  494.      }
  495.    }
  496.    /* initialize zbuf - compression buffer */
  497.    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
  498.    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
  499.       (png_uint_32)png_ptr->zbuf_size);
  500.    png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL,
  501.       png_flush_ptr_NULL);
  502. #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  503.    png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
  504.       1, png_doublep_NULL, png_doublep_NULL);
  505. #endif
  506. #ifdef PNG_SETJMP_SUPPORTED
  507. /* Applications that neglect to set up their own setjmp() and then encounter
  508.    a png_error() will longjmp here.  Since the jmpbuf is then meaningless we
  509.    abort instead of returning. */
  510. #ifdef USE_FAR_KEYWORD
  511.    if (setjmp(jmpbuf))
  512.       PNG_ABORT();
  513.    png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf));
  514. #else
  515.    if (setjmp(png_ptr->jmpbuf))
  516.       PNG_ABORT();
  517. #endif
  518. #endif
  519.    return (png_ptr);
  520. }
  521. /* Initialize png_ptr structure, and allocate any memory needed */
  522. #undef png_write_init
  523. void PNGAPI
  524. png_write_init(png_structp png_ptr)
  525. {
  526.    /* We only come here via pre-1.0.7-compiled applications */
  527.    png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0);
  528. }
  529. void PNGAPI
  530. png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver,
  531.    png_size_t png_struct_size, png_size_t png_info_size)
  532. {
  533.    /* We only come here via pre-1.0.12-compiled applications */
  534. #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
  535.    if(png_sizeof(png_struct) > png_struct_size ||
  536.       png_sizeof(png_info) > png_info_size)
  537.    {
  538.       char msg[80];
  539.       png_ptr->warning_fn=NULL;
  540.       if (user_png_ver)
  541.       {
  542.         sprintf(msg, "Application was compiled with png.h from libpng-%.20s",
  543.            user_png_ver);
  544.         png_warning(png_ptr, msg);
  545.       }
  546.       sprintf(msg, "Application  is  running with png.c from libpng-%.20s",
  547.          png_libpng_ver);
  548.       png_warning(png_ptr, msg);
  549.    }
  550. #endif
  551.    if(png_sizeof(png_struct) > png_struct_size)
  552.      {
  553.        png_ptr->error_fn=NULL;
  554. #ifdef PNG_ERROR_NUMBERS_SUPPORTED
  555.        png_ptr->flags=0;
  556. #endif
  557.        png_error(png_ptr,
  558.        "The png struct allocated by the application for writing is too small.");
  559.      }
  560.    if(png_sizeof(png_info) > png_info_size)
  561.      {
  562.        png_ptr->error_fn=NULL;
  563. #ifdef PNG_ERROR_NUMBERS_SUPPORTED
  564.        png_ptr->flags=0;
  565. #endif
  566.        png_error(png_ptr,
  567.        "The info struct allocated by the application for writing is too small.");
  568.      }
  569.    png_write_init_3(&png_ptr, user_png_ver, png_struct_size);
  570. }
  571. void PNGAPI
  572. png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
  573.    png_size_t png_struct_size)
  574. {
  575.    png_structp png_ptr=*ptr_ptr;
  576. #ifdef PNG_SETJMP_SUPPORTED
  577.    jmp_buf tmp_jmp; /* to save current jump buffer */
  578. #endif
  579.    int i = 0;
  580.    do
  581.    {
  582.      if (user_png_ver[i] != png_libpng_ver[i])
  583.      {
  584. #ifdef PNG_LEGACY_SUPPORTED
  585.        png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
  586. #else
  587.        png_ptr->warning_fn=NULL;
  588.        png_warning(png_ptr,
  589.      "Application uses deprecated png_write_init() and should be recompiled.");
  590.        break;
  591. #endif
  592.      }
  593.    } while (png_libpng_ver[i++]);
  594.    png_debug(1, "in png_write_init_3n");
  595. #ifdef PNG_SETJMP_SUPPORTED
  596.    /* save jump buffer and error functions */
  597.    png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf));
  598. #endif
  599.    if (png_sizeof(png_struct) > png_struct_size)
  600.      {
  601.        png_destroy_struct(png_ptr);
  602.        png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
  603.        *ptr_ptr = png_ptr;
  604.      }
  605.    /* reset all variables to 0 */
  606.    png_memset(png_ptr, 0, png_sizeof (png_struct));
  607.    /* added at libpng-1.2.6 */
  608. #ifdef PNG_SET_USER_LIMITS_SUPPORTED
  609.    png_ptr->user_width_max=PNG_USER_WIDTH_MAX;
  610.    png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;
  611. #endif
  612. #if !defined(PNG_1_0_X)
  613. #ifdef PNG_ASSEMBLER_CODE_SUPPORTED
  614.    png_init_mmx_flags(png_ptr);   /* 1.2.0 addition */
  615. #endif
  616. #endif /* PNG_1_0_X */
  617. #ifdef PNG_SETJMP_SUPPORTED
  618.    /* restore jump buffer */
  619.    png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf));
  620. #endif
  621.    png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL,
  622.       png_flush_ptr_NULL);
  623.    /* initialize zbuf - compression buffer */
  624.    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
  625.    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
  626.       (png_uint_32)png_ptr->zbuf_size);
  627. #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  628.    png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
  629.       1, png_doublep_NULL, png_doublep_NULL);
  630. #endif
  631. }
  632. /* Write a few rows of image data.  If the image is interlaced,
  633.  * either you will have to write the 7 sub images, or, if you
  634.  * have called png_set_interlace_handling(), you will have to
  635.  * "write" the image seven times.
  636.  */
  637. void PNGAPI
  638. png_write_rows(png_structp png_ptr, png_bytepp row,
  639.    png_uint_32 num_rows)
  640. {
  641.    png_uint_32 i; /* row counter */
  642.    png_bytepp rp; /* row pointer */
  643.    png_debug(1, "in png_write_rowsn");
  644.    /* loop through the rows */
  645.    for (i = 0, rp = row; i < num_rows; i++, rp++)
  646.    {
  647.       png_write_row(png_ptr, *rp);
  648.    }
  649. }
  650. /* Write the image.  You only need to call this function once, even
  651.  * if you are writing an interlaced image.
  652.  */
  653. void PNGAPI
  654. png_write_image(png_structp png_ptr, png_bytepp image)
  655. {
  656.    png_uint_32 i; /* row index */
  657.    int pass, num_pass; /* pass variables */
  658.    png_bytepp rp; /* points to current row */
  659.    png_debug(1, "in png_write_imagen");
  660. #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
  661.    /* intialize interlace handling.  If image is not interlaced,
  662.       this will set pass to 1 */
  663.    num_pass = png_set_interlace_handling(png_ptr);
  664. #else
  665.    num_pass = 1;
  666. #endif
  667.    /* loop through passes */
  668.    for (pass = 0; pass < num_pass; pass++)
  669.    {
  670.       /* loop through image */
  671.       for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
  672.       {
  673.          png_write_row(png_ptr, *rp);
  674.       }
  675.    }
  676. }
  677. /* called by user to write a row of image data */
  678. void PNGAPI
  679. png_write_row(png_structp png_ptr, png_bytep row)
  680. {
  681.    png_debug2(1, "in png_write_row (row %ld, pass %d)n",
  682.       png_ptr->row_number, png_ptr->pass);
  683.    /* initialize transformations and other stuff if first time */
  684.    if (png_ptr->row_number == 0 && png_ptr->pass == 0)
  685.    {
  686.    /* make sure we wrote the header info */
  687.    if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
  688.       png_error(png_ptr,
  689.          "png_write_info was never called before png_write_row.");
  690.    /* check for transforms that have been set but were defined out */
  691. #if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
  692.    if (png_ptr->transformations & PNG_INVERT_MONO)
  693.       png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined.");
  694. #endif
  695. #if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
  696.    if (png_ptr->transformations & PNG_FILLER)
  697.       png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined.");
  698. #endif
  699. #if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED)
  700.    if (png_ptr->transformations & PNG_PACKSWAP)
  701.       png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined.");
  702. #endif
  703. #if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
  704.    if (png_ptr->transformations & PNG_PACK)
  705.       png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined.");
  706. #endif
  707. #if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
  708.    if (png_ptr->transformations & PNG_SHIFT)
  709.       png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined.");
  710. #endif
  711. #if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
  712.    if (png_ptr->transformations & PNG_BGR)
  713.       png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined.");
  714. #endif
  715. #if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
  716.    if (png_ptr->transformations & PNG_SWAP_BYTES)
  717.       png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined.");
  718. #endif
  719.       png_write_start_row(png_ptr);
  720.    }
  721. #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
  722.    /* if interlaced and not interested in row, return */
  723.    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
  724.    {
  725.       switch (png_ptr->pass)
  726.       {
  727.          case 0:
  728.             if (png_ptr->row_number & 0x07)
  729.             {
  730.                png_write_finish_row(png_ptr);
  731.                return;
  732.             }
  733.             break;
  734.          case 1:
  735.             if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
  736.             {
  737.                png_write_finish_row(png_ptr);
  738.                return;
  739.             }
  740.             break;
  741.          case 2:
  742.             if ((png_ptr->row_number & 0x07) != 4)
  743.             {
  744.                png_write_finish_row(png_ptr);
  745.                return;
  746.             }
  747.             break;
  748.          case 3:
  749.             if ((png_ptr->row_number & 0x03) || png_ptr->width < 3)
  750.             {
  751.                png_write_finish_row(png_ptr);
  752.                return;
  753.             }
  754.             break;
  755.          case 4:
  756.             if ((png_ptr->row_number & 0x03) != 2)
  757.             {
  758.                png_write_finish_row(png_ptr);
  759.                return;
  760.             }
  761.             break;
  762.          case 5:
  763.             if ((png_ptr->row_number & 0x01) || png_ptr->width < 2)
  764.             {
  765.                png_write_finish_row(png_ptr);
  766.                return;
  767.             }
  768.             break;
  769.          case 6:
  770.             if (!(png_ptr->row_number & 0x01))
  771.             {
  772.                png_write_finish_row(png_ptr);
  773.                return;
  774.             }
  775.             break;
  776.       }
  777.    }
  778. #endif
  779.    /* set up row info for transformations */
  780.    png_ptr->row_info.color_type = png_ptr->color_type;
  781.    png_ptr->row_info.width = png_ptr->usr_width;
  782.    png_ptr->row_info.channels = png_ptr->usr_channels;
  783.    png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
  784.    png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
  785.       png_ptr->row_info.channels);
  786.    png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
  787.       png_ptr->row_info.width);
  788.    png_debug1(3, "row_info->color_type = %dn", png_ptr->row_info.color_type);
  789.    png_debug1(3, "row_info->width = %lun", png_ptr->row_info.width);
  790.    png_debug1(3, "row_info->channels = %dn", png_ptr->row_info.channels);
  791.    png_debug1(3, "row_info->bit_depth = %dn", png_ptr->row_info.bit_depth);
  792.    png_debug1(3, "row_info->pixel_depth = %dn", png_ptr->row_info.pixel_depth);
  793.    png_debug1(3, "row_info->rowbytes = %lun", png_ptr->row_info.rowbytes);
  794.    /* Copy user's row into buffer, leaving room for filter byte. */
  795.    png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row,
  796.       png_ptr->row_info.rowbytes);
  797. #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
  798.    /* handle interlacing */
  799.    if (png_ptr->interlaced && png_ptr->pass < 6 &&
  800.       (png_ptr->transformations & PNG_INTERLACE))
  801.    {
  802.       png_do_write_interlace(&(png_ptr->row_info),
  803.          png_ptr->row_buf + 1, png_ptr->pass);
  804.       /* this should always get caught above, but still ... */
  805.       if (!(png_ptr->row_info.width))
  806.       {
  807.          png_write_finish_row(png_ptr);
  808.          return;
  809.       }
  810.    }
  811. #endif
  812.    /* handle other transformations */
  813.    if (png_ptr->transformations)
  814.       png_do_write_transformations(png_ptr);
  815. #if defined(PNG_MNG_FEATURES_SUPPORTED)
  816.    /* Write filter_method 64 (intrapixel differencing) only if
  817.     * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
  818.     * 2. Libpng did not write a PNG signature (this filter_method is only
  819.     *    used in PNG datastreams that are embedded in MNG datastreams) and
  820.     * 3. The application called png_permit_mng_features with a mask that
  821.     *    included PNG_FLAG_MNG_FILTER_64 and
  822.     * 4. The filter_method is 64 and
  823.     * 5. The color_type is RGB or RGBA
  824.     */
  825.    if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
  826.       (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
  827.    {
  828.       /* Intrapixel differencing */
  829.       png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1);
  830.    }
  831. #endif
  832.    /* Find a filter if necessary, filter the row and write it out. */
  833.    png_write_find_filter(png_ptr, &(png_ptr->row_info));
  834.    if (png_ptr->write_row_fn != NULL)
  835.       (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
  836. }
  837. #if defined(PNG_WRITE_FLUSH_SUPPORTED)
  838. /* Set the automatic flush interval or 0 to turn flushing off */
  839. void PNGAPI
  840. png_set_flush(png_structp png_ptr, int nrows)
  841. {
  842.    png_debug(1, "in png_set_flushn");
  843.    png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
  844. }
  845. /* flush the current output buffers now */
  846. void PNGAPI
  847. png_write_flush(png_structp png_ptr)
  848. {
  849.    int wrote_IDAT;
  850.    png_debug(1, "in png_write_flushn");
  851.    /* We have already written out all of the data */
  852.    if (png_ptr->row_number >= png_ptr->num_rows)
  853.      return;
  854.    do
  855.    {
  856.       int ret;
  857.       /* compress the data */
  858.       ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH);
  859.       wrote_IDAT = 0;
  860.       /* check for compression errors */
  861.       if (ret != Z_OK)
  862.       {
  863.          if (png_ptr->zstream.msg != NULL)
  864.             png_error(png_ptr, png_ptr->zstream.msg);
  865.          else
  866.             png_error(png_ptr, "zlib error");
  867.       }
  868.       if (!(png_ptr->zstream.avail_out))
  869.       {
  870.          /* write the IDAT and reset the zlib output buffer */
  871.          png_write_IDAT(png_ptr, png_ptr->zbuf,
  872.                         png_ptr->zbuf_size);
  873.          png_ptr->zstream.next_out = png_ptr->zbuf;
  874.          png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  875.          wrote_IDAT = 1;
  876.       }
  877.    } while(wrote_IDAT == 1);
  878.    /* If there is any data left to be output, write it into a new IDAT */
  879.    if (png_ptr->zbuf_size != png_ptr->zstream.avail_out)
  880.    {
  881.       /* write the IDAT and reset the zlib output buffer */
  882.       png_write_IDAT(png_ptr, png_ptr->zbuf,
  883.                      png_ptr->zbuf_size - png_ptr->zstream.avail_out);
  884.       png_ptr->zstream.next_out = png_ptr->zbuf;
  885.       png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  886.    }
  887.    png_ptr->flush_rows = 0;
  888.    png_flush(png_ptr);
  889. }
  890. #endif /* PNG_WRITE_FLUSH_SUPPORTED */
  891. /* free all memory used by the write */
  892. void PNGAPI
  893. png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
  894. {
  895.    png_structp png_ptr = NULL;
  896.    png_infop info_ptr = NULL;
  897. #ifdef PNG_USER_MEM_SUPPORTED
  898.    png_free_ptr free_fn = NULL;
  899.    png_voidp mem_ptr = NULL;
  900. #endif
  901.    png_debug(1, "in png_destroy_write_structn");
  902.    if (png_ptr_ptr != NULL)
  903.    {
  904.       png_ptr = *png_ptr_ptr;
  905. #ifdef PNG_USER_MEM_SUPPORTED
  906.       free_fn = png_ptr->free_fn;
  907.       mem_ptr = png_ptr->mem_ptr;
  908. #endif
  909.    }
  910.    if (info_ptr_ptr != NULL)
  911.       info_ptr = *info_ptr_ptr;
  912.    if (info_ptr != NULL)
  913.    {
  914.       png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
  915. #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
  916.       if (png_ptr->num_chunk_list)
  917.       {
  918.          png_free(png_ptr, png_ptr->chunk_list);
  919.          png_ptr->chunk_list=NULL;
  920.          png_ptr->num_chunk_list=0;
  921.       }
  922. #endif
  923. #ifdef PNG_USER_MEM_SUPPORTED
  924.       png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
  925.          (png_voidp)mem_ptr);
  926. #else
  927.       png_destroy_struct((png_voidp)info_ptr);
  928. #endif
  929.       *info_ptr_ptr = NULL;
  930.    }
  931.    if (png_ptr != NULL)
  932.    {
  933.       png_write_destroy(png_ptr);
  934. #ifdef PNG_USER_MEM_SUPPORTED
  935.       png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
  936.          (png_voidp)mem_ptr);
  937. #else
  938.       png_destroy_struct((png_voidp)png_ptr);
  939. #endif
  940.       *png_ptr_ptr = NULL;
  941.    }
  942. }
  943. /* Free any memory used in png_ptr struct (old method) */
  944. void /* PRIVATE */
  945. png_write_destroy(png_structp png_ptr)
  946. {
  947. #ifdef PNG_SETJMP_SUPPORTED
  948.    jmp_buf tmp_jmp; /* save jump buffer */
  949. #endif
  950.    png_error_ptr error_fn;
  951.    png_error_ptr warning_fn;
  952.    png_voidp error_ptr;
  953. #ifdef PNG_USER_MEM_SUPPORTED
  954.    png_free_ptr free_fn;
  955. #endif
  956.    png_debug(1, "in png_write_destroyn");
  957.    /* free any memory zlib uses */
  958.    deflateEnd(&png_ptr->zstream);
  959.    /* free our memory.  png_free checks NULL for us. */
  960.    png_free(png_ptr, png_ptr->zbuf);
  961.    png_free(png_ptr, png_ptr->row_buf);
  962.    png_free(png_ptr, png_ptr->prev_row);
  963.    png_free(png_ptr, png_ptr->sub_row);
  964.    png_free(png_ptr, png_ptr->up_row);
  965.    png_free(png_ptr, png_ptr->avg_row);
  966.    png_free(png_ptr, png_ptr->paeth_row);
  967. #if defined(PNG_TIME_RFC1123_SUPPORTED)
  968.    png_free(png_ptr, png_ptr->time_buffer);
  969. #endif
  970. #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  971.    png_free(png_ptr, png_ptr->prev_filters);
  972.    png_free(png_ptr, png_ptr->filter_weights);
  973.    png_free(png_ptr, png_ptr->inv_filter_weights);
  974.    png_free(png_ptr, png_ptr->filter_costs);
  975.    png_free(png_ptr, png_ptr->inv_filter_costs);
  976. #endif
  977. #ifdef PNG_SETJMP_SUPPORTED
  978.    /* reset structure */
  979.    png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf));
  980. #endif
  981.    error_fn = png_ptr->error_fn;
  982.    warning_fn = png_ptr->warning_fn;
  983.    error_ptr = png_ptr->error_ptr;
  984. #ifdef PNG_USER_MEM_SUPPORTED
  985.    free_fn = png_ptr->free_fn;
  986. #endif
  987.    png_memset(png_ptr, 0, png_sizeof (png_struct));
  988.    png_ptr->error_fn = error_fn;
  989.    png_ptr->warning_fn = warning_fn;
  990.    png_ptr->error_ptr = error_ptr;
  991. #ifdef PNG_USER_MEM_SUPPORTED
  992.    png_ptr->free_fn = free_fn;
  993. #endif
  994. #ifdef PNG_SETJMP_SUPPORTED
  995.    png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf));
  996. #endif
  997. }
  998. /* Allow the application to select one or more row filters to use. */
  999. void PNGAPI
  1000. png_set_filter(png_structp png_ptr, int method, int filters)
  1001. {
  1002.    png_debug(1, "in png_set_filtern");
  1003. #if defined(PNG_MNG_FEATURES_SUPPORTED)
  1004.    if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
  1005.       (method == PNG_INTRAPIXEL_DIFFERENCING))
  1006.          method = PNG_FILTER_TYPE_BASE;
  1007. #endif
  1008.    if (method == PNG_FILTER_TYPE_BASE)
  1009.    {
  1010.       switch (filters & (PNG_ALL_FILTERS | 0x07))
  1011.       {
  1012.          case 5:
  1013.          case 6:
  1014.          case 7: png_warning(png_ptr, "Unknown row filter for method 0");
  1015.          case PNG_FILTER_VALUE_NONE:  png_ptr->do_filter=PNG_FILTER_NONE; break;
  1016.          case PNG_FILTER_VALUE_SUB:   png_ptr->do_filter=PNG_FILTER_SUB;  break;
  1017.          case PNG_FILTER_VALUE_UP:    png_ptr->do_filter=PNG_FILTER_UP;   break;
  1018.          case PNG_FILTER_VALUE_AVG:   png_ptr->do_filter=PNG_FILTER_AVG;  break;
  1019.          case PNG_FILTER_VALUE_PAETH: png_ptr->do_filter=PNG_FILTER_PAETH;break;
  1020.          default: png_ptr->do_filter = (png_byte)filters; break;
  1021.       }
  1022.       /* If we have allocated the row_buf, this means we have already started
  1023.        * with the image and we should have allocated all of the filter buffers
  1024.        * that have been selected.  If prev_row isn't already allocated, then
  1025.        * it is too late to start using the filters that need it, since we
  1026.        * will be missing the data in the previous row.  If an application
  1027.        * wants to start and stop using particular filters during compression,
  1028.        * it should start out with all of the filters, and then add and
  1029.        * remove them after the start of compression.
  1030.        */
  1031.       if (png_ptr->row_buf != NULL)
  1032.       {
  1033.          if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL)
  1034.          {
  1035.             png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
  1036.               (png_ptr->rowbytes + 1));
  1037.             png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
  1038.          }
  1039.          if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL)
  1040.          {
  1041.             if (png_ptr->prev_row == NULL)
  1042.             {
  1043.                png_warning(png_ptr, "Can't add Up filter after starting");
  1044.                png_ptr->do_filter &= ~PNG_FILTER_UP;
  1045.             }
  1046.             else
  1047.             {
  1048.                png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
  1049.                   (png_ptr->rowbytes + 1));
  1050.                png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
  1051.             }
  1052.          }
  1053.          if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL)
  1054.          {
  1055.             if (png_ptr->prev_row == NULL)
  1056.             {
  1057.                png_warning(png_ptr, "Can't add Average filter after starting");
  1058.                png_ptr->do_filter &= ~PNG_FILTER_AVG;
  1059.             }
  1060.             else
  1061.             {
  1062.                png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
  1063.                   (png_ptr->rowbytes + 1));
  1064.                png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
  1065.             }
  1066.          }
  1067.          if ((png_ptr->do_filter & PNG_FILTER_PAETH) &&
  1068.              png_ptr->paeth_row == NULL)
  1069.          {
  1070.             if (png_ptr->prev_row == NULL)
  1071.             {
  1072.                png_warning(png_ptr, "Can't add Paeth filter after starting");
  1073.                png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH);
  1074.             }
  1075.             else
  1076.             {
  1077.                png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
  1078.                   (png_ptr->rowbytes + 1));
  1079.                png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
  1080.             }
  1081.          }
  1082.          if (png_ptr->do_filter == PNG_NO_FILTERS)
  1083.             png_ptr->do_filter = PNG_FILTER_NONE;
  1084.       }
  1085.    }
  1086.    else
  1087.       png_error(png_ptr, "Unknown custom filter method");
  1088. }
  1089. /* This allows us to influence the way in which libpng chooses the "best"
  1090.  * filter for the current scanline.  While the "minimum-sum-of-absolute-
  1091.  * differences metric is relatively fast and effective, there is some
  1092.  * question as to whether it can be improved upon by trying to keep the
  1093.  * filtered data going to zlib more consistent, hopefully resulting in
  1094.  * better compression.
  1095.  */
  1096. #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)      /* GRR 970116 */
  1097. void PNGAPI
  1098. png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
  1099.    int num_weights, png_doublep filter_weights,
  1100.    png_doublep filter_costs)
  1101. {
  1102.    int i;
  1103.    png_debug(1, "in png_set_filter_heuristicsn");
  1104.    if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)
  1105.    {
  1106.       png_warning(png_ptr, "Unknown filter heuristic method");
  1107.       return;
  1108.    }
  1109.    if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT)
  1110.    {
  1111.       heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED;
  1112.    }
  1113.    if (num_weights < 0 || filter_weights == NULL ||
  1114.       heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED)
  1115.    {
  1116.       num_weights = 0;
  1117.    }
  1118.    png_ptr->num_prev_filters = (png_byte)num_weights;
  1119.    png_ptr->heuristic_method = (png_byte)heuristic_method;
  1120.    if (num_weights > 0)
  1121.    {
  1122.       if (png_ptr->prev_filters == NULL)
  1123.       {
  1124.          png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
  1125.             (png_uint_32)(png_sizeof(png_byte) * num_weights));
  1126.          /* To make sure that the weighting starts out fairly */
  1127.          for (i = 0; i < num_weights; i++)
  1128.          {
  1129.             png_ptr->prev_filters[i] = 255;
  1130.          }
  1131.       }
  1132.       if (png_ptr->filter_weights == NULL)
  1133.       {
  1134.          png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
  1135.             (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
  1136.          png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
  1137.             (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
  1138.          for (i = 0; i < num_weights; i++)
  1139.          {
  1140.             png_ptr->inv_filter_weights[i] =
  1141.             png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
  1142.          }
  1143.       }
  1144.       for (i = 0; i < num_weights; i++)
  1145.       {
  1146.          if (filter_weights[i] < 0.0)
  1147.          {
  1148.             png_ptr->inv_filter_weights[i] =
  1149.             png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
  1150.          }
  1151.          else
  1152.          {
  1153.             png_ptr->inv_filter_weights[i] =
  1154.                (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5);
  1155.             png_ptr->filter_weights[i] =
  1156.                (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5);
  1157.          }
  1158.       }
  1159.    }
  1160.    /* If, in the future, there are other filter methods, this would
  1161.     * need to be based on png_ptr->filter.
  1162.     */
  1163.    if (png_ptr->filter_costs == NULL)
  1164.    {
  1165.       png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
  1166.          (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
  1167.       png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
  1168.          (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
  1169.       for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
  1170.       {
  1171.          png_ptr->inv_filter_costs[i] =
  1172.          png_ptr->filter_costs[i] = PNG_COST_FACTOR;
  1173.       }
  1174.    }
  1175.    /* Here is where we set the relative costs of the different filters.  We
  1176.     * should take the desired compression level into account when setting
  1177.     * the costs, so that Paeth, for instance, has a high relative cost at low
  1178.     * compression levels, while it has a lower relative cost at higher
  1179.     * compression settings.  The filter types are in order of increasing
  1180.     * relative cost, so it would be possible to do this with an algorithm.
  1181.     */
  1182.    for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
  1183.    {
  1184.       if (filter_costs == NULL || filter_costs[i] < 0.0)
  1185.       {
  1186.          png_ptr->inv_filter_costs[i] =
  1187.          png_ptr->filter_costs[i] = PNG_COST_FACTOR;
  1188.       }
  1189.       else if (filter_costs[i] >= 1.0)
  1190.       {
  1191.          png_ptr->inv_filter_costs[i] =
  1192.             (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5);
  1193.          png_ptr->filter_costs[i] =
  1194.             (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5);
  1195.       }
  1196.    }
  1197. }
  1198. #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
  1199. void PNGAPI
  1200. png_set_compression_level(png_structp png_ptr, int level)
  1201. {
  1202.    png_debug(1, "in png_set_compression_leveln");
  1203.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
  1204.    png_ptr->zlib_level = level;
  1205. }
  1206. void PNGAPI
  1207. png_set_compression_mem_level(png_structp png_ptr, int mem_level)
  1208. {
  1209.    png_debug(1, "in png_set_compression_mem_leveln");
  1210.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
  1211.    png_ptr->zlib_mem_level = mem_level;
  1212. }
  1213. void PNGAPI
  1214. png_set_compression_strategy(png_structp png_ptr, int strategy)
  1215. {
  1216.    png_debug(1, "in png_set_compression_strategyn");
  1217.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
  1218.    png_ptr->zlib_strategy = strategy;
  1219. }
  1220. void PNGAPI
  1221. png_set_compression_window_bits(png_structp png_ptr, int window_bits)
  1222. {
  1223.    if (window_bits > 15)
  1224.       png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
  1225.    else if (window_bits < 8)
  1226.       png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
  1227. #ifndef WBITS_8_OK
  1228.    /* avoid libpng bug with 256-byte windows */
  1229.    if (window_bits == 8)
  1230.      {
  1231.        png_warning(png_ptr, "Compression window is being reset to 512");
  1232.        window_bits=9;
  1233.      }
  1234. #endif
  1235.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
  1236.    png_ptr->zlib_window_bits = window_bits;
  1237. }
  1238. void PNGAPI
  1239. png_set_compression_method(png_structp png_ptr, int method)
  1240. {
  1241.    png_debug(1, "in png_set_compression_methodn");
  1242.    if (method != 8)
  1243.       png_warning(png_ptr, "Only compression method 8 is supported by PNG");
  1244.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
  1245.    png_ptr->zlib_method = method;
  1246. }
  1247. void PNGAPI
  1248. png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn)
  1249. {
  1250.    png_ptr->write_row_fn = write_row_fn;
  1251. }
  1252. #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
  1253. void PNGAPI
  1254. png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
  1255.    write_user_transform_fn)
  1256. {
  1257.    png_debug(1, "in png_set_write_user_transform_fnn");
  1258.    png_ptr->transformations |= PNG_USER_TRANSFORM;
  1259.    png_ptr->write_user_transform_fn = write_user_transform_fn;
  1260. }
  1261. #endif
  1262. #if defined(PNG_INFO_IMAGE_SUPPORTED)
  1263. void PNGAPI
  1264. png_write_png(png_structp png_ptr, png_infop info_ptr,
  1265.               int transforms, voidp params)
  1266. {
  1267. #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
  1268.    /* invert the alpha channel from opacity to transparency */
  1269.    if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
  1270.        png_set_invert_alpha(png_ptr);
  1271. #endif
  1272.    /* Write the file header information. */
  1273.    png_write_info(png_ptr, info_ptr);
  1274.    /* ------ these transformations don't touch the info structure ------- */
  1275. #if defined(PNG_WRITE_INVERT_SUPPORTED)
  1276.    /* invert monochrome pixels */
  1277.    if (transforms & PNG_TRANSFORM_INVERT_MONO)
  1278.        png_set_invert_mono(png_ptr);
  1279. #endif
  1280. #if defined(PNG_WRITE_SHIFT_SUPPORTED)
  1281.    /* Shift the pixels up to a legal bit depth and fill in
  1282.     * as appropriate to correctly scale the image.
  1283.     */
  1284.    if ((transforms & PNG_TRANSFORM_SHIFT)
  1285.                && (info_ptr->valid & PNG_INFO_sBIT))
  1286.        png_set_shift(png_ptr, &info_ptr->sig_bit);
  1287. #endif
  1288. #if defined(PNG_WRITE_PACK_SUPPORTED)
  1289.    /* pack pixels into bytes */
  1290.    if (transforms & PNG_TRANSFORM_PACKING)
  1291.        png_set_packing(png_ptr);
  1292. #endif
  1293. #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
  1294.    /* swap location of alpha bytes from ARGB to RGBA */
  1295.    if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
  1296.        png_set_swap_alpha(png_ptr);
  1297. #endif
  1298. #if defined(PNG_WRITE_FILLER_SUPPORTED)
  1299.    /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
  1300.     * RGB (4 channels -> 3 channels). The second parameter is not used.
  1301.     */
  1302.    if (transforms & PNG_TRANSFORM_STRIP_FILLER)
  1303.        png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
  1304. #endif
  1305. #if defined(PNG_WRITE_BGR_SUPPORTED)
  1306.    /* flip BGR pixels to RGB */
  1307.    if (transforms & PNG_TRANSFORM_BGR)
  1308.        png_set_bgr(png_ptr);
  1309. #endif
  1310. #if defined(PNG_WRITE_SWAP_SUPPORTED)
  1311.    /* swap bytes of 16-bit files to most significant byte first */
  1312.    if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
  1313.        png_set_swap(png_ptr);
  1314. #endif
  1315. #if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
  1316.    /* swap bits of 1, 2, 4 bit packed pixel formats */
  1317.    if (transforms & PNG_TRANSFORM_PACKSWAP)
  1318.        png_set_packswap(png_ptr);
  1319. #endif
  1320.    /* ----------------------- end of transformations ------------------- */
  1321.    /* write the bits */
  1322.    if (info_ptr->valid & PNG_INFO_IDAT)
  1323.        png_write_image(png_ptr, info_ptr->row_pointers);
  1324.    /* It is REQUIRED to call this to finish writing the rest of the file */
  1325.    png_write_end(png_ptr, info_ptr);
  1326.    if(transforms == 0 || params == NULL)
  1327.       /* quiet compiler warnings */ return;
  1328. }
  1329. #endif
  1330. #endif /* PNG_WRITE_SUPPORTED */