PNGWRITE.C
上传用户:wep9318
上传日期:2007-01-07
资源大小:893k
文件大小:20k
源码类别:

图片显示

开发平台:

Visual C++

  1. /* pngwrite.c - general routines to write a png file
  2.    libpng 1.0 beta 3 - version 0.89
  3.    For conditions of distribution and use, see copyright notice in png.h
  4.    Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  5.    May 25, 1996
  6.    */
  7. /* get internal access to png.h */
  8. #define PNG_INTERNAL
  9. #include "png.h"
  10. /* Writes all the png information.  This is the suggested way to use
  11.    the library.  If you have a new chunk to add, make a function to
  12.    write it, and put it in the correct location here.  If you want
  13.    the chunk written after the image data, put it in png_write_end().
  14.    I strongly encurage you to supply a PNG_INFO_ flag, and check
  15.    info->valid before writing the chunk, as that will keep the code
  16.    from breaking if you want to just write a plain png file.
  17.    If you have long comments, I suggest writing them in png_write_end(),
  18.    and compressing them. */
  19. void
  20. png_write_info(png_structp png_ptr, png_infop info)
  21. {
  22.    png_write_sig(png_ptr); /* write PNG signature */
  23.    /* write IHDR information. */
  24.    png_write_IHDR(png_ptr, info->width, info->height, info->bit_depth,
  25.       info->color_type, info->compression_type, info->filter_type,
  26.       info->interlace_type);
  27.    /* the rest of these check to see if the valid field has the appropriate
  28.       flag set, and if it does, writes the chunk. */
  29. #if defined(PNG_WRITE_gAMA_SUPPORTED)
  30.    if (info->valid & PNG_INFO_gAMA)
  31.       png_write_gAMA(png_ptr, info->gamma);
  32. #endif
  33. #if defined(PNG_WRITE_sBIT_SUPPORTED)
  34.    if (info->valid & PNG_INFO_sBIT)
  35.       png_write_sBIT(png_ptr, &(info->sig_bit), info->color_type);
  36. #endif
  37. #if defined(PNG_WRITE_cHRM_SUPPORTED)
  38.    if (info->valid & PNG_INFO_cHRM)
  39.       png_write_cHRM(png_ptr,
  40.          info->x_white, info->y_white,
  41.          info->x_red, info->y_red,
  42.          info->x_green, info->y_green,
  43.          info->x_blue, info->y_blue);
  44. #endif
  45.    if (info->valid & PNG_INFO_PLTE)
  46.       png_write_PLTE(png_ptr, info->palette, info->num_palette);
  47.    else if (info->color_type == PNG_COLOR_TYPE_PALETTE)
  48.       png_error(png_ptr, "Valid palette required for paletted imagesn");
  49. #if defined(PNG_WRITE_tRNS_SUPPORTED)
  50.    if (info->valid & PNG_INFO_tRNS)
  51.       png_write_tRNS(png_ptr, info->trans, &(info->trans_values),
  52.          info->num_trans, info->color_type);
  53. #endif
  54. #if defined(PNG_WRITE_bKGD_SUPPORTED)
  55.    if (info->valid & PNG_INFO_bKGD)
  56.       png_write_bKGD(png_ptr, &(info->background), info->color_type);
  57. #endif
  58. #if defined(PNG_WRITE_hIST_SUPPORTED)
  59.    if (info->valid & PNG_INFO_hIST)
  60.       png_write_hIST(png_ptr, info->hist, info->num_palette);
  61. #endif
  62. #if defined(PNG_WRITE_pHYs_SUPPORTED)
  63.    if (info->valid & PNG_INFO_pHYs)
  64.       png_write_pHYs(png_ptr, info->x_pixels_per_unit,
  65.          info->y_pixels_per_unit, info->phys_unit_type);
  66. #endif
  67. #if defined(PNG_WRITE_oFFs_SUPPORTED)
  68.    if (info->valid & PNG_INFO_oFFs)
  69.       png_write_oFFs(png_ptr, info->x_offset, info->y_offset,
  70.          info->offset_unit_type);
  71. #endif
  72. #if defined(PNG_WRITE_tIME_SUPPORTED)
  73.    if (info->valid & PNG_INFO_tIME)
  74.    {
  75.       png_write_tIME(png_ptr, &(info->mod_time));
  76.       png_ptr->flags |= PNG_FLAG_WROTE_tIME;
  77.    }
  78. #endif
  79. #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
  80.    /* Check to see if we need to write text chunks */
  81.    if (info->num_text)
  82.    {
  83.       int i; /* local counter */
  84.       /* loop through the text chunks */
  85.       for (i = 0; i < info->num_text; i++)
  86.       {
  87.          /* if chunk is compressed */
  88.          if (info->text[i].compression >= 0)
  89.          {
  90. #if defined(PNG_WRITE_zTXt_SUPPORTED)
  91.             /* write compressed chunk */
  92.             png_write_zTXt(png_ptr, info->text[i].key,
  93.                info->text[i].text, info->text[i].text_length,
  94.                info->text[i].compression);
  95. #else
  96.             png_warning(png_ptr, "Unable to write compressed textn");
  97. #endif
  98.          }
  99.          else
  100.          {
  101. #if defined(PNG_WRITE_tEXt_SUPPORTED)
  102.             /* write uncompressed chunk */
  103.             png_write_tEXt(png_ptr, info->text[i].key,
  104.                info->text[i].text, info->text[i].text_length);
  105. #else
  106.             png_warning(png_ptr, "Unable to write uncompressed textn");
  107. #endif
  108.          }
  109.       }
  110.    }
  111. #endif
  112. }
  113. /* writes the end of the png file.  If you don't want to write comments or
  114.    time information, you can pass NULL for info.  If you already wrote these
  115.    in png_write_info(), do not write them again here.  If you have long
  116.    comments, I suggest writing them here, and compressing them. */
  117. void
  118. png_write_end(png_structp png_ptr, png_infop info)
  119. {
  120.    if (!(png_ptr->mode & PNG_HAVE_IDAT))
  121.       png_error(png_ptr, "No IDATs written into file");
  122.    /* see if user wants us to write information chunks */
  123.    if (info)
  124.    {
  125. #if defined(PNG_WRITE_tIME_SUPPORTED)
  126.       /* check to see if user has supplied a time chunk */
  127.       if (info->valid & PNG_INFO_tIME &&
  128.          !(png_ptr->flags & PNG_FLAG_WROTE_tIME))
  129.          png_write_tIME(png_ptr, &(info->mod_time));
  130. #endif
  131. #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
  132.       /* check to see if we need to write comment chunks */
  133.       if (info->num_text)
  134.       {
  135.          int i; /* local index variable */
  136.          /* loop through comment chunks */
  137.          for (i = 0; i < info->num_text; i++)
  138.          {
  139. #if defined(PNG_WRITE_zTXt_SUPPORTED)
  140.             /* check to see if comment is to be compressed */
  141.             if (info->text[i].compression >= 0)
  142.             {
  143.                /* write compressed chunk */
  144.                png_write_zTXt(png_ptr, info->text[i].key,
  145.                   info->text[i].text, info->text[i].text_length,
  146.                   info->text[i].compression);
  147.             }
  148. #if defined(PNG_WRITE_tEXt_SUPPORTED)
  149.             else
  150. #endif
  151. #endif
  152. #if defined(PNG_WRITE_tEXt_SUPPORTED)
  153.             {
  154.                /* write uncompressed chunk */
  155.                png_write_tEXt(png_ptr, info->text[i].key,
  156.                   info->text[i].text, info->text[i].text_length);
  157.             }
  158. #endif
  159.          }
  160.       }
  161. #endif
  162.    }
  163.    png_ptr->mode |= PNG_AFTER_IDAT;
  164.    /* write end of png file */
  165.    png_write_IEND(png_ptr);
  166. }
  167. #if defined(PNG_WRITE_tIME_SUPPORTED)
  168. void
  169. png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
  170. {
  171.    ptime->year = (png_uint_16)(1900 + ttime->tm_year);
  172.    ptime->month = (png_byte)(ttime->tm_mon + 1);
  173.    ptime->day = (png_byte)ttime->tm_mday;
  174.    ptime->hour = (png_byte)ttime->tm_hour;
  175.    ptime->minute = (png_byte)ttime->tm_min;
  176.    ptime->second = (png_byte)ttime->tm_sec;
  177. }
  178. void
  179. png_convert_from_time_t(png_timep ptime, time_t ttime)
  180. {
  181.    struct tm *tbuf;
  182.    tbuf = gmtime(&ttime);
  183.    png_convert_from_struct_tm(ptime, tbuf);
  184. }
  185. #endif
  186. /* initialize png structure, and allocate any memory needed */
  187. png_structp
  188. png_create_write_struct(png_const_charp user_png_ver, voidp error_ptr,
  189.    png_error_ptr warn_fn, png_error_ptr error_fn)
  190. {
  191.    png_structp png_ptr;
  192.    if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
  193.    {
  194.       return (png_structp)NULL;
  195.    }
  196.    if (setjmp(png_ptr->jmpbuf))
  197.    {
  198.       png_large_free(png_ptr, png_ptr->zbuf);
  199.       png_free(png_ptr, png_ptr->zstream);
  200.       png_destroy_struct(png_ptr);
  201.       return (png_structp)NULL;
  202.    }
  203.    png_set_error_fn(png_ptr, error_ptr, warn_fn, error_fn);
  204.    if (user_png_ver == NULL || strcmp(user_png_ver, png_libpng_ver))
  205.    {
  206.       if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0])
  207.       {
  208.          png_error(png_ptr, "Incompatible libpng versions");
  209.       }
  210.       else
  211.       {
  212.          png_warning(png_ptr, "Different libpng versions");
  213.       }
  214.    }
  215.    /* initialize zbuf - compression buffer */
  216.    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
  217.    png_ptr->zbuf = png_large_malloc(png_ptr, png_ptr->zbuf_size);
  218.    png_set_write_fn(png_ptr, NULL, NULL, NULL);
  219.    png_ptr->do_free |= PNG_FREE_STRUCT;
  220.    return (png_ptr);
  221. }
  222. /* initialize png structure, and allocate any memory needed */
  223. void
  224. png_write_init(png_structp png_ptr)
  225. {
  226.    jmp_buf tmp_jmp; /* to save current jump buffer */
  227.    /* save jump buffer and error functions */
  228.    png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
  229.    /* reset all variables to 0 */
  230.    png_memset(png_ptr, 0, sizeof (png_struct));
  231.    /* restore jump buffer */
  232.    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
  233.    /* initialize zbuf - compression buffer */
  234.    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
  235.    png_ptr->zbuf = png_large_malloc(png_ptr, png_ptr->zbuf_size);
  236.    png_set_write_fn(png_ptr, NULL, NULL, NULL);
  237. }
  238. /* write a few rows of image data.  If the image is interlaced,
  239.    either you will have to write the 7 sub images, or, if you
  240.    have called png_set_interlace_handling(), you will have to
  241.    "write" the image seven times */
  242. void
  243. png_write_rows(png_structp png_ptr, png_bytepp row,
  244.    png_uint_32 num_rows)
  245. {
  246.    png_uint_32 i; /* row counter */
  247.    png_bytepp rp; /* row pointer */
  248.    /* loop through the rows */
  249.    for (i = 0, rp = row; i < num_rows; i++, rp++)
  250.    {
  251.       png_write_row(png_ptr, *rp);
  252.    }
  253. }
  254. /* write the image.  You only need to call this function once, even
  255.    if you are writing an interlaced image. */
  256. void
  257. png_write_image(png_structp png_ptr, png_bytepp image)
  258. {
  259.    png_uint_32 i; /* row index */
  260.    int pass, num_pass; /* pass variables */
  261.    png_bytepp rp; /* points to current row */
  262.    /* intialize interlace handling.  If image is not interlaced,
  263.       this will set pass to 1 */
  264.    num_pass = png_set_interlace_handling(png_ptr);
  265.    /* loop through passes */
  266.    for (pass = 0; pass < num_pass; pass++)
  267.    {
  268.       /* loop through image */
  269.       for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
  270.       {
  271.          png_write_row(png_ptr, *rp);
  272.       }
  273.    }
  274. }
  275. /* called by user to write a row of image data */
  276. void
  277. png_write_row(png_structp png_ptr, png_bytep row)
  278. {
  279.    /* initialize transformations and other stuff if first time */
  280.    if (png_ptr->row_number == 0 && png_ptr->pass == 0)
  281.    {
  282.       png_write_start_row(png_ptr);
  283.    }
  284. #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
  285.    /* if interlaced and not interested in row, return */
  286.    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
  287.    {
  288.       switch (png_ptr->pass)
  289.       {
  290.          case 0:
  291.             if (png_ptr->row_number & 7)
  292.             {
  293.                png_write_finish_row(png_ptr);
  294.                return;
  295.             }
  296.             break;
  297.          case 1:
  298.             if ((png_ptr->row_number & 7) || png_ptr->width < 5)
  299.             {
  300.                png_write_finish_row(png_ptr);
  301.                return;
  302.             }
  303.             break;
  304.          case 2:
  305.             if ((png_ptr->row_number & 7) != 4)
  306.             {
  307.                png_write_finish_row(png_ptr);
  308.                return;
  309.             }
  310.             break;
  311.          case 3:
  312.             if ((png_ptr->row_number & 3) || png_ptr->width < 3)
  313.             {
  314.                png_write_finish_row(png_ptr);
  315.                return;
  316.             }
  317.             break;
  318.          case 4:
  319.             if ((png_ptr->row_number & 3) != 2)
  320.             {
  321.                png_write_finish_row(png_ptr);
  322.                return;
  323.             }
  324.             break;
  325.          case 5:
  326.             if ((png_ptr->row_number & 1) || png_ptr->width < 2)
  327.             {
  328.                png_write_finish_row(png_ptr);
  329.                return;
  330.             }
  331.             break;
  332.          case 6:
  333.             if (!(png_ptr->row_number & 1))
  334.             {
  335.                png_write_finish_row(png_ptr);
  336.                return;
  337.             }
  338.             break;
  339.       }
  340.    }
  341. #endif
  342.    /* set up row info for transformations */
  343.    png_ptr->row_info.color_type = png_ptr->color_type;
  344.    png_ptr->row_info.width = png_ptr->usr_width;
  345.    png_ptr->row_info.channels = png_ptr->usr_channels;
  346.    png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
  347.    png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
  348.       png_ptr->row_info.channels);
  349.    png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
  350.       (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
  351.    /* copy users row into buffer, leaving room for filter byte */
  352.    png_memcpy(png_ptr->row_buf + 1, row, (png_size_t)png_ptr->row_info.rowbytes);
  353. #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
  354.    /* handle interlacing */
  355.    if (png_ptr->interlaced && png_ptr->pass < 6 &&
  356.       (png_ptr->transformations & PNG_INTERLACE))
  357.    {
  358.       png_do_write_interlace(&(png_ptr->row_info),
  359.          png_ptr->row_buf + 1, png_ptr->pass);
  360.       /* this should always get caught above, but still ... */
  361.       if (!(png_ptr->row_info.width))
  362.       {
  363.          png_write_finish_row(png_ptr);
  364.          return;
  365.       }
  366.    }
  367. #endif
  368.    /* handle other transformations */
  369.    if (png_ptr->transformations)
  370.       png_do_write_transformations(png_ptr);
  371.    /* find a filter if necessary, filter the row and write it out */
  372.    png_write_find_filter(png_ptr, &(png_ptr->row_info));
  373. }
  374. #if defined(PNG_WRITE_FLUSH_SUPPORTED)
  375. /* Set the automatic flush interval or 0 to turn flushing off */
  376. void
  377. png_set_flush(png_structp png_ptr, int nrows)
  378. {
  379.    png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
  380. }
  381. /* flush the current output buffers now */
  382. void
  383. png_write_flush(png_structp png_ptr)
  384. {
  385.    int wrote_IDAT;
  386.    /* We have already written out all of the data */
  387.    if (png_ptr->row_number >= png_ptr->num_rows)
  388.      return;
  389.    do
  390.    {
  391.       int ret;
  392.       /* compress the data */
  393.       ret = deflate(png_ptr->zstream, Z_SYNC_FLUSH);
  394.       wrote_IDAT = 0;
  395.       /* check for compression errors */
  396.       if (ret != Z_OK)
  397.       {
  398.          if (png_ptr->zstream->msg)
  399.             png_error(png_ptr, png_ptr->zstream->msg);
  400.          else
  401.             png_error(png_ptr, "zlib error");
  402.       }
  403.       if (!png_ptr->zstream->avail_out)
  404.       {
  405.          /* write the IDAT and reset the zlib output buffer */
  406.          png_write_IDAT(png_ptr, png_ptr->zbuf,
  407.                         png_ptr->zbuf_size);
  408.          png_ptr->zstream->next_out = png_ptr->zbuf;
  409.          png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
  410.          wrote_IDAT = 1;
  411.       }
  412.    } while(wrote_IDAT == 1);
  413.    /* If there is any data left to be output, write it into a new IDAT */
  414.    if (png_ptr->zbuf_size != png_ptr->zstream->avail_out)
  415.    {
  416.       /* write the IDAT and reset the zlib output buffer */
  417.       png_write_IDAT(png_ptr, png_ptr->zbuf,
  418.                      png_ptr->zbuf_size - png_ptr->zstream->avail_out);
  419.       png_ptr->zstream->next_out = png_ptr->zbuf;
  420.       png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
  421.    }
  422.    png_ptr->flush_rows = 0;
  423.    png_flush(png_ptr);
  424. }
  425. #endif /* PNG_WRITE_FLUSH_SUPPORTED */
  426. /* free all memory used by the write */
  427. void
  428. png_destroy_write_struct(png_structpp png_ptr, png_infopp info_ptr)
  429. {
  430.    if (info_ptr && *info_ptr)
  431.    {
  432.       png_destroy_struct((voidp)*info_ptr);
  433.       *info_ptr = (png_infop)NULL;
  434.    }
  435.    if (png_ptr && *png_ptr)
  436.    {
  437.       png_write_destroy(*png_ptr);
  438.       png_destroy_struct((voidp)*png_ptr);
  439.       *png_ptr = (png_structp)NULL;
  440.    }
  441. }
  442. /* free any memory used in png struct (old) */
  443. void
  444. png_write_destroy(png_structp png_ptr)
  445. {
  446.    jmp_buf tmp_jmp; /* save jump buffer */
  447.    png_error_ptr error_fn;
  448.    png_error_ptr warning_fn;
  449.    png_voidp error_ptr;
  450.    /* free any memory zlib uses */
  451.    deflateEnd(png_ptr->zstream);
  452.    png_free(png_ptr, png_ptr->zstream);
  453.    /* free our memory.  png_free checks NULL for us. */
  454.    png_large_free(png_ptr, png_ptr->zbuf);
  455.    png_large_free(png_ptr, png_ptr->row_buf);
  456.    png_large_free(png_ptr, png_ptr->prev_row);
  457.    png_large_free(png_ptr, png_ptr->sub_row);
  458.    png_large_free(png_ptr, png_ptr->up_row);
  459.    png_large_free(png_ptr, png_ptr->avg_row);
  460.    png_large_free(png_ptr, png_ptr->paeth_row);
  461.    /* reset structure */
  462.    png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
  463.    error_fn = png_ptr->error_fn;
  464.    warning_fn = png_ptr->warning_fn;
  465.    error_ptr = png_ptr->error_ptr;
  466.    png_memset(png_ptr, 0, sizeof (png_struct));
  467.    png_ptr->error_fn = error_fn;
  468.    png_ptr->warning_fn = warning_fn;
  469.    png_ptr->error_ptr = error_ptr;
  470.    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
  471. }
  472. /* Allow the application to select one or more filters to use */
  473. void
  474. png_set_filter(png_structp png_ptr, int method, int filters)
  475. {
  476.    /* We allow 'method' only for future expansion of the base filter method */
  477.    if (method == 0)
  478.    {
  479.       switch (filters & (PNG_ALL_FILTERS | 0x07))
  480.       {
  481.          case 5:
  482.          case 6:
  483.          case 7: png_warning(png_ptr, "Unknown custom row filter for method 0");
  484.          case 0: png_ptr->do_filter = PNG_FILTER_NONE; break;
  485.          case 1: png_ptr->do_filter = PNG_FILTER_SUB; break;
  486.          case 2: png_ptr->do_filter = PNG_FILTER_UP; break;
  487.          case 3: png_ptr->do_filter = PNG_FILTER_AVG; break;
  488.          case 4: png_ptr->do_filter = PNG_FILTER_PAETH; break;
  489.          default: png_ptr->do_filter = (png_byte)filters; break;
  490.       }
  491.       /* If we have allocated the row_buf, then we should have also allocated
  492.        * all of the filter buffers that have been selected.
  493.        */
  494.       if (png_ptr->row_buf)
  495.       {
  496.          if (png_ptr->do_filter & PNG_FILTER_SUB && !(png_ptr->sub_row))
  497.          {
  498.             png_ptr->sub_row = (png_bytep )png_large_malloc(png_ptr,
  499.                png_ptr->rowbytes + 1);
  500.             png_ptr->sub_row[0] = 1;  /* Set the row filter type */
  501.          }
  502.          if (png_ptr->do_filter & PNG_FILTER_UP && !(png_ptr->up_row))
  503.          {
  504.             if (!(png_ptr->prev_row))
  505.             {
  506.                png_warning(png_ptr, "Can't to add up filter after starting");
  507.                png_ptr->do_filter &= ~PNG_FILTER_UP;
  508.             }
  509.             else
  510.             {
  511.                png_ptr->up_row = (png_bytep )png_large_malloc(png_ptr,
  512.                   png_ptr->rowbytes + 1);
  513.                png_ptr->up_row[0] = 2;  /* Set the row filter type */
  514.             }
  515.          }
  516.          if (png_ptr->do_filter & PNG_FILTER_AVG && !(png_ptr->avg_row))
  517.          {
  518.             if (!(png_ptr->prev_row))
  519.             {
  520.                png_warning(png_ptr, "Can't add average filter after starting");
  521.                png_ptr->do_filter &= ~PNG_FILTER_AVG;
  522.             }
  523.             else
  524.             {
  525.                png_ptr->up_row = (png_bytep )png_large_malloc(png_ptr,
  526.                   png_ptr->rowbytes + 1);
  527.                png_ptr->up_row[0] = 3;  /* Set the row filter type */
  528.             }
  529.          }
  530.          if (png_ptr->do_filter & PNG_FILTER_PAETH && !(png_ptr->paeth_row))
  531.          {
  532.             if (!(png_ptr->prev_row))
  533.             {
  534.                png_warning(png_ptr, "Can't add Paeth filter after starting");
  535.                png_ptr->do_filter &= ~PNG_FILTER_PAETH;
  536.             }
  537.             else
  538.             {
  539.                png_ptr->paeth_row = (png_bytep )png_large_malloc(png_ptr,
  540.                   png_ptr->rowbytes + 1);
  541.                png_ptr->paeth_row[0] = 4;  /* Set the row filter type */
  542.             }
  543.          }
  544.          if (png_ptr->do_filter == PNG_NO_FILTERS)
  545.             png_ptr->do_filter = PNG_FILTER_NONE;
  546.       }
  547.    }
  548.    else
  549.      png_error(png_ptr, "Unknown custom filter method");
  550. }
  551. void
  552. png_set_compression_level(png_structp png_ptr, int level)
  553. {
  554.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
  555.    png_ptr->zlib_level = level;
  556. }
  557. void
  558. png_set_compression_mem_level(png_structp png_ptr, int mem_level)
  559. {
  560.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
  561.    png_ptr->zlib_mem_level = mem_level;
  562. }
  563. void
  564. png_set_compression_strategy(png_structp png_ptr, int strategy)
  565. {
  566.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
  567.    png_ptr->zlib_strategy = strategy;
  568. }
  569. void
  570. png_set_compression_window_bits(png_structp png_ptr, int window_bits)
  571. {
  572.    if (window_bits > 15)
  573.       png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
  574.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
  575.    png_ptr->zlib_window_bits = window_bits;
  576. }
  577. void
  578. png_set_compression_method(png_structp png_ptr, int method)
  579. {
  580.    if (method != 8)
  581.       png_warning(png_ptr, "Only compression method 8 is supported by PNG");
  582.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
  583.    png_ptr->zlib_method = method;
  584. }