1/*****************************************************************************/
2// bitsinfo
3// Written by Michael Wilber, Haiku Translation Kit Team
4//
5// Version:
6//
7// bitsinfo is a command line program for displaying text information about
8// Be bitmap format ("bits") images.  The Be bitmap format is used by
9// the Translation Kit as the intermediate format for converting images.
10// To make "bits" images, you can use the "translate" command line program or
11// the BBitmapTranslator (available: http://www.bebits.com/app/647).
12//
13// This application and all source files used in its construction, except
14// where noted, are licensed under the MIT License, and have been written
15// and are:
16//
17// Copyright (c) 2003 Haiku Project
18//
19// Permission is hereby granted, free of charge, to any person obtaining a
20// copy of this software and associated documentation files (the "Software"),
21// to deal in the Software without restriction, including without limitation
22// the rights to use, copy, modify, merge, publish, distribute, sublicense,
23// and/or sell copies of the Software, and to permit persons to whom the
24// Software is furnished to do so, subject to the following conditions:
25//
26// The above copyright notice and this permission notice shall be included
27// in all copies or substantial portions of the Software.
28//
29// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
30// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
32// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
34// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
35// DEALINGS IN THE SOFTWARE.
36/*****************************************************************************/
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <ByteOrder.h>
41#include <Catalog.h>
42#include <File.h>
43#include <TranslatorFormats.h>
44#include <StorageDefs.h>
45
46#undef B_TRANSLATION_CONTEXT
47#define B_TRANSLATION_CONTEXT "bitsinfo"
48
49struct ColorSpaceName {
50	color_space id;
51	const char *name;
52};
53#define COLORSPACENAME(id) {id, #id}
54
55const char *kpixels = "-pixels";
56
57void
58PrintBitsInfo(const char *filepath, bool bdumppixels)
59{
60	BFile file(filepath, B_READ_ONLY);
61
62	if (file.InitCheck() == B_OK) {
63		TranslatorBitmap header;
64		memset(&header, 0, sizeof(TranslatorBitmap));
65
66		// read in the rest of the header
67		ssize_t size = sizeof(TranslatorBitmap);
68		if (file.Read(reinterpret_cast<uint8 *> (&header), size) != size) {
69			printf(B_TRANSLATE("\nError: Unable to read the Be bitmap "
70				"header.\n"));
71			return;
72		}
73		if (!bdumppixels)
74			// I don't need the file anymore
75			file.Unset();
76
77		// convert to host byte order
78		if (swap_data(B_UINT32_TYPE, &header, sizeof(TranslatorBitmap),
79			B_SWAP_BENDIAN_TO_HOST) != B_OK) {
80			printf(B_TRANSLATE("\nError: Unable to swap byte order\n"));
81			return;
82		}
83
84		printf(B_TRANSLATE("\nBe bitmap (\"bits\") header for: %s\n\n"),
85			filepath);
86
87		const uint32 kbitsmagic = 0x62697473UL;
88			// in ASCII, this number looks like "bits"
89		if (header.magic == kbitsmagic)
90			printf(B_TRANSLATE("magic number: 0x%.8lx (valid)\n"),
91				header.magic);
92		else
93			printf(B_TRANSLATE("magic number: 0x%.8lx (INVALID, should be: "
94				"0x%.8lx)\n"), header.magic, kbitsmagic);
95		printf(B_TRANSLATE("bounds: (%f, %f, %f, %f)\n"),
96			header.bounds.left, header.bounds.top,
97			header.bounds.right, header.bounds.bottom);
98		printf(B_TRANSLATE("dimensions: %d x %d\n"),
99			static_cast<int>(header.bounds.Width() + 1),
100			static_cast<int>(header.bounds.Height() + 1));
101
102		printf(B_TRANSLATE("bytes per row: %u\n"),
103			static_cast<unsigned int>(header.rowBytes));
104
105		// print out colorspace if it matches an item in the list
106		ColorSpaceName colorspaces[] = {
107			COLORSPACENAME(B_NO_COLOR_SPACE),
108			COLORSPACENAME(B_RGB32),
109			COLORSPACENAME(B_RGBA32),
110			COLORSPACENAME(B_RGB24),
111			COLORSPACENAME(B_RGB16),
112			COLORSPACENAME(B_RGB15),
113			COLORSPACENAME(B_RGBA15),
114			COLORSPACENAME(B_CMAP8),
115			COLORSPACENAME(B_GRAY8),
116			COLORSPACENAME(B_GRAY1),
117			COLORSPACENAME(B_RGB32_BIG),
118			COLORSPACENAME(B_RGBA32_BIG),
119			COLORSPACENAME(B_RGB24_BIG),
120			COLORSPACENAME(B_RGB16_BIG),
121			COLORSPACENAME(B_RGB15_BIG),
122			COLORSPACENAME(B_RGBA15_BIG),
123			COLORSPACENAME(B_YCbCr422),
124			COLORSPACENAME(B_YCbCr411),
125			COLORSPACENAME(B_YCbCr444),
126			COLORSPACENAME(B_YCbCr420),
127			COLORSPACENAME(B_YUV422),
128			COLORSPACENAME(B_YUV411),
129			COLORSPACENAME(B_YUV444),
130			COLORSPACENAME(B_YUV420),
131			COLORSPACENAME(B_YUV9),
132			COLORSPACENAME(B_YUV12),
133			COLORSPACENAME(B_UVL24),
134			COLORSPACENAME(B_UVL32),
135			COLORSPACENAME(B_UVLA32),
136			COLORSPACENAME(B_LAB24),
137			COLORSPACENAME(B_LAB32),
138			COLORSPACENAME(B_LABA32),
139			COLORSPACENAME(B_HSI24),
140			COLORSPACENAME(B_HSI32),
141			COLORSPACENAME(B_HSIA32),
142			COLORSPACENAME(B_HSV24),
143			COLORSPACENAME(B_HSV32),
144			COLORSPACENAME(B_HSVA32),
145			COLORSPACENAME(B_HLS24),
146			COLORSPACENAME(B_HLS32),
147			COLORSPACENAME(B_HLSA32),
148			COLORSPACENAME(B_CMY24),
149			COLORSPACENAME(B_CMY32),
150			COLORSPACENAME(B_CMYA32),
151			COLORSPACENAME(B_CMYK32)
152		};
153		const int32 kncolorspaces =  sizeof(colorspaces) /
154			sizeof(ColorSpaceName);
155		int32 i;
156		for (i = 0; i < kncolorspaces; i++) {
157			if (header.colors == colorspaces[i].id) {
158				printf(B_TRANSLATE("color space: %s\n"), colorspaces[i].name);
159				break;
160			}
161		}
162		if (i == kncolorspaces)
163			printf(B_TRANSLATE("color space: Unknown (0x%.8lx)\n"),
164				static_cast<unsigned long>(header.colors));
165
166		printf(B_TRANSLATE("data size: %u\n"),
167			static_cast<unsigned int>(header.dataSize));
168
169		if (bdumppixels) {
170			const char *components = NULL;
171			int32 ncomponents = 0;
172			switch (header.colors) {
173				case B_RGB24:
174					components = "BGR";
175					ncomponents = 3;
176					break;
177				case B_RGB32:
178					components = "BGR-";
179					ncomponents = 4;
180					break;
181				case B_RGBA32:
182					components = "BGRA";
183					ncomponents = 4;
184					break;
185
186				default:
187					printf(B_TRANSLATE("Sorry, %s isn't supported yet"
188						" for this color space\n"), kpixels);
189					return;
190			}
191			uint8 *prow = new uint8[header.rowBytes];
192			if (!prow) {
193				printf(B_TRANSLATE("Error: Not enough memory for row "
194					"buffer\n"));
195				return;
196			}
197			ssize_t ret, n;
198			uint32 totalbytes = 0;
199			printf(B_TRANSLATE("pixel data (%s):\n"), components);
200			while ((ret = file.Read(prow, header.rowBytes)) > 0) {
201				n = 0;
202				while (n < ret) {
203					if (n && !(n % ncomponents))
204						printf(" ");
205					printf("%.2X", prow[n]);
206					n++;
207					totalbytes++;
208					if (!(totalbytes % (uint32) ret))
209						printf("\n\n");
210				}
211			}
212		}
213
214	} else
215		printf(B_TRANSLATE_COMMENT("Error opening %s\n",
216			"file path is opening"), filepath);
217}
218
219int
220main(int argc, char **argv)
221{
222	if (argc == 1) {
223		printf(B_TRANSLATE("\nbitsinfo - reports information about a Be "
224			"bitmap (\"bits\") image\n"));
225		printf(B_TRANSLATE("\nUsage:\n"));
226		printf(B_TRANSLATE("bitsinfo [options] filename.bits\n\n"));
227		printf(B_TRANSLATE("Options:\n\n"));
228		printf(B_TRANSLATE("\t%s \t print RGB color for each pixel\n"),
229			kpixels);
230	}
231	else {
232		int32 first = 1;
233		bool bdumppixels = false;
234		if (strcmp(argv[1], kpixels) == 0) {
235			bdumppixels = true;
236			first = 2;
237		}
238
239		for (int32 i = first; i < argc; i++)
240			PrintBitsInfo(argv[i], bdumppixels);
241	}
242
243	printf("\n");
244
245	return 0;
246}
247
248