1
2/* pngget.c - retrieval of values from info struct
3 *
4 * Last changed in libpng 1.6.1 [March 28, 2013]
5 * Copyright (c) 1998-2013 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 * This code is released under the libpng license.
10 * For conditions of distribution and use, see the disclaimer
11 * and license in png.h
12 *
13 */
14
15#include "pngpriv.h"
16
17#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
18
19png_uint_32 PNGAPI
20png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr,
21    png_uint_32 flag)
22{
23   if (png_ptr != NULL && info_ptr != NULL)
24      return(info_ptr->valid & flag);
25
26   return(0);
27}
28
29png_size_t PNGAPI
30png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr)
31{
32   if (png_ptr != NULL && info_ptr != NULL)
33      return(info_ptr->rowbytes);
34
35   return(0);
36}
37
38#ifdef PNG_INFO_IMAGE_SUPPORTED
39png_bytepp PNGAPI
40png_get_rows(png_const_structrp png_ptr, png_const_inforp info_ptr)
41{
42   if (png_ptr != NULL && info_ptr != NULL)
43      return(info_ptr->row_pointers);
44
45   return(0);
46}
47#endif
48
49#ifdef PNG_EASY_ACCESS_SUPPORTED
50/* Easy access to info, added in libpng-0.99 */
51png_uint_32 PNGAPI
52png_get_image_width(png_const_structrp png_ptr, png_const_inforp info_ptr)
53{
54   if (png_ptr != NULL && info_ptr != NULL)
55      return info_ptr->width;
56
57   return (0);
58}
59
60png_uint_32 PNGAPI
61png_get_image_height(png_const_structrp png_ptr, png_const_inforp info_ptr)
62{
63   if (png_ptr != NULL && info_ptr != NULL)
64      return info_ptr->height;
65
66   return (0);
67}
68
69png_byte PNGAPI
70png_get_bit_depth(png_const_structrp png_ptr, png_const_inforp info_ptr)
71{
72   if (png_ptr != NULL && info_ptr != NULL)
73      return info_ptr->bit_depth;
74
75   return (0);
76}
77
78png_byte PNGAPI
79png_get_color_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
80{
81   if (png_ptr != NULL && info_ptr != NULL)
82      return info_ptr->color_type;
83
84   return (0);
85}
86
87png_byte PNGAPI
88png_get_filter_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
89{
90   if (png_ptr != NULL && info_ptr != NULL)
91      return info_ptr->filter_type;
92
93   return (0);
94}
95
96png_byte PNGAPI
97png_get_interlace_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
98{
99   if (png_ptr != NULL && info_ptr != NULL)
100      return info_ptr->interlace_type;
101
102   return (0);
103}
104
105png_byte PNGAPI
106png_get_compression_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
107{
108   if (png_ptr != NULL && info_ptr != NULL)
109      return info_ptr->compression_type;
110
111   return (0);
112}
113
114png_uint_32 PNGAPI
115png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
116   info_ptr)
117{
118#ifdef PNG_pHYs_SUPPORTED
119   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
120      {
121         png_debug1(1, "in %s retrieval function",
122             "png_get_x_pixels_per_meter");
123
124         if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
125            return (info_ptr->x_pixels_per_unit);
126      }
127#endif
128
129   return (0);
130}
131
132png_uint_32 PNGAPI
133png_get_y_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
134    info_ptr)
135{
136#ifdef PNG_pHYs_SUPPORTED
137   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
138   {
139      png_debug1(1, "in %s retrieval function",
140          "png_get_y_pixels_per_meter");
141
142      if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
143         return (info_ptr->y_pixels_per_unit);
144   }
145#endif
146
147   return (0);
148}
149
150png_uint_32 PNGAPI
151png_get_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr)
152{
153#ifdef PNG_pHYs_SUPPORTED
154   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
155   {
156      png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter");
157
158      if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER &&
159          info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit)
160         return (info_ptr->x_pixels_per_unit);
161   }
162#endif
163
164   return (0);
165}
166
167#ifdef PNG_FLOATING_POINT_SUPPORTED
168float PNGAPI
169png_get_pixel_aspect_ratio(png_const_structrp png_ptr, png_const_inforp
170   info_ptr)
171{
172#ifdef PNG_READ_pHYs_SUPPORTED
173   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
174   {
175      png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio");
176
177      if (info_ptr->x_pixels_per_unit != 0)
178         return ((float)((float)info_ptr->y_pixels_per_unit
179             /(float)info_ptr->x_pixels_per_unit));
180   }
181#else
182   PNG_UNUSED(png_ptr)
183   PNG_UNUSED(info_ptr)
184#endif
185
186   return ((float)0.0);
187}
188#endif
189
190#ifdef PNG_FIXED_POINT_SUPPORTED
191png_fixed_point PNGAPI
192png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr,
193    png_const_inforp info_ptr)
194{
195#ifdef PNG_READ_pHYs_SUPPORTED
196   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)
197       && info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0
198       && info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX
199       && info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX)
200   {
201      png_fixed_point res;
202
203      png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed");
204
205      /* The following casts work because a PNG 4 byte integer only has a valid
206       * range of 0..2^31-1; otherwise the cast might overflow.
207       */
208      if (png_muldiv(&res, (png_int_32)info_ptr->y_pixels_per_unit, PNG_FP_1,
209          (png_int_32)info_ptr->x_pixels_per_unit))
210         return res;
211   }
212#else
213   PNG_UNUSED(png_ptr)
214   PNG_UNUSED(info_ptr)
215#endif
216
217   return 0;
218}
219#endif
220
221png_int_32 PNGAPI
222png_get_x_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr)
223{
224#ifdef PNG_oFFs_SUPPORTED
225   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
226   {
227      png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns");
228
229      if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
230         return (info_ptr->x_offset);
231   }
232#endif
233
234   return (0);
235}
236
237png_int_32 PNGAPI
238png_get_y_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr)
239{
240#ifdef PNG_oFFs_SUPPORTED
241   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
242   {
243      png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns");
244
245      if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
246         return (info_ptr->y_offset);
247   }
248#endif
249
250   return (0);
251}
252
253png_int_32 PNGAPI
254png_get_x_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
255{
256#ifdef PNG_oFFs_SUPPORTED
257   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
258   {
259      png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels");
260
261      if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
262         return (info_ptr->x_offset);
263   }
264#endif
265
266   return (0);
267}
268
269png_int_32 PNGAPI
270png_get_y_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
271{
272#ifdef PNG_oFFs_SUPPORTED
273   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
274   {
275      png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels");
276
277      if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
278         return (info_ptr->y_offset);
279   }
280#endif
281
282   return (0);
283}
284
285#ifdef PNG_INCH_CONVERSIONS_SUPPORTED
286static png_uint_32
287ppi_from_ppm(png_uint_32 ppm)
288{
289#if 0
290   /* The conversion is *(2.54/100), in binary (32 digits):
291    * .00000110100000001001110101001001
292    */
293   png_uint_32 t1001, t1101;
294   ppm >>= 1;                  /* .1 */
295   t1001 = ppm + (ppm >> 3);   /* .1001 */
296   t1101 = t1001 + (ppm >> 1); /* .1101 */
297   ppm >>= 20;                 /* .000000000000000000001 */
298   t1101 += t1101 >> 15;       /* .1101000000000001101 */
299   t1001 >>= 11;               /* .000000000001001 */
300   t1001 += t1001 >> 12;       /* .000000000001001000000001001 */
301   ppm += t1001;               /* .000000000001001000001001001 */
302   ppm += t1101;               /* .110100000001001110101001001 */
303   return (ppm + 16) >> 5;/* .00000110100000001001110101001001 */
304#else
305   /* The argument is a PNG unsigned integer, so it is not permitted
306    * to be bigger than 2^31.
307    */
308   png_fixed_point result;
309   if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127,
310       5000))
311      return result;
312
313   /* Overflow. */
314   return 0;
315#endif
316}
317
318png_uint_32 PNGAPI
319png_get_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr)
320{
321   return ppi_from_ppm(png_get_pixels_per_meter(png_ptr, info_ptr));
322}
323
324png_uint_32 PNGAPI
325png_get_x_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr)
326{
327   return ppi_from_ppm(png_get_x_pixels_per_meter(png_ptr, info_ptr));
328}
329
330png_uint_32 PNGAPI
331png_get_y_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr)
332{
333   return ppi_from_ppm(png_get_y_pixels_per_meter(png_ptr, info_ptr));
334}
335
336#ifdef PNG_FIXED_POINT_SUPPORTED
337static png_fixed_point
338png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns)
339{
340   /* Convert from metres * 1,000,000 to inches * 100,000, meters to
341    * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127.
342    * Notice that this can overflow - a warning is output and 0 is
343    * returned.
344    */
345   return png_muldiv_warn(png_ptr, microns, 500, 127);
346}
347
348png_fixed_point PNGAPI
349png_get_x_offset_inches_fixed(png_const_structrp png_ptr,
350    png_const_inforp info_ptr)
351{
352   return png_fixed_inches_from_microns(png_ptr,
353       png_get_x_offset_microns(png_ptr, info_ptr));
354}
355#endif
356
357#ifdef PNG_FIXED_POINT_SUPPORTED
358png_fixed_point PNGAPI
359png_get_y_offset_inches_fixed(png_const_structrp png_ptr,
360    png_const_inforp info_ptr)
361{
362   return png_fixed_inches_from_microns(png_ptr,
363       png_get_y_offset_microns(png_ptr, info_ptr));
364}
365#endif
366
367#ifdef PNG_FLOATING_POINT_SUPPORTED
368float PNGAPI
369png_get_x_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr)
370{
371   /* To avoid the overflow do the conversion directly in floating
372    * point.
373    */
374   return (float)(png_get_x_offset_microns(png_ptr, info_ptr) * .00003937);
375}
376#endif
377
378#ifdef PNG_FLOATING_POINT_SUPPORTED
379float PNGAPI
380png_get_y_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr)
381{
382   /* To avoid the overflow do the conversion directly in floating
383    * point.
384    */
385   return (float)(png_get_y_offset_microns(png_ptr, info_ptr) * .00003937);
386}
387#endif
388
389#ifdef PNG_pHYs_SUPPORTED
390png_uint_32 PNGAPI
391png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr,
392    png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
393{
394   png_uint_32 retval = 0;
395
396   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
397   {
398      png_debug1(1, "in %s retrieval function", "pHYs");
399
400      if (res_x != NULL)
401      {
402         *res_x = info_ptr->x_pixels_per_unit;
403         retval |= PNG_INFO_pHYs;
404      }
405
406      if (res_y != NULL)
407      {
408         *res_y = info_ptr->y_pixels_per_unit;
409         retval |= PNG_INFO_pHYs;
410      }
411
412      if (unit_type != NULL)
413      {
414         *unit_type = (int)info_ptr->phys_unit_type;
415         retval |= PNG_INFO_pHYs;
416
417         if (*unit_type == 1)
418         {
419            if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50);
420            if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50);
421         }
422      }
423   }
424
425   return (retval);
426}
427#endif /* PNG_pHYs_SUPPORTED */
428#endif  /* PNG_INCH_CONVERSIONS_SUPPORTED */
429
430/* png_get_channels really belongs in here, too, but it's been around longer */
431
432#endif  /* PNG_EASY_ACCESS_SUPPORTED */
433
434
435png_byte PNGAPI
436png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr)
437{
438   if (png_ptr != NULL && info_ptr != NULL)
439      return(info_ptr->channels);
440
441   return (0);
442}
443
444#ifdef PNG_READ_SUPPORTED
445png_const_bytep PNGAPI
446png_get_signature(png_const_structrp png_ptr, png_const_inforp info_ptr)
447{
448   if (png_ptr != NULL && info_ptr != NULL)
449      return(info_ptr->signature);
450
451   return (NULL);
452}
453#endif
454
455#ifdef PNG_bKGD_SUPPORTED
456png_uint_32 PNGAPI
457png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
458   png_color_16p *background)
459{
460   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)
461       && background != NULL)
462   {
463      png_debug1(1, "in %s retrieval function", "bKGD");
464
465      *background = &(info_ptr->background);
466      return (PNG_INFO_bKGD);
467   }
468
469   return (0);
470}
471#endif
472
473#ifdef PNG_cHRM_SUPPORTED
474/* The XYZ APIs were added in 1.5.5 to take advantage of the code added at the
475 * same time to correct the rgb grayscale coefficient defaults obtained from the
476 * cHRM chunk in 1.5.4
477 */
478#  ifdef PNG_FLOATING_POINT_SUPPORTED
479png_uint_32 PNGAPI
480png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
481    double *white_x, double *white_y, double *red_x, double *red_y,
482    double *green_x, double *green_y, double *blue_x, double *blue_y)
483{
484   /* Quiet API change: this code used to only return the end points if a cHRM
485    * chunk was present, but the end points can also come from iCCP or sRGB
486    * chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and
487    * the png_set_ APIs merely check that set end points are mutually
488    * consistent.
489    */
490   if (png_ptr != NULL && info_ptr != NULL &&
491      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS))
492   {
493      png_debug1(1, "in %s retrieval function", "cHRM");
494
495      if (white_x != NULL)
496         *white_x = png_float(png_ptr,
497            info_ptr->colorspace.end_points_xy.whitex, "cHRM white X");
498      if (white_y != NULL)
499         *white_y = png_float(png_ptr,
500            info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y");
501      if (red_x != NULL)
502         *red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx,
503            "cHRM red X");
504      if (red_y != NULL)
505         *red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy,
506            "cHRM red Y");
507      if (green_x != NULL)
508         *green_x = png_float(png_ptr,
509            info_ptr->colorspace.end_points_xy.greenx, "cHRM green X");
510      if (green_y != NULL)
511         *green_y = png_float(png_ptr,
512            info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y");
513      if (blue_x != NULL)
514         *blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex,
515            "cHRM blue X");
516      if (blue_y != NULL)
517         *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey,
518            "cHRM blue Y");
519      return (PNG_INFO_cHRM);
520   }
521
522   return (0);
523}
524
525png_uint_32 PNGAPI
526png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
527   double *red_X, double *red_Y, double *red_Z, double *green_X,
528   double *green_Y, double *green_Z, double *blue_X, double *blue_Y,
529   double *blue_Z)
530{
531   if (png_ptr != NULL && info_ptr != NULL &&
532      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS))
533   {
534      png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)");
535
536      if (red_X != NULL)
537         *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X,
538            "cHRM red X");
539      if (red_Y != NULL)
540         *red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y,
541            "cHRM red Y");
542      if (red_Z != NULL)
543         *red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z,
544            "cHRM red Z");
545      if (green_X != NULL)
546         *green_X = png_float(png_ptr,
547            info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X");
548      if (green_Y != NULL)
549         *green_Y = png_float(png_ptr,
550            info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y");
551      if (green_Z != NULL)
552         *green_Z = png_float(png_ptr,
553            info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z");
554      if (blue_X != NULL)
555         *blue_X = png_float(png_ptr,
556            info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X");
557      if (blue_Y != NULL)
558         *blue_Y = png_float(png_ptr,
559            info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y");
560      if (blue_Z != NULL)
561         *blue_Z = png_float(png_ptr,
562            info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z");
563      return (PNG_INFO_cHRM);
564   }
565
566   return (0);
567}
568#  endif
569
570#  ifdef PNG_FIXED_POINT_SUPPORTED
571png_uint_32 PNGAPI
572png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
573    png_fixed_point *int_red_X, png_fixed_point *int_red_Y,
574    png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
575    png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
576    png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
577    png_fixed_point *int_blue_Z)
578{
579   if (png_ptr != NULL && info_ptr != NULL &&
580      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS))
581   {
582      png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
583
584      if (int_red_X != NULL)
585         *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X;
586      if (int_red_Y != NULL)
587         *int_red_Y = info_ptr->colorspace.end_points_XYZ.red_Y;
588      if (int_red_Z != NULL)
589         *int_red_Z = info_ptr->colorspace.end_points_XYZ.red_Z;
590      if (int_green_X != NULL)
591         *int_green_X = info_ptr->colorspace.end_points_XYZ.green_X;
592      if (int_green_Y != NULL)
593         *int_green_Y = info_ptr->colorspace.end_points_XYZ.green_Y;
594      if (int_green_Z != NULL)
595         *int_green_Z = info_ptr->colorspace.end_points_XYZ.green_Z;
596      if (int_blue_X != NULL)
597         *int_blue_X = info_ptr->colorspace.end_points_XYZ.blue_X;
598      if (int_blue_Y != NULL)
599         *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y;
600      if (int_blue_Z != NULL)
601         *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z;
602      return (PNG_INFO_cHRM);
603   }
604
605   return (0);
606}
607
608png_uint_32 PNGAPI
609png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
610    png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x,
611    png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y,
612    png_fixed_point *blue_x, png_fixed_point *blue_y)
613{
614   png_debug1(1, "in %s retrieval function", "cHRM");
615
616   if (png_ptr != NULL && info_ptr != NULL &&
617      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS))
618   {
619      if (white_x != NULL)
620         *white_x = info_ptr->colorspace.end_points_xy.whitex;
621      if (white_y != NULL)
622         *white_y = info_ptr->colorspace.end_points_xy.whitey;
623      if (red_x != NULL)
624         *red_x = info_ptr->colorspace.end_points_xy.redx;
625      if (red_y != NULL)
626         *red_y = info_ptr->colorspace.end_points_xy.redy;
627      if (green_x != NULL)
628         *green_x = info_ptr->colorspace.end_points_xy.greenx;
629      if (green_y != NULL)
630         *green_y = info_ptr->colorspace.end_points_xy.greeny;
631      if (blue_x != NULL)
632         *blue_x = info_ptr->colorspace.end_points_xy.bluex;
633      if (blue_y != NULL)
634         *blue_y = info_ptr->colorspace.end_points_xy.bluey;
635      return (PNG_INFO_cHRM);
636   }
637
638   return (0);
639}
640#  endif
641#endif
642
643#ifdef PNG_gAMA_SUPPORTED
644#  ifdef PNG_FIXED_POINT_SUPPORTED
645png_uint_32 PNGAPI
646png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
647    png_fixed_point *file_gamma)
648{
649   png_debug1(1, "in %s retrieval function", "gAMA");
650
651   if (png_ptr != NULL && info_ptr != NULL &&
652      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) &&
653      file_gamma != NULL)
654   {
655      *file_gamma = info_ptr->colorspace.gamma;
656      return (PNG_INFO_gAMA);
657   }
658
659   return (0);
660}
661#  endif
662
663#  ifdef PNG_FLOATING_POINT_SUPPORTED
664png_uint_32 PNGAPI
665png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr,
666    double *file_gamma)
667{
668   png_debug1(1, "in %s retrieval function", "gAMA(float)");
669
670   if (png_ptr != NULL && info_ptr != NULL &&
671      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) &&
672      file_gamma != NULL)
673   {
674      *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma,
675         "png_get_gAMA");
676      return (PNG_INFO_gAMA);
677   }
678
679   return (0);
680}
681#  endif
682#endif
683
684#ifdef PNG_sRGB_SUPPORTED
685png_uint_32 PNGAPI
686png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr,
687    int *file_srgb_intent)
688{
689   png_debug1(1, "in %s retrieval function", "sRGB");
690
691   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)
692       && file_srgb_intent != NULL)
693   {
694      *file_srgb_intent = info_ptr->colorspace.rendering_intent;
695      return (PNG_INFO_sRGB);
696   }
697
698   return (0);
699}
700#endif
701
702#ifdef PNG_iCCP_SUPPORTED
703png_uint_32 PNGAPI
704png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
705    png_charpp name, int *compression_type,
706    png_bytepp profile, png_uint_32 *proflen)
707{
708   png_debug1(1, "in %s retrieval function", "iCCP");
709
710   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)
711       && name != NULL && compression_type != NULL && profile != NULL &&
712		 proflen != NULL)
713   {
714      *name = info_ptr->iccp_name;
715      *profile = info_ptr->iccp_profile;
716      *proflen = png_get_uint_32(info_ptr->iccp_profile);
717      /* This is somewhat irrelevant since the profile data returned has
718       * actually been uncompressed.
719       */
720      *compression_type = PNG_COMPRESSION_TYPE_BASE;
721      return (PNG_INFO_iCCP);
722   }
723
724   return (0);
725}
726#endif
727
728#ifdef PNG_sPLT_SUPPORTED
729int PNGAPI
730png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr,
731    png_sPLT_tpp spalettes)
732{
733   if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL)
734   {
735      *spalettes = info_ptr->splt_palettes;
736      return info_ptr->splt_palettes_num;
737   }
738
739   return (0);
740}
741#endif
742
743#ifdef PNG_hIST_SUPPORTED
744png_uint_32 PNGAPI
745png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
746    png_uint_16p *hist)
747{
748   png_debug1(1, "in %s retrieval function", "hIST");
749
750   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)
751       && hist != NULL)
752   {
753      *hist = info_ptr->hist;
754      return (PNG_INFO_hIST);
755   }
756
757   return (0);
758}
759#endif
760
761png_uint_32 PNGAPI
762png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr,
763    png_uint_32 *width, png_uint_32 *height, int *bit_depth,
764    int *color_type, int *interlace_type, int *compression_type,
765    int *filter_type)
766{
767   png_debug1(1, "in %s retrieval function", "IHDR");
768
769   if (png_ptr == NULL || info_ptr == NULL || width == NULL ||
770       height == NULL || bit_depth == NULL || color_type == NULL)
771      return (0);
772
773   *width = info_ptr->width;
774   *height = info_ptr->height;
775   *bit_depth = info_ptr->bit_depth;
776   *color_type = info_ptr->color_type;
777
778   if (compression_type != NULL)
779      *compression_type = info_ptr->compression_type;
780
781   if (filter_type != NULL)
782      *filter_type = info_ptr->filter_type;
783
784   if (interlace_type != NULL)
785      *interlace_type = info_ptr->interlace_type;
786
787   /* This is redundant if we can be sure that the info_ptr values were all
788    * assigned in png_set_IHDR().  We do the check anyhow in case an
789    * application has ignored our advice not to mess with the members
790    * of info_ptr directly.
791    */
792   png_check_IHDR(png_ptr, info_ptr->width, info_ptr->height,
793       info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
794       info_ptr->compression_type, info_ptr->filter_type);
795
796   return (1);
797}
798
799#ifdef PNG_oFFs_SUPPORTED
800png_uint_32 PNGAPI
801png_get_oFFs(png_const_structrp png_ptr, png_const_inforp info_ptr,
802    png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)
803{
804   png_debug1(1, "in %s retrieval function", "oFFs");
805
806   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)
807       && offset_x != NULL && offset_y != NULL && unit_type != NULL)
808   {
809      *offset_x = info_ptr->x_offset;
810      *offset_y = info_ptr->y_offset;
811      *unit_type = (int)info_ptr->offset_unit_type;
812      return (PNG_INFO_oFFs);
813   }
814
815   return (0);
816}
817#endif
818
819#ifdef PNG_pCAL_SUPPORTED
820png_uint_32 PNGAPI
821png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
822    png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams,
823    png_charp *units, png_charpp *params)
824{
825   png_debug1(1, "in %s retrieval function", "pCAL");
826
827   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)
828       && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
829       nparams != NULL && units != NULL && params != NULL)
830   {
831      *purpose = info_ptr->pcal_purpose;
832      *X0 = info_ptr->pcal_X0;
833      *X1 = info_ptr->pcal_X1;
834      *type = (int)info_ptr->pcal_type;
835      *nparams = (int)info_ptr->pcal_nparams;
836      *units = info_ptr->pcal_units;
837      *params = info_ptr->pcal_params;
838      return (PNG_INFO_pCAL);
839   }
840
841   return (0);
842}
843#endif
844
845#ifdef PNG_sCAL_SUPPORTED
846#  ifdef PNG_FIXED_POINT_SUPPORTED
847#    if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \
848         defined(PNG_FLOATING_POINT_SUPPORTED)
849png_uint_32 PNGAPI
850png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
851    int *unit, png_fixed_point *width, png_fixed_point *height)
852{
853   if (png_ptr != NULL && info_ptr != NULL &&
854       (info_ptr->valid & PNG_INFO_sCAL))
855   {
856      *unit = info_ptr->scal_unit;
857      /*TODO: make this work without FP support; the API is currently eliminated
858       * if neither floating point APIs nor internal floating point arithmetic
859       * are enabled.
860       */
861      *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width");
862      *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height),
863         "sCAL height");
864      return (PNG_INFO_sCAL);
865   }
866
867   return(0);
868}
869#    endif /* FLOATING_ARITHMETIC */
870#  endif /* FIXED_POINT */
871#  ifdef PNG_FLOATING_POINT_SUPPORTED
872png_uint_32 PNGAPI
873png_get_sCAL(png_const_structrp png_ptr, png_const_inforp info_ptr,
874    int *unit, double *width, double *height)
875{
876   if (png_ptr != NULL && info_ptr != NULL &&
877       (info_ptr->valid & PNG_INFO_sCAL))
878   {
879      *unit = info_ptr->scal_unit;
880      *width = atof(info_ptr->scal_s_width);
881      *height = atof(info_ptr->scal_s_height);
882      return (PNG_INFO_sCAL);
883   }
884
885   return(0);
886}
887#  endif /* FLOATING POINT */
888png_uint_32 PNGAPI
889png_get_sCAL_s(png_const_structrp png_ptr, png_const_inforp info_ptr,
890    int *unit, png_charpp width, png_charpp height)
891{
892   if (png_ptr != NULL && info_ptr != NULL &&
893       (info_ptr->valid & PNG_INFO_sCAL))
894   {
895      *unit = info_ptr->scal_unit;
896      *width = info_ptr->scal_s_width;
897      *height = info_ptr->scal_s_height;
898      return (PNG_INFO_sCAL);
899   }
900
901   return(0);
902}
903#endif /* sCAL */
904
905#ifdef PNG_pHYs_SUPPORTED
906png_uint_32 PNGAPI
907png_get_pHYs(png_const_structrp png_ptr, png_const_inforp info_ptr,
908    png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
909{
910   png_uint_32 retval = 0;
911
912   png_debug1(1, "in %s retrieval function", "pHYs");
913
914   if (png_ptr != NULL && info_ptr != NULL &&
915       (info_ptr->valid & PNG_INFO_pHYs))
916   {
917      if (res_x != NULL)
918      {
919         *res_x = info_ptr->x_pixels_per_unit;
920         retval |= PNG_INFO_pHYs;
921      }
922
923      if (res_y != NULL)
924      {
925         *res_y = info_ptr->y_pixels_per_unit;
926         retval |= PNG_INFO_pHYs;
927      }
928
929      if (unit_type != NULL)
930      {
931         *unit_type = (int)info_ptr->phys_unit_type;
932         retval |= PNG_INFO_pHYs;
933      }
934   }
935
936   return (retval);
937}
938#endif /* pHYs */
939
940png_uint_32 PNGAPI
941png_get_PLTE(png_const_structrp png_ptr, png_inforp info_ptr,
942    png_colorp *palette, int *num_palette)
943{
944   png_debug1(1, "in %s retrieval function", "PLTE");
945
946   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE)
947       && palette != NULL)
948   {
949      *palette = info_ptr->palette;
950      *num_palette = info_ptr->num_palette;
951      png_debug1(3, "num_palette = %d", *num_palette);
952      return (PNG_INFO_PLTE);
953   }
954
955   return (0);
956}
957
958#ifdef PNG_sBIT_SUPPORTED
959png_uint_32 PNGAPI
960png_get_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
961    png_color_8p *sig_bit)
962{
963   png_debug1(1, "in %s retrieval function", "sBIT");
964
965   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)
966       && sig_bit != NULL)
967   {
968      *sig_bit = &(info_ptr->sig_bit);
969      return (PNG_INFO_sBIT);
970   }
971
972   return (0);
973}
974#endif
975
976#ifdef PNG_TEXT_SUPPORTED
977int PNGAPI
978png_get_text(png_const_structrp png_ptr, png_inforp info_ptr,
979    png_textp *text_ptr, int *num_text)
980{
981   if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0)
982   {
983      png_debug1(1, "in 0x%lx retrieval function",
984         (unsigned long)png_ptr->chunk_name);
985
986      if (text_ptr != NULL)
987         *text_ptr = info_ptr->text;
988
989      if (num_text != NULL)
990         *num_text = info_ptr->num_text;
991
992      return info_ptr->num_text;
993   }
994
995   if (num_text != NULL)
996      *num_text = 0;
997
998   return(0);
999}
1000#endif
1001
1002#ifdef PNG_tIME_SUPPORTED
1003png_uint_32 PNGAPI
1004png_get_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
1005    png_timep *mod_time)
1006{
1007   png_debug1(1, "in %s retrieval function", "tIME");
1008
1009   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)
1010       && mod_time != NULL)
1011   {
1012      *mod_time = &(info_ptr->mod_time);
1013      return (PNG_INFO_tIME);
1014   }
1015
1016   return (0);
1017}
1018#endif
1019
1020#ifdef PNG_tRNS_SUPPORTED
1021png_uint_32 PNGAPI
1022png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr,
1023    png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)
1024{
1025   png_uint_32 retval = 0;
1026   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1027   {
1028      png_debug1(1, "in %s retrieval function", "tRNS");
1029
1030      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1031      {
1032         if (trans_alpha != NULL)
1033         {
1034            *trans_alpha = info_ptr->trans_alpha;
1035            retval |= PNG_INFO_tRNS;
1036         }
1037
1038         if (trans_color != NULL)
1039            *trans_color = &(info_ptr->trans_color);
1040      }
1041
1042      else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */
1043      {
1044         if (trans_color != NULL)
1045         {
1046            *trans_color = &(info_ptr->trans_color);
1047            retval |= PNG_INFO_tRNS;
1048         }
1049
1050         if (trans_alpha != NULL)
1051            *trans_alpha = NULL;
1052      }
1053
1054      if (num_trans != NULL)
1055      {
1056         *num_trans = info_ptr->num_trans;
1057         retval |= PNG_INFO_tRNS;
1058      }
1059   }
1060
1061   return (retval);
1062}
1063#endif
1064
1065#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
1066int PNGAPI
1067png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr,
1068    png_unknown_chunkpp unknowns)
1069{
1070   if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL)
1071   {
1072      *unknowns = info_ptr->unknown_chunks;
1073      return info_ptr->unknown_chunks_num;
1074   }
1075
1076   return (0);
1077}
1078#endif
1079
1080#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
1081png_byte PNGAPI
1082png_get_rgb_to_gray_status (png_const_structrp png_ptr)
1083{
1084   return (png_byte)(png_ptr ? png_ptr->rgb_to_gray_status : 0);
1085}
1086#endif
1087
1088#ifdef PNG_USER_CHUNKS_SUPPORTED
1089png_voidp PNGAPI
1090png_get_user_chunk_ptr(png_const_structrp png_ptr)
1091{
1092   return (png_ptr ? png_ptr->user_chunk_ptr : NULL);
1093}
1094#endif
1095
1096png_size_t PNGAPI
1097png_get_compression_buffer_size(png_const_structrp png_ptr)
1098{
1099   if (png_ptr == NULL)
1100      return 0;
1101
1102#  ifdef PNG_WRITE_SUPPORTED
1103      if (png_ptr->mode & PNG_IS_READ_STRUCT)
1104#  endif
1105   {
1106#     ifdef PNG_SEQUENTIAL_READ_SUPPORTED
1107         return png_ptr->IDAT_read_size;
1108#     else
1109         return PNG_IDAT_READ_SIZE;
1110#     endif
1111   }
1112
1113#  ifdef PNG_WRITE_SUPPORTED
1114      else
1115         return png_ptr->zbuffer_size;
1116#  endif
1117}
1118
1119#ifdef PNG_SET_USER_LIMITS_SUPPORTED
1120/* These functions were added to libpng 1.2.6 and were enabled
1121 * by default in libpng-1.4.0 */
1122png_uint_32 PNGAPI
1123png_get_user_width_max (png_const_structrp png_ptr)
1124{
1125   return (png_ptr ? png_ptr->user_width_max : 0);
1126}
1127
1128png_uint_32 PNGAPI
1129png_get_user_height_max (png_const_structrp png_ptr)
1130{
1131   return (png_ptr ? png_ptr->user_height_max : 0);
1132}
1133
1134/* This function was added to libpng 1.4.0 */
1135png_uint_32 PNGAPI
1136png_get_chunk_cache_max (png_const_structrp png_ptr)
1137{
1138   return (png_ptr ? png_ptr->user_chunk_cache_max : 0);
1139}
1140
1141/* This function was added to libpng 1.4.1 */
1142png_alloc_size_t PNGAPI
1143png_get_chunk_malloc_max (png_const_structrp png_ptr)
1144{
1145   return (png_ptr ? png_ptr->user_chunk_malloc_max : 0);
1146}
1147#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
1148
1149/* These functions were added to libpng 1.4.0 */
1150#ifdef PNG_IO_STATE_SUPPORTED
1151png_uint_32 PNGAPI
1152png_get_io_state (png_const_structrp png_ptr)
1153{
1154   return png_ptr->io_state;
1155}
1156
1157png_uint_32 PNGAPI
1158png_get_io_chunk_type (png_const_structrp png_ptr)
1159{
1160   return png_ptr->chunk_name;
1161}
1162#endif /* ?PNG_IO_STATE_SUPPORTED */
1163
1164#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
1165#  ifdef PNG_GET_PALETTE_MAX_SUPPORTED
1166int PNGAPI
1167png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr)
1168{
1169   if (png_ptr != NULL && info_ptr != NULL)
1170      return png_ptr->num_palette_max;
1171
1172   return (-1);
1173}
1174#  endif
1175#endif
1176
1177#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
1178