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