pngwrite.c
上传用户:zlh9724
上传日期:2007-01-04
资源大小:1991k
文件大小:16k
源码类别:

浏览器

开发平台:

Unix_Linux

  1. /* pngwrite.c - general routines to write a png file
  2. libpng 1.0 beta 2 - version 0.87
  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.    January 15, 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. #if defined(PNG_WRITE_tRNS_SUPPORTED)
  48.    if (info->valid & PNG_INFO_tRNS)
  49.       png_write_tRNS(png_ptr, info->trans, &(info->trans_values),
  50.          info->num_trans, info->color_type);
  51. #endif
  52. #if defined(PNG_WRITE_bKGD_SUPPORTED)
  53.    if (info->valid & PNG_INFO_bKGD)
  54.       png_write_bKGD(png_ptr, &(info->background), info->color_type);
  55. #endif
  56. #if defined(PNG_WRITE_hIST_SUPPORTED)
  57.    if (info->valid & PNG_INFO_hIST)
  58.       png_write_hIST(png_ptr, info->hist, info->num_palette);
  59. #endif
  60. #if defined(PNG_WRITE_pHYs_SUPPORTED)
  61.    if (info->valid & PNG_INFO_pHYs)
  62.       png_write_pHYs(png_ptr, info->x_pixels_per_unit,
  63.          info->y_pixels_per_unit, info->phys_unit_type);
  64. #endif
  65. #if defined(PNG_WRITE_oFFs_SUPPORTED)
  66.    if (info->valid & PNG_INFO_oFFs)
  67.       png_write_oFFs(png_ptr, info->x_offset, info->y_offset,
  68.          info->offset_unit_type);
  69. #endif
  70. #if defined(PNG_WRITE_tIME_SUPPORTED)
  71.    if (info->valid & PNG_INFO_tIME)
  72.       png_write_tIME(png_ptr, &(info->mod_time));
  73.    /* Check to see if we need to write text chunks */
  74. #endif
  75. #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
  76.    if (info->num_text)
  77.    {
  78.       int i; /* local counter */
  79.       /* loop through the text chunks */
  80.       for (i = 0; i < info->num_text; i++)
  81.       {
  82.          /* if chunk is compressed */
  83.          if (info->text[i].compression >= 0)
  84.          {
  85. #if defined(PNG_WRITE_zTXt_SUPPORTED)
  86. /* write compressed chunk */
  87.             png_write_zTXt(png_ptr, info->text[i].key,
  88.                info->text[i].text, info->text[i].text_length,
  89.                info->text[i].compression);
  90. #endif
  91.          }
  92.          else
  93.          {
  94. #if defined(PNG_WRITE_tEXt_SUPPORTED)
  95.             /* write uncompressed chunk */
  96.             png_write_tEXt(png_ptr, info->text[i].key,
  97. info->text[i].text, info->text[i].text_length);
  98. #endif
  99.          }
  100.       }
  101.    }
  102. #endif
  103. }
  104. /* writes the end of the png file.  If you don't want to write comments or
  105.    time information, you can pass NULL for info.  If you already wrote these
  106.    in png_write_info(), do not write them again here.  If you have long
  107.    comments, I suggest writing them here, and compressing them. */
  108. void
  109. png_write_end(png_structp png_ptr, png_infop info)
  110. {
  111. /* see if user wants us to write information chunks */
  112.    if (info)
  113.    {
  114. #if defined(PNG_WRITE_tIME_SUPPORTED)
  115.       /* check to see if user has supplied a time chunk */
  116.       if (info->valid & PNG_INFO_tIME)
  117.          png_write_tIME(png_ptr, &(info->mod_time));
  118. #endif
  119. #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
  120.       /* check to see if we need to write comment chunks */
  121.       if (info->num_text)
  122.       {
  123.          int i; /* local index variable */
  124.          /* loop through comment chunks */
  125.          for (i = 0; i < info->num_text; i++)
  126. {
  127.             /* check to see if comment is to be compressed */
  128.             if (info->text[i].compression >= 0)
  129.             {
  130. #if defined(PNG_WRITE_zTXt_SUPPORTED)
  131.                /* write compressed chunk */
  132.                png_write_zTXt(png_ptr, info->text[i].key,
  133.                   info->text[i].text, info->text[i].text_length,
  134.                   info->text[i].compression);
  135. #endif
  136.             }
  137.             else
  138.             {
  139. #if defined(PNG_WRITE_tEXt_SUPPORTED)
  140.                /* write uncompressed chunk */
  141.                png_write_tEXt(png_ptr, info->text[i].key,
  142.                   info->text[i].text, info->text[i].text_length);
  143. #endif
  144. }
  145.          }
  146.       }
  147. #endif
  148.    }
  149.    /* write end of png file */
  150.    png_write_IEND(png_ptr);
  151. }
  152. #if defined(PNG_WRITE_tIME_SUPPORTED)
  153. void
  154. png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
  155. {
  156. ptime->year = (png_uint_16)(1900 + ttime->tm_year);
  157. ptime->month = (png_byte)(ttime->tm_mon + 1);
  158. ptime->day = (png_byte)ttime->tm_mday;
  159. ptime->hour = (png_byte)ttime->tm_hour;
  160. ptime->minute = (png_byte)ttime->tm_min;
  161. ptime->second = (png_byte)ttime->tm_sec;
  162. }
  163. void
  164. png_convert_from_time_t(png_timep ptime, time_t ttime)
  165. {
  166.    struct tm *tbuf;
  167.    tbuf = gmtime(&ttime);
  168.    png_convert_from_struct_tm(ptime, tbuf);
  169. }
  170. #endif
  171. /* initialize png structure, and allocate any memory needed */
  172. void
  173. png_write_init(png_structp png_ptr)
  174. {
  175.    jmp_buf tmp_jmp; /* to save current jump buffer */
  176. png_msg_ptr error_fn;
  177. png_msg_ptr warning_fn;
  178. png_voidp msg_ptr;
  179. /* save jump buffer and error functions */
  180. png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
  181. error_fn = png_ptr->error_fn;
  182. warning_fn = png_ptr->warning_fn;
  183. msg_ptr = png_ptr->msg_ptr;
  184. /* reset all variables to 0 */
  185. png_memset(png_ptr, 0, sizeof (png_struct));
  186. /* restore jump buffer and error functions */
  187.    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
  188. png_ptr->error_fn = error_fn;
  189. png_ptr->warning_fn = warning_fn;
  190. png_ptr->msg_ptr = msg_ptr;
  191.    /* initialize zbuf - compression buffer */
  192.    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
  193.    png_ptr->zbuf = png_large_malloc(png_ptr, png_ptr->zbuf_size);
  194. }
  195. /* write a few rows of image data.  If the image is interlaced,
  196.    either you will have to write the 7 sub images, or, if you
  197.    have called png_set_interlace_handling(), you will have to
  198. "write" the image seven times */
  199. void
  200. png_write_rows(png_structp png_ptr, png_bytepp row,
  201.    png_uint_32 num_rows)
  202. {
  203.    png_uint_32 i; /* row counter */
  204.    png_bytepp rp; /* row pointer */
  205.    /* loop through the rows */
  206.    for (i = 0, rp = row; i < num_rows; i++, rp++)
  207.    {
  208.       png_write_row(png_ptr, *rp);
  209.    }
  210. }
  211. /* write the image.  You only need to call this function once, even
  212.    if you are writing an interlaced image. */
  213. void
  214. png_write_image(png_structp png_ptr, png_bytepp image)
  215. {
  216.    png_uint_32 i; /* row index */
  217.    int pass, num_pass; /* pass variables */
  218.    png_bytepp rp; /* points to current row */
  219.    /* intialize interlace handling.  If image is not interlaced,
  220.       this will set pass to 1 */
  221.    num_pass = png_set_interlace_handling(png_ptr);
  222.    /* loop through passes */
  223.    for (pass = 0; pass < num_pass; pass++)
  224.    {
  225.       /* loop through image */
  226.       for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
  227.       {
  228.          png_write_row(png_ptr, *rp);
  229.       }
  230.    }
  231. }
  232. /* write a row of image data */
  233. void
  234. png_write_row(png_structp png_ptr, png_bytep row)
  235. {
  236.    /* initialize transformations and other stuff if first time */
  237.    if (png_ptr->row_number == 0 && png_ptr->pass == 0)
  238.    {
  239.       png_write_start_row(png_ptr);
  240.    }
  241. #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
  242.    /* if interlaced and not interested in row, return */
  243.    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
  244.    {
  245.       switch (png_ptr->pass)
  246.       {
  247. case 0:
  248.             if (png_ptr->row_number & 7)
  249.             {
  250.                png_write_finish_row(png_ptr);
  251.                return;
  252.             }
  253.             break;
  254.          case 1:
  255.             if ((png_ptr->row_number & 7) || png_ptr->width < 5)
  256.             {
  257.                png_write_finish_row(png_ptr);
  258.                return;
  259.             }
  260.             break;
  261.          case 2:
  262.             if ((png_ptr->row_number & 7) != 4)
  263.             {
  264.                png_write_finish_row(png_ptr);
  265. return;
  266.             }
  267.             break;
  268.          case 3:
  269.             if ((png_ptr->row_number & 3) || png_ptr->width < 3)
  270.             {
  271.                png_write_finish_row(png_ptr);
  272.                return;
  273.             }
  274.             break;
  275.          case 4:
  276.             if ((png_ptr->row_number & 3) != 2)
  277.             {
  278.                png_write_finish_row(png_ptr);
  279.                return;
  280.             }
  281.             break;
  282.          case 5:
  283. if ((png_ptr->row_number & 1) || png_ptr->width < 2)
  284.             {
  285.                png_write_finish_row(png_ptr);
  286.                return;
  287.             }
  288.             break;
  289.          case 6:
  290.             if (!(png_ptr->row_number & 1))
  291.             {
  292.                png_write_finish_row(png_ptr);
  293.                return;
  294.             }
  295.             break;
  296.       }
  297.    }
  298. #endif
  299.    /* set up row info for transformations */
  300. png_ptr->row_info.color_type = png_ptr->color_type;
  301.    png_ptr->row_info.width = png_ptr->usr_width;
  302.    png_ptr->row_info.channels = png_ptr->usr_channels;
  303.    png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
  304. png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
  305. png_ptr->row_info.channels);
  306.    png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
  307.       (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
  308.    /* copy users row into buffer, leaving room for filter byte */
  309.    png_memcpy(png_ptr->row_buf + 1, row, (png_size_t)png_ptr->row_info.rowbytes);
  310. #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
  311.    /* handle interlacing */
  312.    if (png_ptr->interlaced && png_ptr->pass < 6 &&
  313.       (png_ptr->transformations & PNG_INTERLACE))
  314.    {
  315.       png_do_write_interlace(&(png_ptr->row_info),
  316. png_ptr->row_buf + 1, png_ptr->pass);
  317.       /* this should always get caught above, but still ... */
  318.       if (!(png_ptr->row_info.width))
  319.       {
  320.          png_write_finish_row(png_ptr);
  321.          return;
  322.       }
  323.    }
  324. #endif
  325.    /* handle other transformations */
  326.    if (png_ptr->transformations)
  327.       png_do_write_transformations(png_ptr);
  328.    /* filter rows that have been proved to help */
  329.    if (png_ptr->do_filter)
  330.    {
  331.       /* save row to previous row */
  332. png_memcpy(png_ptr->save_row, png_ptr->row_buf,
  333.          (png_size_t)png_ptr->row_info.rowbytes + 1);
  334.       /* filter row */
  335.       png_write_filter_row(&(png_ptr->row_info), png_ptr->row_buf,
  336.          png_ptr->prev_row);
  337.       /* trade saved pointer and prev pointer so next row references are correctly */
  338.       { /* scope limiter */
  339. png_bytep tptr;
  340.          tptr = png_ptr->prev_row;
  341.          png_ptr->prev_row = png_ptr->save_row;
  342.          png_ptr->save_row = tptr;
  343.       }
  344.    }
  345.    else
  346.       /* set filter row to "none" */
  347. png_ptr->row_buf[0] = 0;
  348.    /* set up the zlib input buffer */
  349.    png_ptr->zstream->next_in = png_ptr->row_buf;
  350.    png_ptr->zstream->avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
  351.    /* repeat until we have compressed all the data */
  352.    do
  353.    {
  354.       int ret; /* return of zlib */
  355.       /* compress the data */
  356.       ret = deflate(png_ptr->zstream, Z_NO_FLUSH);
  357.       /* check for compression errors */
  358.       if (ret != Z_OK)
  359.       {
  360.          if (png_ptr->zstream->msg)
  361.             png_error(png_ptr, png_ptr->zstream->msg);
  362. else
  363. png_error(png_ptr, "zlib error");
  364.       }
  365.       /* see if it is time to write another IDAT */
  366.       if (!png_ptr->zstream->avail_out)
  367.       {
  368.          /* write the IDAT and reset the zlib output buffer */
  369.          png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
  370.          png_ptr->zstream->next_out = png_ptr->zbuf;
  371.          png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
  372.       }
  373.    /* repeat until all data has been compressed */
  374.    } while (png_ptr->zstream->avail_in);
  375. /* finish row - updates counters and flushes zlib if last row */
  376. png_write_finish_row(png_ptr);
  377. #if defined(PNG_WRITE_FLUSH_SUPPORTED)
  378. png_ptr->flush_rows++;
  379. if (png_ptr->flush_dist > 0 &&
  380.  png_ptr->flush_rows >= png_ptr->flush_dist)
  381. {
  382. png_write_flush(png_ptr);
  383. }
  384. #endif /* PNG_WRITE_FLUSH_SUPPORTED */
  385. }
  386. #if defined(PNG_WRITE_FLUSH_SUPPORTED)
  387. /* Set the automatic flush interval or 0 to turn flushing off */
  388. void
  389. png_set_flush(png_structp png_ptr, int nrows)
  390. {
  391. png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
  392. }
  393. /* flush the current output buffers now */
  394. void
  395. png_write_flush(png_structp png_ptr)
  396. {
  397. int wrote_IDAT;
  398. if (png_ptr->mode != PNG_HAVE_IDAT)
  399.   return;
  400. do
  401. {
  402. int ret;
  403. /* compress the data */
  404. ret = deflate(png_ptr->zstream, Z_SYNC_FLUSH);
  405. wrote_IDAT = 0;
  406. /* check for compression errors */
  407. if (ret != Z_OK)
  408. {
  409. if (png_ptr->zstream->msg)
  410. png_error(png_ptr, png_ptr->zstream->msg);
  411. else
  412. png_error(png_ptr, "zlib error");
  413. }
  414. if (!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);
  419. png_ptr->zstream->next_out = png_ptr->zbuf;
  420. png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
  421. wrote_IDAT = 1;
  422. }
  423. } while(wrote_IDAT == 1);
  424. /* If there is any data left to be output, write it into a new IDAT */
  425. if (png_ptr->zbuf_size != png_ptr->zstream->avail_out)
  426. {
  427. /* write the IDAT and reset the zlib output buffer */
  428. png_write_IDAT(png_ptr, png_ptr->zbuf,
  429. png_ptr->zbuf_size - png_ptr->zstream->avail_out);
  430. png_ptr->zstream->next_out = png_ptr->zbuf;
  431. png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
  432. }
  433. png_ptr->flush_rows = 0;
  434. png_flush(png_ptr);
  435. }
  436. #endif /* PNG_WRITE_FLUSH_SUPPORTED */
  437. /* free any memory used in png struct */
  438. void
  439. png_write_destroy(png_structp png_ptr)
  440. {
  441. jmp_buf tmp_jmp; /* save jump buffer */
  442.    /* free any memory zlib uses */
  443. deflateEnd(png_ptr->zstream);
  444.    png_free(png_ptr, png_ptr->zstream);
  445.    /* free our memory.  png_free checks NULL for us. */
  446.    png_large_free(png_ptr, png_ptr->zbuf);
  447.    png_large_free(png_ptr, png_ptr->row_buf);
  448.    png_large_free(png_ptr, png_ptr->prev_row);
  449.    png_large_free(png_ptr, png_ptr->save_row);
  450.    /* reset structure */
  451.    png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
  452.    png_memset(png_ptr, 0, sizeof (png_struct));
  453.    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
  454. }
  455. void
  456. png_set_filtering(png_structp png_ptr, int filter)
  457. {
  458.    png_ptr->do_custom_filter = 1;
  459.    png_ptr->do_filter = (png_byte)filter;
  460. }
  461. void
  462. png_set_compression_level(png_structp png_ptr, int level)
  463. {
  464.    png_ptr->zlib_custom_level = 1;
  465.    png_ptr->zlib_level = level;
  466. }
  467. void
  468. png_set_compression_mem_level(png_structp png_ptr, int mem_level)
  469. {
  470.    png_ptr->zlib_custom_mem_level = 1;
  471. png_ptr->zlib_mem_level = mem_level;
  472. }
  473. void
  474. png_set_compression_strategy(png_structp png_ptr, int strategy)
  475. {
  476.    png_ptr->zlib_custom_strategy = 1;
  477.    png_ptr->zlib_strategy = strategy;
  478. }
  479. void
  480. png_set_compression_window_bits(png_structp png_ptr, int window_bits)
  481. {
  482.    png_ptr->zlib_custom_window_bits = 1;
  483.    png_ptr->zlib_window_bits = window_bits;
  484. }
  485. void
  486. png_set_compression_method(png_structp png_ptr, int method)
  487. {
  488.    png_ptr->zlib_custom_method = 1;
  489.    png_ptr->zlib_method = method;
  490. }