pngwrite.c
Upload User: kairuinn
Upload Date: 2009-02-07
Package Size: 2922k
Code Size: 48k
Category:

Graph program

Development Platform:

Visual C++

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