1 /*****************************************************************************/ 2 // bmpinfo 3 // Written by Michael Wilber, OBOS 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 OpenBeOS 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 <File.h> 40 #include <TranslatorFormats.h> 41 #include <StorageDefs.h> 42 43 #define BMP_NO_COMPRESS 0 44 #define BMP_RLE8_COMPRESS 1 45 #define BMP_RLE4_COMPRESS 2 46 47 struct BMPFileHeader { 48 // for both MS and OS/2 BMP formats 49 uint16 magic; // = 'BM' 50 uint32 fileSize; // file size in bytes 51 uint32 reserved; // equals 0 52 uint32 dataOffset; // file offset to actual image 53 }; 54 55 struct MSInfoHeader { 56 uint32 size; // size of this struct (40) 57 uint32 width; // bitmap width 58 uint32 height; // bitmap height 59 uint16 planes; // number of planes, always 1? 60 uint16 bitsperpixel; // bits per pixel, (1,4,8,16 or 24) 61 uint32 compression; // type of compression 62 uint32 imagesize; // size of image data if compressed 63 uint32 xpixperm; // horizontal pixels per meter 64 uint32 ypixperm; // vertical pixels per meter 65 uint32 colorsused; // number of actually used colors 66 uint32 colorsimportant; // number of important colors, zero = all 67 }; 68 69 struct OS2InfoHeader { 70 uint32 size; // size of this struct (12) 71 uint16 width; // bitmap width 72 uint16 height; // bitmap height 73 uint16 planes; // number of planes, always 1? 74 uint16 bitsperpixel; // bits per pixel, (1,4,8,16 or 24) 75 }; 76 77 void 78 print_bmp_info(BFile &file) 79 { 80 uint8 buf[40]; 81 BMPFileHeader fh; 82 83 ssize_t size = 14; 84 if (file.Read(buf, size) != size) { 85 printf("Error: unable to read BMP file header\n"); 86 return; 87 } 88 89 // convert fileHeader to host byte order 90 memcpy(&fh.magic, buf, 2); 91 memcpy(&fh.fileSize, buf + 2, 4); 92 memcpy(&fh.reserved, buf + 6, 4); 93 memcpy(&fh.dataOffset, buf + 10, 4); 94 swap_data(B_UINT16_TYPE, &fh.magic, sizeof(uint16), 95 B_SWAP_BENDIAN_TO_HOST); 96 swap_data(B_UINT32_TYPE, (reinterpret_cast<uint8 *> (&fh)) + 2, 97 12, B_SWAP_LENDIAN_TO_HOST); 98 99 printf("\nFile Header:\n"); 100 printf(" magic: 0x%.4x (should be: 0x424d)\n", fh.magic); 101 printf(" file size: 0x%.8lx (%lu)\n", fh.fileSize, fh.fileSize); 102 printf(" reserved: 0x%.8lx (should be: 0x%.8x)\n", fh.reserved, 0); 103 printf("data offset: 0x%.8lx (%lu) (should be: >= 54 for MS format " 104 "and >= 26 for OS/2 format)\n", fh.dataOffset, fh.dataOffset); 105 106 uint32 headersize = 0; 107 if (file.Read(&headersize, 4) != 4) { 108 printf("Error: unable to read info header size\n"); 109 return; 110 } 111 swap_data(B_UINT32_TYPE, &headersize, 4, B_SWAP_LENDIAN_TO_HOST); 112 113 if (headersize == sizeof(MSInfoHeader)) { 114 // MS format 115 MSInfoHeader msh; 116 msh.size = headersize; 117 if (file.Read(reinterpret_cast<uint8 *> (&msh) + 4, 36) != 36) { 118 printf("Error: unable to read entire MS info header\n"); 119 return; 120 } 121 122 // convert msheader to host byte order 123 swap_data(B_UINT32_TYPE, reinterpret_cast<uint8 *> (&msh) + 4, 36, 124 B_SWAP_LENDIAN_TO_HOST); 125 126 printf("\nMS Info Header:\n"); 127 printf(" header size: 0x%.8lx (%lu) (should be: 40)\n", msh.size, msh.size); 128 printf(" width: %lu\n", msh.width); 129 printf(" height: %lu\n", msh.height); 130 printf(" planes: %u (should be: 1)\n", msh.planes); 131 printf(" bits per pixel: %u (should be: 1,4,8,16,24 or 32)\n", msh.bitsperpixel); 132 printf(" compression: %s (%lu)\n", 133 ((msh.compression == BMP_NO_COMPRESS) ? ("none") : 134 ((msh.compression == BMP_RLE8_COMPRESS) ? ("RLE 8") : 135 ((msh.compression == BMP_RLE4_COMPRESS) ? ("RLE 4") : 136 ("unknown")))), msh.compression); 137 printf(" image size: 0x%.8lx (%lu)\n", msh.imagesize, msh.imagesize); 138 printf(" x pixels/meter: %lu\n", msh.xpixperm); 139 printf(" y pixels/meter: %lu\n", msh.ypixperm); 140 printf(" colors used: %lu\n", msh.colorsused); 141 printf("colors important: %lu\n", msh.colorsimportant); 142 143 } else if (headersize == sizeof(OS2InfoHeader)) { 144 // OS/2 format 145 146 OS2InfoHeader os2; 147 os2.size = headersize; 148 if (file.Read(reinterpret_cast<uint8 *> (&os2) + 4, 8) != 8) { 149 printf("Error: unable to read entire OS/2 info header\n"); 150 return; 151 } 152 153 // convert os2header to host byte order 154 swap_data(B_UINT32_TYPE, reinterpret_cast<uint8 *> (&os2) + 4, 8, 155 B_SWAP_LENDIAN_TO_HOST); 156 157 printf("\nOS/2 Info Header:\n"); 158 printf(" header size: 0x%.8lx (%lu) (should be: 12)\n", os2.size, os2.size); 159 printf(" width: %u\n", os2.width); 160 printf(" height: %u\n", os2.height); 161 printf(" planes: %u (should be: 1)\n", os2.planes); 162 printf("bits per pixel: %u (should be: 1,4,8 or 24)\n", 163 os2.bitsperpixel); 164 165 } else 166 printf("Error: info header size (%lu) does not match MS or OS/2 " 167 "info header size\n", headersize); 168 } 169 170 int 171 main(int argc, char **argv) 172 { 173 printf("\n"); 174 175 if (argc == 1) { 176 printf("bmpinfo - reports information about a BMP image file\n"); 177 printf("\nUsage:\n"); 178 printf("bmpinfo filename.bmp\n"); 179 } 180 else { 181 BFile file; 182 183 for (int32 i = 1; i < argc; i++) { 184 if (file.SetTo(argv[i], B_READ_ONLY) != B_OK) 185 printf("\nError opening %s\n", argv[i]); 186 else { 187 printf("\nBMP image information for: %s\n", argv[i]); 188 print_bmp_info(file); 189 } 190 } 191 192 } 193 194 printf("\n"); 195 196 return 0; 197 } 198 199