1 /*****************************************************************************/ 2 // bmpinfo 3 // Written by Michael Wilber, Haiku Translation Kit Team 4 // 5 // Version: 6 // 7 // bmpinfo is a command line program for displaying information about 8 // BMP images. 9 // 10 // 11 // This application and all source files used in its construction, except 12 // where noted, are licensed under the MIT License, and have been written 13 // and are: 14 // 15 // Copyright (c) 2003 Haiku Project 16 // 17 // Permission is hereby granted, free of charge, to any person obtaining a 18 // copy of this software and associated documentation files (the "Software"), 19 // to deal in the Software without restriction, including without limitation 20 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 21 // and/or sell copies of the Software, and to permit persons to whom the 22 // Software is furnished to do so, subject to the following conditions: 23 // 24 // The above copyright notice and this permission notice shall be included 25 // in all copies or substantial portions of the Software. 26 // 27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 28 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 32 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 33 // DEALINGS IN THE SOFTWARE. 34 /*****************************************************************************/ 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <ByteOrder.h> 39 #include <Catalog.h> 40 #include <File.h> 41 #include <TranslatorFormats.h> 42 #include <StorageDefs.h> 43 44 #undef B_TRANSLATION_CONTEXT 45 #define B_TRANSLATION_CONTEXT "bmpinfo" 46 47 #define BMP_NO_COMPRESS 0 48 #define BMP_RLE8_COMPRESS 1 49 #define BMP_RLE4_COMPRESS 2 50 51 struct BMPFileHeader { 52 // for both MS and OS/2 BMP formats 53 uint16 magic; // = 'BM' 54 uint32 fileSize; // file size in bytes 55 uint32 reserved; // equals 0 56 uint32 dataOffset; // file offset to actual image 57 }; 58 59 struct MSInfoHeader { 60 uint32 size; // size of this struct (40) 61 uint32 width; // bitmap width 62 uint32 height; // bitmap height 63 uint16 planes; // number of planes, always 1? 64 uint16 bitsperpixel; // bits per pixel, (1,4,8,16 or 24) 65 uint32 compression; // type of compression 66 uint32 imagesize; // size of image data if compressed 67 uint32 xpixperm; // horizontal pixels per meter 68 uint32 ypixperm; // vertical pixels per meter 69 uint32 colorsused; // number of actually used colors 70 uint32 colorsimportant; // number of important colors, zero = all 71 }; 72 73 struct OS2InfoHeader { 74 uint32 size; // size of this struct (12) 75 uint16 width; // bitmap width 76 uint16 height; // bitmap height 77 uint16 planes; // number of planes, always 1? 78 uint16 bitsperpixel; // bits per pixel, (1,4,8,16 or 24) 79 }; 80 81 void 82 print_bmp_info(BFile &file) 83 { 84 uint8 buf[40]; 85 BMPFileHeader fh; 86 87 ssize_t size = 14; 88 if (file.Read(buf, size) != size) { 89 printf(B_TRANSLATE("Error: unable to read BMP file header\n")); 90 return; 91 } 92 93 // convert fileHeader to host byte order 94 memcpy(&fh.magic, buf, 2); 95 memcpy(&fh.fileSize, buf + 2, 4); 96 memcpy(&fh.reserved, buf + 6, 4); 97 memcpy(&fh.dataOffset, buf + 10, 4); 98 swap_data(B_UINT16_TYPE, &fh.magic, sizeof(uint16), 99 B_SWAP_BENDIAN_TO_HOST); 100 swap_data(B_UINT32_TYPE, (reinterpret_cast<uint8 *> (&fh)) + 2, 101 12, B_SWAP_LENDIAN_TO_HOST); 102 103 printf(B_TRANSLATE("\nFile Header:\n")); 104 printf(B_TRANSLATE(" magic: 0x%.4x (should be: 0x424d)\n"), fh.magic); 105 printf(B_TRANSLATE(" file size: 0x%.8lx (%lu)\n"), fh.fileSize, 106 fh.fileSize); 107 printf(B_TRANSLATE(" reserved: 0x%.8lx (should be: 0x%.8x)\n"), 108 fh.reserved, 0); 109 printf(B_TRANSLATE("data offset: 0x%.8lx (%lu) (should be: >= 54 for MS " 110 "format and >= 26 for OS/2 format)\n"), fh.dataOffset, fh.dataOffset); 111 112 uint32 headersize = 0; 113 if (file.Read(&headersize, 4) != 4) { 114 printf(B_TRANSLATE("Error: unable to read info header size\n")); 115 return; 116 } 117 swap_data(B_UINT32_TYPE, &headersize, 4, B_SWAP_LENDIAN_TO_HOST); 118 119 if (headersize == sizeof(MSInfoHeader)) { 120 // MS format 121 MSInfoHeader msh; 122 msh.size = headersize; 123 if (file.Read(reinterpret_cast<uint8 *> (&msh) + 4, 36) != 36) { 124 printf(B_TRANSLATE("Error: unable to read entire MS info header\n")); 125 return; 126 } 127 128 // convert msheader to host byte order 129 swap_data(B_UINT32_TYPE, reinterpret_cast<uint8 *> (&msh) + 4, 36, 130 B_SWAP_LENDIAN_TO_HOST); 131 132 printf(B_TRANSLATE("\nMS Info Header:\n")); 133 printf(B_TRANSLATE(" header size: 0x%.8lx (%lu) (should be: " 134 "40)\n"), msh.size, msh.size); 135 printf(B_TRANSLATE(" width: %lu\n"), msh.width); 136 printf(B_TRANSLATE(" height: %lu\n"), msh.height); 137 printf(B_TRANSLATE(" planes: %u (should be: 1)\n"), 138 msh.planes); 139 printf(B_TRANSLATE(" bits per pixel: %u (should be: 1,4,8,16,24 or " 140 "32)\n"), msh.bitsperpixel); 141 if (msh.compression == BMP_NO_COMPRESS) 142 printf(B_TRANSLATE(" compression: none (%lu)\n"), 143 msh.compression); 144 else if (msh.compression == BMP_RLE8_COMPRESS) 145 printf(B_TRANSLATE(" compression: RLE8 (%lu)\n"), 146 msh.compression); 147 else if (msh.compression == BMP_RLE4_COMPRESS) 148 printf(B_TRANSLATE(" compression: RLE4 (%lu)\n"), 149 msh.compression); 150 else 151 printf(B_TRANSLATE(" compression: unknown (%lu)\n"), 152 msh.compression); 153 printf(B_TRANSLATE(" image size: 0x%.8lx (%lu)\n"), msh.imagesize, 154 msh.imagesize); 155 printf(B_TRANSLATE(" x pixels/meter: %lu\n"), msh.xpixperm); 156 printf(B_TRANSLATE(" y pixels/meter: %lu\n"), msh.ypixperm); 157 printf(B_TRANSLATE(" colors used: %lu\n"), msh.colorsused); 158 printf(B_TRANSLATE("colors important: %lu\n"), msh.colorsimportant); 159 160 } else if (headersize == sizeof(OS2InfoHeader)) { 161 // OS/2 format 162 163 OS2InfoHeader os2; 164 os2.size = headersize; 165 if (file.Read(reinterpret_cast<uint8 *> (&os2) + 4, 8) != 8) { 166 printf(B_TRANSLATE("Error: unable to read entire OS/2 info " 167 "header\n")); 168 return; 169 } 170 171 // convert os2header to host byte order 172 swap_data(B_UINT32_TYPE, reinterpret_cast<uint8 *> (&os2) + 4, 8, 173 B_SWAP_LENDIAN_TO_HOST); 174 175 printf(B_TRANSLATE("\nOS/2 Info Header:\n")); 176 printf(B_TRANSLATE(" header size: 0x%.8lx (%lu) (should be: 12)\n"), 177 os2.size, os2.size); 178 printf(B_TRANSLATE(" width: %u\n"), os2.width); 179 printf(B_TRANSLATE(" height: %u\n"), os2.height); 180 printf(B_TRANSLATE(" planes: %u (should be: 1)\n"), os2.planes); 181 printf(B_TRANSLATE("bits per pixel: %u (should be: 1,4,8 or 24)\n"), 182 os2.bitsperpixel); 183 184 } else 185 printf(B_TRANSLATE("Error: info header size (%lu) does not match MS " 186 "or OS/2 info header size\n"), headersize); 187 } 188 189 int 190 main(int argc, char **argv) 191 { 192 printf("\n"); 193 194 if (argc == 1) { 195 printf(B_TRANSLATE("bmpinfo - reports information about a BMP image " 196 "file\n")); 197 printf(B_TRANSLATE("\nUsage:\n")); 198 printf(B_TRANSLATE("bmpinfo filename.bmp\n")); 199 } 200 else { 201 BFile file; 202 203 for (int32 i = 1; i < argc; i++) { 204 if (file.SetTo(argv[i], B_READ_ONLY) != B_OK) 205 printf(B_TRANSLATE("\nError opening %s\n"), argv[i]); 206 else { 207 printf(B_TRANSLATE("\nBMP image information for: %s\n"), 208 argv[i]); 209 print_bmp_info(file); 210 } 211 } 212 213 } 214 215 printf("\n"); 216 217 return 0; 218 } 219 220