1 /*****************************************************************************/
2 // pnginfo
3 // Written by Michael Wilber, Haiku Translation Kit Team
4 //
5 // Version:
6 //
7 // pnginfo is a command line program for displaying text information about
8 // PNG images.
9 //
10 // This application and all source files used in its construction, except
11 // where noted, are licensed under the MIT License, and have been written
12 // and are:
13 //
14 // Copyright (c) 2004 Haiku Project
15 //
16 // Permission is hereby granted, free of charge, to any person obtaining a
17 // copy of this software and associated documentation files (the "Software"),
18 // to deal in the Software without restriction, including without limitation
19 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 // and/or sell copies of the Software, and to permit persons to whom the
21 // Software is furnished to do so, subject to the following conditions:
22 //
23 // The above copyright notice and this permission notice shall be included
24 // in all copies or substantial portions of the Software.
25 //
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
29 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
31 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32 // DEALINGS IN THE SOFTWARE.
33 /*****************************************************************************/
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <png.h>
38 #include <ByteOrder.h>
39 #include <File.h>
40 #include <TranslatorFormats.h>
41 #include <StorageDefs.h>
42
43 /* The png_jmpbuf() macro, used in error handling, became available in
44 * libpng version 1.0.6. If you want to be able to run your code with older
45 * versions of libpng, you must define the macro yourself (but only if it
46 * is not already defined by libpng!).
47 */
48
49 #ifndef png_jmpbuf
50 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
51 #endif
52
53 //// libpng Callback functions!
54 BPositionIO *
get_pio(png_structp ppng)55 get_pio(png_structp ppng)
56 {
57 BPositionIO *pio = NULL;
58 pio = static_cast<BPositionIO *>(png_get_io_ptr(ppng));
59 return pio;
60 }
61
62 void
pngcb_read_data(png_structp ppng,png_bytep pdata,png_size_t length)63 pngcb_read_data(png_structp ppng, png_bytep pdata, png_size_t length)
64 {
65 BPositionIO *pio = get_pio(ppng);
66 pio->Read(pdata, static_cast<size_t>(length));
67 }
68
69 void
pngcb_write_data(png_structp ppng,png_bytep pdata,png_size_t length)70 pngcb_write_data(png_structp ppng, png_bytep pdata, png_size_t length)
71 {
72 BPositionIO *pio = get_pio(ppng);
73 pio->Write(pdata, static_cast<size_t>(length));
74 }
75
76 void
pngcb_flush_data(png_structp ppng)77 pngcb_flush_data(png_structp ppng)
78 {
79 // I don't think I really need to do anything here
80 }
81 //// End: libpng Callback functions
82
83 void
PrintPNGInfo(const char * path)84 PrintPNGInfo(const char *path)
85 {
86 printf("\n--- %s ---\n", path);
87
88 BFile *pfile;
89 pfile = new BFile(path, B_READ_ONLY);
90 if (!pfile || pfile->InitCheck() != B_OK) {
91 printf("Error: unable to open the file\n");
92 return;
93 }
94 BPositionIO *pio = static_cast<BPositionIO *>(pfile);
95
96 const int32 kSigSize = 8;
97 uint8 buf[kSigSize];
98 if (pio->Read(buf, kSigSize) != kSigSize) {
99 printf("Error: unable to read PNG signature\n");
100 return;
101 }
102 if (!png_check_sig(buf, kSigSize)) {
103 // if first 8 bytes of stream don't match PNG signature bail
104 printf("Error: file doesn't begin with PNG signature\n");
105 return;
106 }
107
108 // use libpng to get info about the file
109 png_structp ppng = NULL;
110 png_infop pinfo = NULL;
111 while (ppng == NULL) {
112 // create PNG read pointer with default error handling routines
113 ppng = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
114 if (!ppng)
115 break;
116 // alocate / init memory for image information
117 pinfo = png_create_info_struct(ppng);
118 if (!pinfo)
119 break;
120 // set error handling
121 if (setjmp(png_jmpbuf(ppng))) {
122 // When an error occurs in libpng, it uses
123 // the longjmp function to continue execution
124 // from this point
125 printf("Error: error in libpng function\n");
126 break;
127 }
128
129 // set read callback function
130 png_set_read_fn(ppng, static_cast<void *>(pio), pngcb_read_data);
131
132 // Read in PNG image info
133 png_set_sig_bytes(ppng, 8);
134 png_read_info(ppng, pinfo);
135
136 png_uint_32 width, height;
137 int bit_depth, color_type, interlace_type, compression_type, filter_type;
138 png_get_IHDR(ppng, pinfo, &width, &height, &bit_depth, &color_type,
139 &interlace_type, &compression_type, &filter_type);
140
141 printf(" width: %lu\n", width);
142 printf(" height: %lu\n", height);
143 printf(" row bytes: %lu\n", pinfo->rowbytes);
144 printf("bit depth (bits/channel): %d\n", bit_depth);
145 printf(" channels: %d\n", pinfo->channels);
146 printf("pixel depth (bits/pixel): %d\n", pinfo->pixel_depth);
147 printf(" color type: ");
148 const char *desc = NULL;
149 switch (color_type) {
150 case PNG_COLOR_TYPE_GRAY:
151 desc = "Grayscale";
152 break;
153 case PNG_COLOR_TYPE_PALETTE:
154 desc = "Palette";
155 break;
156 case PNG_COLOR_TYPE_RGB:
157 desc = "RGB";
158 break;
159 case PNG_COLOR_TYPE_RGB_ALPHA:
160 desc = "RGB + Alpha";
161 break;
162 case PNG_COLOR_TYPE_GRAY_ALPHA:
163 desc = "Grayscale + Alpha";
164 break;
165 default:
166 desc = "Unknown";
167 break;
168 }
169 printf("%s (%d)\n", desc, color_type);
170
171 printf(" interlacing: ");
172 switch (interlace_type) {
173 case PNG_INTERLACE_NONE:
174 desc = "None";
175 break;
176 case PNG_INTERLACE_ADAM7:
177 desc = "Adam7";
178 break;
179 default:
180 desc = "Unknown";
181 break;
182 }
183 printf("%s (%d)\n", desc, interlace_type);
184
185 printf(" compression type: ");
186 switch (compression_type) {
187 case PNG_COMPRESSION_TYPE_DEFAULT:
188 desc = "Default: Deflate method 8, 32K window";
189 break;
190 default:
191 desc = "Unknown";
192 break;
193 }
194 printf("%s (%d)\n", desc, compression_type);
195
196 printf(" filter type: ");
197 switch (filter_type) {
198 case PNG_FILTER_TYPE_DEFAULT:
199 desc = "Single row per-byte";
200 break;
201 case PNG_INTRAPIXEL_DIFFERENCING:
202 desc = "Intrapixel Differencing [for MNG files]";
203 break;
204 default:
205 desc = "Unknown";
206 break;
207 }
208 printf("%s (%d)\n", desc, filter_type);
209 }
210 if (ppng) {
211 // free PNG handle / info structures
212 if (!pinfo)
213 png_destroy_read_struct(&ppng, png_infopp_NULL, png_infopp_NULL);
214 else
215 png_destroy_read_struct(&ppng, &pinfo, png_infopp_NULL);
216 }
217
218 delete pfile;
219 pfile = NULL;
220 }
221
222 int
main(int argc,char ** argv)223 main(int argc, char **argv)
224 {
225 if (argc == 1) {
226 printf("\npnginfo - reports information about PNG images\n");
227 printf("\nUsage:\n");
228 printf("pnginfo [options] filename.png\n\n");
229 }
230 else {
231 int32 first = 1;
232 for (int32 i = first; i < argc; i++)
233 PrintPNGInfo(argv[i]);
234 }
235
236 printf("\n");
237
238 return 0;
239 }
240
241