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! 54BPositionIO * 55get_pio(png_structp ppng) 56{ 57 BPositionIO *pio = NULL; 58 pio = static_cast<BPositionIO *>(png_get_io_ptr(ppng)); 59 return pio; 60} 61 62void 63pngcb_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 69void 70pngcb_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 76void 77pngcb_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 83void 84PrintPNGInfo(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 222int 223main(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