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