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