xref: /haiku/src/tools/translation/pnginfo/pnginfo.cpp (revision 268f99dd7dc4bd7474a8bd2742d3f1ec1de6752a)
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