xref: /haiku/src/tools/translation/bmpinfo/bmpinfo.cpp (revision 1214ef1b2100f2b3299fc9d8d6142e46f70a4c3f)
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