source: svn/newcon3bcm2_21bu/dst/dlib/src/PNG/pngwrite.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 33.9 KB
Line 
1/*
2 * $Id: //suprahd/releases/suprahd_163/suprahd_ztvapp640_163/drivers/graphics/PNG/lpng102/pngwrite.c#1 $
3 * $Revision: #1 $
4 * $DateTime: 2006/02/24 17:51:46 $
5 * $Change: 42566 $
6 * $Author: pryush.sharma $
7 */
8
9   
10/* pngwrite.c - general routines to write a PNG file
11 *
12 * libpng 1.0.2 - June 14, 1998
13 * For conditions of distribution and use, see copyright notice in png.h
14 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
15 * Copyright (c) 1996, 1997 Andreas Dilger
16 * Copyright (c) 1998, Glenn Randers-Pehrson
17 */
18
19/* get internal access to png.h */
20#define PNG_INTERNAL
21#include "png.h"
22
23/* Writes all the PNG information.  This is the suggested way to use the
24 * library.  If you have a new chunk to add, make a function to write it,
25 * and put it in the correct location here.  If you want the chunk written
26 * after the image data, put it in png_write_end().  I strongly encourage
27 * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
28 * the chunk, as that will keep the code from breaking if you want to just
29 * write a plain PNG file.  If you have long comments, I suggest writing
30 * them in png_write_end(), and compressing them.
31 */
32void
33png_write_info(png_structp png_ptr, png_infop info_ptr)
34{
35#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
36   int i;
37#endif
38
39   png_debug(1, "in png_write_info\n");
40   png_write_sig(png_ptr); /* write PNG signature */
41   /* write IHDR information. */
42   png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
43      info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
44      info_ptr->filter_type,
45#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
46      info_ptr->interlace_type);
47#else
48      0);
49#endif
50   /* the rest of these check to see if the valid field has the appropriate
51      flag set, and if it does, writes the chunk. */
52#if defined(PNG_WRITE_gAMA_SUPPORTED)
53   if (info_ptr->valid & PNG_INFO_gAMA)
54      png_write_gAMA(png_ptr, info_ptr->gamma);
55#endif
56#if defined(PNG_WRITE_sRGB_SUPPORTED)
57   if (info_ptr->valid & PNG_INFO_sRGB)
58      png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
59#endif
60#if defined(PNG_WRITE_sBIT_SUPPORTED)
61   if (info_ptr->valid & PNG_INFO_sBIT)
62      png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
63#endif
64#if defined(PNG_WRITE_cHRM_SUPPORTED)
65   if (info_ptr->valid & PNG_INFO_cHRM)
66      png_write_cHRM(png_ptr,
67         info_ptr->x_white, info_ptr->y_white,
68         info_ptr->x_red, info_ptr->y_red,
69         info_ptr->x_green, info_ptr->y_green,
70         info_ptr->x_blue, info_ptr->y_blue);
71#endif
72   if (info_ptr->valid & PNG_INFO_PLTE)
73      png_write_PLTE(png_ptr, info_ptr->palette,
74         (png_uint_32)info_ptr->num_palette);
75   else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
76      png_error(png_ptr, "Valid palette required for paletted images\n");
77
78#if defined(PNG_WRITE_tRNS_SUPPORTED)
79   if (info_ptr->valid & PNG_INFO_tRNS)
80      {
81#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
82         /* invert the alpha channel (in tRNS) */
83         if (png_ptr->transformations & PNG_INVERT_ALPHA &&
84            info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
85         {
86            int j;
87            for (j=0; j<(int)info_ptr->num_trans; j++)
88               info_ptr->trans[j] = 255 - info_ptr->trans[j];
89         }
90#endif
91      png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values),
92         info_ptr->num_trans, info_ptr->color_type);
93      }
94#endif
95#if defined(PNG_WRITE_bKGD_SUPPORTED)
96   if (info_ptr->valid & PNG_INFO_bKGD)
97      png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
98#endif
99#if defined(PNG_WRITE_hIST_SUPPORTED)
100   if (info_ptr->valid & PNG_INFO_hIST)
101      png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
102#endif
103#if defined(PNG_WRITE_oFFs_SUPPORTED)
104   if (info_ptr->valid & PNG_INFO_oFFs)
105      png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
106         info_ptr->offset_unit_type);
107#endif
108#if defined(PNG_WRITE_pCAL_SUPPORTED)
109   if (info_ptr->valid & PNG_INFO_pCAL)
110      png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
111         info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
112         info_ptr->pcal_units, info_ptr->pcal_params);
113#endif
114#if defined(PNG_WRITE_pHYs_SUPPORTED)
115   if (info_ptr->valid & PNG_INFO_pHYs)
116      png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
117         info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
118#endif
119#if defined(PNG_WRITE_tIME_SUPPORTED)
120   if (info_ptr->valid & PNG_INFO_tIME)
121   {
122      png_write_tIME(png_ptr, &(info_ptr->mod_time));
123      png_ptr->flags |= PNG_FLAG_WROTE_tIME;
124   }
125#endif
126#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
127   /* Check to see if we need to write text chunks */
128   for (i = 0; i < info_ptr->num_text; i++)
129   {
130      png_debug2(2, "Writing header text chunk %d, type %d\n", i,
131         info_ptr->text[i].compression);
132      /* If we want a compressed text chunk */
133      if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
134      {
135#if defined(PNG_WRITE_zTXt_SUPPORTED)
136         /* write compressed chunk */
137         png_write_zTXt(png_ptr, info_ptr->text[i].key,
138            info_ptr->text[i].text, info_ptr->text[i].text_length,
139            info_ptr->text[i].compression);
140#else
141         png_warning(png_ptr, "Unable to write compressed text\n");
142#endif
143         /* Mark this chunk as written */
144         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
145      }
146      else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
147      {
148#if defined(PNG_WRITE_tEXt_SUPPORTED)
149         /* write uncompressed chunk */
150         png_write_tEXt(png_ptr, info_ptr->text[i].key,
151            info_ptr->text[i].text, info_ptr->text[i].text_length);
152#else
153         png_warning(png_ptr, "Unable to write uncompressed text\n");
154#endif
155         /* Mark this chunk as written */
156         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
157      }
158   }
159#endif
160}
161
162/* Writes the end of the PNG file.  If you don't want to write comments or
163 * time information, you can pass NULL for info.  If you already wrote these
164 * in png_write_info(), do not write them again here.  If you have long
165 * comments, I suggest writing them here, and compressing them.
166 */
167void
168png_write_end(png_structp png_ptr, png_infop info_ptr)
169{
170   png_debug(1, "in png_write_end\n");
171   if (!(png_ptr->mode & PNG_HAVE_IDAT))
172      png_error(png_ptr, "No IDATs written into file");
173
174   /* see if user wants us to write information chunks */
175   if (info_ptr != NULL)
176   {
177#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
178      int i; /* local index variable */
179#endif
180#if defined(PNG_WRITE_tIME_SUPPORTED)
181      /* check to see if user has supplied a time chunk */
182      if (info_ptr->valid & PNG_INFO_tIME &&
183         !(png_ptr->flags & PNG_FLAG_WROTE_tIME))
184         png_write_tIME(png_ptr, &(info_ptr->mod_time));
185#endif
186#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
187      /* loop through comment chunks */
188      for (i = 0; i < info_ptr->num_text; i++)
189      {
190         png_debug2(2, "Writing trailer text chunk %d, type %d\n", i,
191            info_ptr->text[i].compression);
192         if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
193         {
194#if defined(PNG_WRITE_zTXt_SUPPORTED)
195            /* write compressed chunk */
196            png_write_zTXt(png_ptr, info_ptr->text[i].key,
197               info_ptr->text[i].text, info_ptr->text[i].text_length,
198               info_ptr->text[i].compression);
199#else
200            png_warning(png_ptr, "Unable to write compressed text\n");
201#endif
202            /* Mark this chunk as written */
203            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
204         }
205         else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
206         {
207#if defined(PNG_WRITE_tEXt_SUPPORTED)
208            /* write uncompressed chunk */
209            png_write_tEXt(png_ptr, info_ptr->text[i].key,
210               info_ptr->text[i].text, info_ptr->text[i].text_length);
211#else
212            png_warning(png_ptr, "Unable to write uncompressed text\n");
213#endif
214
215            /* Mark this chunk as written */
216            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
217         }
218      }
219#endif
220   }
221
222   png_ptr->mode |= PNG_AFTER_IDAT;
223
224   /* write end of PNG file */
225   png_write_IEND(png_ptr);
226}
227
228#if defined(PNG_WRITE_tIME_SUPPORTED)
229void
230png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
231{
232   png_debug(1, "in png_convert_from_struct_tm\n");
233   ptime->year = (png_uint_16)(1900 + ttime->tm_year);
234   ptime->month = (png_byte)(ttime->tm_mon + 1);
235   ptime->day = (png_byte)ttime->tm_mday;
236   ptime->hour = (png_byte)ttime->tm_hour;
237   ptime->minute = (png_byte)ttime->tm_min;
238   ptime->second = (png_byte)ttime->tm_sec;
239}
240
241void
242png_convert_from_time_t(png_timep ptime, time_t ttime)
243{
244   struct tm *tbuf;
245
246   png_debug(1, "in png_convert_from_time_t\n");
247   tbuf = gmtime(&ttime);
248   png_convert_from_struct_tm(ptime, tbuf);
249}
250#endif
251
252/* Initialize png_ptr structure, and allocate any memory needed */
253png_structp
254png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr,
255   png_error_ptr error_fn, png_error_ptr warn_fn)
256{
257#ifdef PNG_USER_MEM_SUPPORTED
258   return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
259      warn_fn, NULL, NULL, NULL));
260}
261
262/* Alternate initialize png_ptr structure, and allocate any memory needed */
263png_structp
264png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
265   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
266   png_malloc_ptr malloc_fn, png_free_ptr free_fn)
267{
268#endif /* PNG_USER_MEM_SUPPORTED */
269   png_structp png_ptr;
270#ifdef USE_FAR_KEYWORD
271   jmp_buf jmpbuf;
272#endif
273   png_debug(1, "in png_create_write_struct\n");
274#ifdef PNG_USER_MEM_SUPPORTED
275   if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
276      (png_malloc_ptr)malloc_fn)) == NULL)
277#else
278   if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
279#endif /* PNG_USER_MEM_SUPPORTED */
280   {
281      return ((png_structp)NULL);
282   }
283#ifdef USE_FAR_KEYWORD
284   if (setjmp(jmpbuf))
285#else
286   if (setjmp(&png_ptr->jmpbuf))
287#endif
288   {
289      png_free(png_ptr, png_ptr->zbuf);
290      png_destroy_struct(png_ptr);
291      return ((png_structp)NULL);
292   }
293#ifdef USE_FAR_KEYWORD
294   png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
295#endif
296#ifdef PNG_USER_MEM_SUPPORTED
297   png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
298#endif /* PNG_USER_MEM_SUPPORTED */
299   png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
300
301   /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
302    * we must recompile any applications that use any older library version.
303    * For versions after libpng 1.0, we will be compatible, so we need
304    * only check the first digit.
305    */
306   if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
307       (png_libpng_ver[0] == '0' && user_png_ver[2] < '9'))
308   {
309      png_error(png_ptr,
310         "Incompatible libpng version in application and library");
311   }
312
313   /* initialize zbuf - compression buffer */
314   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
315   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
316      (png_uint_32)png_ptr->zbuf_size);
317
318   png_set_write_fn(png_ptr, NULL, NULL, NULL);
319
320#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
321   png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
322      1, NULL, NULL);
323#endif
324
325   return ((png_structp)png_ptr);
326}
327
328/* Initialize png_ptr structure, and allocate any memory needed */
329void
330png_write_init(png_structp png_ptr)
331{
332   jmp_buf tmp_jmp; /* to save current jump buffer */
333
334   png_debug(1, "in png_write_init\n");
335   /* save jump buffer and error functions */
336   png_memcpy(&tmp_jmp, &png_ptr->jmpbuf, sizeof (jmp_buf));
337
338   /* reset all variables to 0 */
339   png_memset(png_ptr, 0, sizeof (png_struct));
340
341   /* restore jump buffer */
342   png_memcpy(&png_ptr->jmpbuf, &tmp_jmp, sizeof (jmp_buf));
343
344   /* initialize zbuf - compression buffer */
345   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
346   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
347      (png_uint_32)png_ptr->zbuf_size);
348   png_set_write_fn(png_ptr, NULL, NULL, NULL);
349
350#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
351   png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
352      1, NULL, NULL);
353#endif
354}
355
356/* Write a few rows of image data.  If the image is interlaced,
357 * either you will have to write the 7 sub images, or, if you
358 * have called png_set_interlace_handling(), you will have to
359 * "write" the image seven times.
360 */
361void
362png_write_rows(png_structp png_ptr, png_bytepp row,
363   png_uint_32 num_rows)
364{
365   png_uint_32 i; /* row counter */
366   png_bytepp rp; /* row pointer */
367
368   png_debug(1, "in png_write_rows\n");
369   /* loop through the rows */
370   for (i = 0, rp = row; i < num_rows; i++, rp++)
371   {
372      png_write_row(png_ptr, *rp);
373   }
374}
375
376/* Write the image.  You only need to call this function once, even
377 * if you are writing an interlaced image.
378 */
379void
380png_write_image(png_structp png_ptr, png_bytepp image)
381{
382   png_uint_32 i; /* row index */
383   int pass, num_pass; /* pass variables */
384   png_bytepp rp; /* points to current row */
385
386   png_debug(1, "in png_write_image\n");
387#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
388   /* intialize interlace handling.  If image is not interlaced,
389      this will set pass to 1 */
390   num_pass = png_set_interlace_handling(png_ptr);
391#else
392   num_pass = 1;
393#endif
394   /* loop through passes */
395   for (pass = 0; pass < num_pass; pass++)
396   {
397      /* loop through image */
398      for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
399      {
400         png_write_row(png_ptr, *rp);
401      }
402   }
403}
404
405/* called by user to write a row of image data */
406void
407png_write_row(png_structp png_ptr, png_bytep row)
408{
409   png_debug2(1, "in png_write_row (row %ld, pass %d)\n",
410      png_ptr->row_number, png_ptr->pass);
411   /* initialize transformations and other stuff if first time */
412   if (png_ptr->row_number == 0 && png_ptr->pass == 0)
413   {
414   /* check for transforms that have been set but were defined out */
415#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
416   if (png_ptr->transformations & PNG_INVERT_MONO)
417      png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined.");
418#endif
419#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
420   if (png_ptr->transformations & PNG_FILLER)
421      png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined.");
422#endif
423#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED)
424   if (png_ptr->transformations & PNG_PACKSWAP)
425      png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined.");
426#endif
427#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
428   if (png_ptr->transformations & PNG_PACK)
429      png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined.");
430#endif
431#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
432   if (png_ptr->transformations & PNG_SHIFT)
433      png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined.");
434#endif
435#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
436   if (png_ptr->transformations & PNG_BGR)
437      png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined.");
438#endif
439#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
440   if (png_ptr->transformations & PNG_SWAP_BYTES)
441      png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined.");
442#endif
443
444      png_write_start_row(png_ptr);
445   }
446
447#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
448   /* if interlaced and not interested in row, return */
449   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
450   {
451      switch (png_ptr->pass)
452      {
453         case 0:
454            if (png_ptr->row_number & 7)
455            {
456               png_write_finish_row(png_ptr);
457               return;
458            }
459            break;
460         case 1:
461            if ((png_ptr->row_number & 7) || png_ptr->width < 5)
462            {
463               png_write_finish_row(png_ptr);
464               return;
465            }
466            break;
467         case 2:
468            if ((png_ptr->row_number & 7) != 4)
469            {
470               png_write_finish_row(png_ptr);
471               return;
472            }
473            break;
474         case 3:
475            if ((png_ptr->row_number & 3) || png_ptr->width < 3)
476            {
477               png_write_finish_row(png_ptr);
478               return;
479            }
480            break;
481         case 4:
482            if ((png_ptr->row_number & 3) != 2)
483            {
484               png_write_finish_row(png_ptr);
485               return;
486            }
487            break;
488         case 5:
489            if ((png_ptr->row_number & 1) || png_ptr->width < 2)
490            {
491               png_write_finish_row(png_ptr);
492               return;
493            }
494            break;
495         case 6:
496            if (!(png_ptr->row_number & 1))
497            {
498               png_write_finish_row(png_ptr);
499               return;
500            }
501            break;
502      }
503   }
504#endif
505
506   /* set up row info for transformations */
507   png_ptr->row_info.color_type = png_ptr->color_type;
508   png_ptr->row_info.width = png_ptr->usr_width;
509   png_ptr->row_info.channels = png_ptr->usr_channels;
510   png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
511   png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
512      png_ptr->row_info.channels);
513
514   png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
515      (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
516
517   png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type);
518   png_debug1(3, "row_info->width = %d\n", png_ptr->row_info.width);
519   png_debug1(3, "row_info->channels = %d\n", png_ptr->row_info.channels);
520   png_debug1(3, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth);
521   png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth);
522   png_debug1(3, "row_info->rowbytes = %d\n", png_ptr->row_info.rowbytes);
523
524   /* Copy user's row into buffer, leaving room for filter byte. */
525   png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row,
526      png_ptr->row_info.rowbytes);
527
528#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
529   /* handle interlacing */
530   if (png_ptr->interlaced && png_ptr->pass < 6 &&
531      (png_ptr->transformations & PNG_INTERLACE))
532   {
533      png_do_write_interlace(&(png_ptr->row_info),
534         png_ptr->row_buf + 1, png_ptr->pass);
535      /* this should always get caught above, but still ... */
536      if (!(png_ptr->row_info.width))
537      {
538         png_write_finish_row(png_ptr);
539         return;
540      }
541   }
542#endif
543
544   /* handle other transformations */
545   if (png_ptr->transformations)
546      png_do_write_transformations(png_ptr);
547
548   /* Find a filter if necessary, filter the row and write it out. */
549   png_write_find_filter(png_ptr, &(png_ptr->row_info));
550
551   if (png_ptr->write_row_fn != NULL)
552      (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
553}
554
555#if defined(PNG_WRITE_FLUSH_SUPPORTED)
556/* Set the automatic flush interval or 0 to turn flushing off */
557void
558png_set_flush(png_structp png_ptr, int nrows)
559{
560   png_debug(1, "in png_set_flush\n");
561   png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
562}
563
564/* flush the current output buffers now */
565void
566png_write_flush(png_structp png_ptr)
567{
568   int wrote_IDAT;
569
570   png_debug(1, "in png_write_flush\n");
571   /* We have already written out all of the data */
572   if (png_ptr->row_number >= png_ptr->num_rows)
573     return;
574
575   do
576   {
577      int ret;
578
579      /* compress the data */
580      ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH);
581      wrote_IDAT = 0;
582
583      /* check for compression errors */
584      if (ret != Z_OK)
585      {
586         if (png_ptr->zstream.msg != NULL)
587            png_error(png_ptr, png_ptr->zstream.msg);
588         else
589            png_error(png_ptr, "zlib error");
590      }
591
592      if (!(png_ptr->zstream.avail_out))
593      {
594         /* write the IDAT and reset the zlib output buffer */
595         png_write_IDAT(png_ptr, png_ptr->zbuf,
596                        png_ptr->zbuf_size);
597         png_ptr->zstream.next_out = png_ptr->zbuf;
598         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
599         wrote_IDAT = 1;
600      }
601   } while(wrote_IDAT == 1);
602
603   /* If there is any data left to be output, write it into a new IDAT */
604   if (png_ptr->zbuf_size != png_ptr->zstream.avail_out)
605   {
606      /* write the IDAT and reset the zlib output buffer */
607      png_write_IDAT(png_ptr, png_ptr->zbuf,
608                     png_ptr->zbuf_size - png_ptr->zstream.avail_out);
609      png_ptr->zstream.next_out = png_ptr->zbuf;
610      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
611   }
612   png_ptr->flush_rows = 0;
613   png_flush(png_ptr);
614}
615#endif /* PNG_WRITE_FLUSH_SUPPORTED */
616
617/* free all memory used by the write */
618void
619png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
620{
621   png_structp png_ptr = NULL;
622   png_infop info_ptr = NULL;
623#ifdef PNG_USER_MEM_SUPPORTED
624   png_free_ptr free_fn = NULL;
625#endif
626
627   png_debug(1, "in png_destroy_write_struct\n");
628   if (png_ptr_ptr != NULL)
629   {
630      png_ptr = *png_ptr_ptr;
631#ifdef PNG_USER_MEM_SUPPORTED
632      free_fn = png_ptr->free_fn;
633#endif
634   }
635
636   if (info_ptr_ptr != NULL)
637      info_ptr = *info_ptr_ptr;
638
639   if (info_ptr != NULL)
640   {
641#ifdef PNG_WRITE_tEXt_SUPPORTED
642      png_free(png_ptr, info_ptr->text);
643#endif
644#if defined(PNG_READ_pCAL_SUPPORTED)
645      png_free(png_ptr, info_ptr->pcal_purpose);
646      png_free(png_ptr, info_ptr->pcal_units);
647      if (info_ptr->pcal_params != NULL)
648      {
649         int i;
650         for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
651         {
652            png_free(png_ptr, info_ptr->pcal_params[i]);
653         }
654         png_free(png_ptr, info_ptr->pcal_params);
655      }
656#endif
657#ifdef PNG_USER_MEM_SUPPORTED
658      png_destroy_struct_2((png_voidp)info_ptr, free_fn);
659#else
660      png_destroy_struct((png_voidp)info_ptr);
661#endif
662      *info_ptr_ptr = (png_infop)NULL;
663   }
664
665   if (png_ptr != NULL)
666   {
667      png_write_destroy(png_ptr);
668#ifdef PNG_USER_MEM_SUPPORTED
669      png_destroy_struct_2((png_voidp)png_ptr, free_fn);
670#else
671      png_destroy_struct((png_voidp)png_ptr);
672#endif
673      *png_ptr_ptr = (png_structp)NULL;
674   }
675}
676
677
678/* Free any memory used in png_ptr struct (old method) */
679void
680png_write_destroy(png_structp png_ptr)
681{
682   jmp_buf tmp_jmp; /* save jump buffer */
683   png_error_ptr error_fn;
684   png_error_ptr warning_fn;
685   png_voidp error_ptr;
686#ifdef PNG_USER_MEM_SUPPORTED
687   png_free_ptr free_fn;
688#endif
689
690   png_debug(1, "in png_write_destroy\n");
691   /* free any memory zlib uses */
692   deflateEnd(&png_ptr->zstream);
693
694   /* free our memory.  png_free checks NULL for us. */
695   png_free(png_ptr, png_ptr->zbuf);
696   png_free(png_ptr, png_ptr->row_buf);
697   png_free(png_ptr, png_ptr->prev_row);
698   png_free(png_ptr, png_ptr->sub_row);
699   png_free(png_ptr, png_ptr->up_row);
700   png_free(png_ptr, png_ptr->avg_row);
701   png_free(png_ptr, png_ptr->paeth_row);
702#if defined(PNG_TIME_RFC1123_SUPPORTED)
703   png_free(png_ptr, png_ptr->time_buffer);
704#endif /* PNG_TIME_RFC1123_SUPPORTED */
705#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
706   png_free(png_ptr, png_ptr->prev_filters);
707   png_free(png_ptr, png_ptr->filter_weights);
708   png_free(png_ptr, png_ptr->inv_filter_weights);
709   png_free(png_ptr, png_ptr->filter_costs);
710   png_free(png_ptr, png_ptr->inv_filter_costs);
711#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
712
713   /* reset structure */
714   png_memcpy(&tmp_jmp, &png_ptr->jmpbuf, sizeof (jmp_buf));
715
716   error_fn = png_ptr->error_fn;
717   warning_fn = png_ptr->warning_fn;
718   error_ptr = png_ptr->error_ptr;
719#ifdef PNG_USER_MEM_SUPPORTED
720   free_fn = png_ptr->free_fn;
721#endif
722
723   png_memset(png_ptr, 0, sizeof (png_struct));
724
725   png_ptr->error_fn = error_fn;
726   png_ptr->warning_fn = warning_fn;
727   png_ptr->error_ptr = error_ptr;
728#ifdef PNG_USER_MEM_SUPPORTED
729   png_ptr->free_fn = free_fn;
730#endif
731
732   png_memcpy(&png_ptr->jmpbuf, &tmp_jmp, sizeof (jmp_buf));
733}
734
735/* Allow the application to select one or more row filters to use. */
736void
737png_set_filter(png_structp png_ptr, int method, int filters)
738{
739   png_debug(1, "in png_set_filter\n");
740   /* We allow 'method' only for future expansion of the base filter method. */
741   if (method == PNG_FILTER_TYPE_BASE)
742   {
743      switch (filters & (PNG_ALL_FILTERS | 0x07))
744      {
745         case 5:
746         case 6:
747         case 7: png_warning(png_ptr, "Unknown row filter for method 0");
748         case PNG_FILTER_VALUE_NONE:  png_ptr->do_filter=PNG_FILTER_NONE; break;
749         case PNG_FILTER_VALUE_SUB:   png_ptr->do_filter=PNG_FILTER_SUB;  break;
750         case PNG_FILTER_VALUE_UP:    png_ptr->do_filter=PNG_FILTER_UP;   break;
751         case PNG_FILTER_VALUE_AVG:   png_ptr->do_filter=PNG_FILTER_AVG;  break;
752         case PNG_FILTER_VALUE_PAETH: png_ptr->do_filter=PNG_FILTER_PAETH;break;
753         default: png_ptr->do_filter = (png_byte)filters; break;
754      }
755
756      /* If we have allocated the row_buf, this means we have already started
757       * with the image and we should have allocated all of the filter buffers
758       * that have been selected.  If prev_row isn't already allocated, then
759       * it is too late to start using the filters that need it, since we
760       * will be missing the data in the previous row.  If an application
761       * wants to start and stop using particular filters during compression,
762       * it should start out with all of the filters, and then add and
763       * remove them after the start of compression.
764       */
765      if (png_ptr->row_buf != NULL)
766      {
767         if (png_ptr->do_filter & PNG_FILTER_SUB && png_ptr->sub_row == NULL)
768         {
769            png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
770              (png_ptr->rowbytes + 1));
771            png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
772         }
773
774         if (png_ptr->do_filter & PNG_FILTER_UP && png_ptr->up_row == NULL)
775         {
776            if (png_ptr->prev_row == NULL)
777            {
778               png_warning(png_ptr, "Can't add Up filter after starting");
779               png_ptr->do_filter &= ~PNG_FILTER_UP;
780            }
781            else
782            {
783               png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
784                  (png_ptr->rowbytes + 1));
785               png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
786            }
787         }
788
789         if (png_ptr->do_filter & PNG_FILTER_AVG && png_ptr->avg_row == NULL)
790         {
791            if (png_ptr->prev_row == NULL)
792            {
793               png_warning(png_ptr, "Can't add Average filter after starting");
794               png_ptr->do_filter &= ~PNG_FILTER_AVG;
795            }
796            else
797            {
798               png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
799                  (png_ptr->rowbytes + 1));
800               png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
801            }
802         }
803
804         if (png_ptr->do_filter & PNG_FILTER_PAETH &&
805             png_ptr->paeth_row == NULL)
806         {
807            if (png_ptr->prev_row == NULL)
808            {
809               png_warning(png_ptr, "Can't add Paeth filter after starting");
810               png_ptr->do_filter &= ~PNG_FILTER_PAETH;
811            }
812            else
813            {
814               png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
815                  (png_ptr->rowbytes + 1));
816               png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
817            }
818         }
819
820         if (png_ptr->do_filter == PNG_NO_FILTERS)
821            png_ptr->do_filter = PNG_FILTER_NONE;
822      }
823   }
824   else
825      png_error(png_ptr, "Unknown custom filter method");
826}
827
828/* This allows us to influence the way in which libpng chooses the "best"
829 * filter for the current scanline.  While the "minimum-sum-of-absolute-
830 * differences metric is relatively fast and effective, there is some
831 * question as to whether it can be improved upon by trying to keep the
832 * filtered data going to zlib more consistent, hopefully resulting in
833 * better compression.
834 */
835#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)      /* GRR 970116 */
836void
837png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
838   int num_weights, png_doublep filter_weights,
839   png_doublep filter_costs)
840{
841   int i;
842
843   png_debug(1, "in png_set_filter_heuristics\n");
844   if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)
845   {
846      png_warning(png_ptr, "Unknown filter heuristic method");
847      return;
848   }
849
850   if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT)
851   {
852      heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED;
853   }
854
855   if (num_weights < 0 || filter_weights == NULL ||
856      heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED)
857   {
858      num_weights = 0;
859   }
860
861   png_ptr->num_prev_filters = num_weights;
862   png_ptr->heuristic_method = heuristic_method;
863
864   if (num_weights > 0)
865   {
866      if (png_ptr->prev_filters == NULL)
867      {
868         png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
869            (png_uint_32)(sizeof(png_byte) * num_weights));
870
871         /* To make sure that the weighting starts out fairly */
872         for (i = 0; i < num_weights; i++)
873         {
874            png_ptr->prev_filters[i] = 255;
875         }
876      }
877
878      if (png_ptr->filter_weights == NULL)
879      {
880         png_ptr->filter_weights = (png_uint_16p) png_malloc(png_ptr,
881            (png_uint_32)(sizeof(png_uint_16) * num_weights));
882
883         png_ptr->inv_filter_weights = (png_uint_16p) png_malloc(png_ptr,
884            (png_uint_32)(sizeof(png_uint_16) * num_weights));
885
886         for (i = 0; i < num_weights; i++)
887         {
888            png_ptr->inv_filter_weights[i] =
889            png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
890         }
891      }
892
893      for (i = 0; i < num_weights; i++)
894      {
895         if (filter_weights[i] < 0.0)
896         {
897            png_ptr->inv_filter_weights[i] =
898            png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
899         }
900         else
901         {
902            png_ptr->inv_filter_weights[i] =
903               (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5);
904            png_ptr->filter_weights[i] =
905               (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5);
906         }
907      }
908   }
909
910   /* If, in the future, there are other filter methods, this would
911    * need to be based on png_ptr->filter.
912    */
913   if (png_ptr->filter_costs == NULL)
914   {
915      png_ptr->filter_costs = (png_uint_16p) png_malloc(png_ptr,
916         (png_uint_32)(sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
917
918      png_ptr->inv_filter_costs = (png_uint_16p) png_malloc(png_ptr,
919         (png_uint_32)(sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
920
921      for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
922      {
923         png_ptr->inv_filter_costs[i] =
924         png_ptr->filter_costs[i] = PNG_COST_FACTOR;
925      }
926   }
927
928   /* Here is where we set the relative costs of the different filters.  We
929    * should take the desired compression level into account when setting
930    * the costs, so that Paeth, for instance, has a high relative cost at low
931    * compression levels, while it has a lower relative cost at higher
932    * compression settings.  The filter types are in order of increasing
933    * relative cost, so it would be possible to do this with an algorithm.
934    */
935   for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
936   {
937      if (filter_costs == NULL || filter_costs[i] < 0.0)
938      {
939         png_ptr->inv_filter_costs[i] =
940         png_ptr->filter_costs[i] = PNG_COST_FACTOR;
941      }
942      else if (filter_costs[i] >= 1.0)
943      {
944         png_ptr->inv_filter_costs[i] =
945            (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5);
946         png_ptr->filter_costs[i] =
947            (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5);
948      }
949   }
950}
951#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
952
953void
954png_set_compression_level(png_structp png_ptr, int level)
955{
956   png_debug(1, "in png_set_compression_level\n");
957   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
958   png_ptr->zlib_level = level;
959}
960
961void
962png_set_compression_mem_level(png_structp png_ptr, int mem_level)
963{
964   png_debug(1, "in png_set_compression_mem_level\n");
965   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
966   png_ptr->zlib_mem_level = mem_level;
967}
968
969void
970png_set_compression_strategy(png_structp png_ptr, int strategy)
971{
972   png_debug(1, "in png_set_compression_strategy\n");
973   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
974   png_ptr->zlib_strategy = strategy;
975}
976
977void
978png_set_compression_window_bits(png_structp png_ptr, int window_bits)
979{
980   if (window_bits > 15)
981      png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
982   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
983   png_ptr->zlib_window_bits = window_bits;
984}
985
986void
987png_set_compression_method(png_structp png_ptr, int method)
988{
989   png_debug(1, "in png_set_compression_method\n");
990   if (method != 8)
991      png_warning(png_ptr, "Only compression method 8 is supported by PNG");
992   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
993   png_ptr->zlib_method = method;
994}
995
996void
997png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn)
998{
999   png_ptr->write_row_fn = write_row_fn;
1000}
1001
1002#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1003void
1004png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
1005   write_user_transform_fn)
1006{
1007   png_debug(1, "in png_set_write_user_transform_fn\n");
1008   png_ptr->transformations |= PNG_USER_TRANSFORM;
1009   png_ptr->write_user_transform_fn = write_user_transform_fn;
1010}
1011#endif
1012
Note: See TracBrowser for help on using the repository browser.