1/*
2 * Copyright 2006-2009, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Stephan A��mus <superstippi@gmx.de>
7 */
8
9#include "WonderBrushTranslator.h"
10
11#include <new>
12#include <stdio.h>
13#include <string.h>
14
15#include <Bitmap.h>
16#include <Catalog.h>
17#include <OS.h>
18
19#include "blending.h"
20
21#include "WonderBrushImage.h"
22#include "WonderBrushView.h"
23
24
25#undef B_TRANSLATION_CONTEXT
26#define B_TRANSLATION_CONTEXT "WonderBrushTranslator"
27
28
29using std::nothrow;
30
31// The input formats that this translator supports.
32static const translation_format sInputFormats[] = {
33	/*{
34		B_TRANSLATOR_BITMAP,
35		B_TRANSLATOR_BITMAP,
36		BBT_IN_QUALITY,
37		BBT_IN_CAPABILITY,
38		"image/x-be-bitmap",
39		"Be Bitmap Format (WonderBrushTranslator)"
40	},*/
41	{
42		WBI_FORMAT,
43		B_TRANSLATOR_BITMAP,
44		WBI_IN_QUALITY,
45		WBI_IN_CAPABILITY,
46		"image/x-wonderbrush",
47		"WonderBrush image"
48	}
49};
50
51// The output formats that this translator supports.
52static const translation_format sOutputFormats[] = {
53	{
54		B_TRANSLATOR_BITMAP,
55		B_TRANSLATOR_BITMAP,
56		BBT_OUT_QUALITY,
57		BBT_OUT_CAPABILITY,
58		"image/x-be-bitmap",
59		"Be Bitmap Format (WonderBrushTranslator)"
60	}/*,
61	{
62		WBI_FORMAT,
63		B_TRANSLATOR_BITMAP,
64		WBI_OUT_QUALITY,
65		WBI_OUT_CAPABILITY,
66		"image/x-wonderbrush",
67		"WonderBrush image"
68	}*/
69};
70
71
72// Default settings for the Translator
73static const TranSetting sDefaultSettings[] = {
74	{ B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false },
75	{ B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false }
76};
77
78const uint32 kNumInputFormats = sizeof(sInputFormats) /
79	sizeof(translation_format);
80const uint32 kNumOutputFormats = sizeof(sOutputFormats) /
81	sizeof(translation_format);
82const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) /
83	sizeof(TranSetting);
84
85
86BTranslator*
87make_nth_translator(int32 n, image_id you, uint32 flags, ...)
88{
89	if (!n)
90		return new WonderBrushTranslator();
91	else
92		return NULL;
93}
94
95
96WonderBrushTranslator::WonderBrushTranslator()
97	: BaseTranslator(B_TRANSLATE("WonderBrush images"),
98		B_TRANSLATE("WonderBrush image translator"),
99		WBI_TRANSLATOR_VERSION,
100		sInputFormats, kNumInputFormats,
101		sOutputFormats, kNumOutputFormats,
102		"WBITranslator_Settings",
103		sDefaultSettings, kNumDefaultSettings,
104		B_TRANSLATOR_BITMAP, WBI_FORMAT)
105{
106#if GAMMA_BLEND
107	init_gamma_blending();
108#endif
109}
110
111
112WonderBrushTranslator::~WonderBrushTranslator()
113{
114#if GAMMA_BLEND
115	uninit_gamma_blending();
116#endif
117}
118
119
120status_t
121identify_wbi_header(BPositionIO* inSource, translator_info* outInfo,
122	uint32 outType, WonderBrushImage** _wbImage = NULL)
123{
124	status_t status = B_NO_MEMORY;
125	// construct new WonderBrushImage object and set it to the provided BPositionIO
126	WonderBrushImage* wbImage = new(nothrow) WonderBrushImage();
127	if (wbImage)
128		status = wbImage->SetTo(inSource);
129
130	if (status >= B_OK) {
131		if (outInfo) {
132			outInfo->type = WBI_FORMAT;
133			outInfo->group = B_TRANSLATOR_BITMAP;
134			outInfo->quality = WBI_IN_QUALITY;
135			outInfo->capability = WBI_IN_CAPABILITY;
136			strcpy(outInfo->MIME, "image/x-wonderbrush");
137			strlcpy(outInfo->name, B_TRANSLATE("WonderBrush image"),
138				sizeof(outInfo->name));
139		}
140	} else {
141		delete wbImage;
142		wbImage = NULL;
143	}
144	if (!_wbImage) {
145		// close WonderBrushImage if caller is not interested in handle
146		delete wbImage;
147	} else {
148		// leave WonderBrushImage open (if it is) and return handle if
149		// caller needs it
150		*_wbImage = wbImage;
151	}
152
153	return status;
154}
155
156
157status_t
158WonderBrushTranslator::DerivedIdentify(BPositionIO* inSource,
159	const translation_format* inFormat, BMessage* ioExtension,
160	translator_info* outInfo, uint32 outType)
161{
162	return identify_wbi_header(inSource, outInfo, outType);
163}
164
165
166status_t
167WonderBrushTranslator::DerivedTranslate(BPositionIO* inSource,
168	const translator_info* inInfo, BMessage* ioExtension,
169	uint32 outType, BPositionIO* outDestination, int32 baseType)
170{
171	if (baseType == 0)
172		// if inSource is NOT in bits format
173		return _TranslateFromWBI(inSource, outType, outDestination);
174	else
175		// if BaseTranslator did not properly identify the data as
176		// bits or not bits
177		return B_NO_TRANSLATOR;
178}
179
180
181BView*
182WonderBrushTranslator::NewConfigView(TranslatorSettings* settings)
183{
184	return new WonderBrushView(BRect(0, 0, 225, 175),
185		B_TRANSLATE("WBI Settings"), B_FOLLOW_ALL, B_WILL_DRAW, settings);
186}
187
188
189// #pragma mark -
190
191
192status_t
193WonderBrushTranslator::_TranslateFromWBI(BPositionIO* inSource, uint32 outType,
194	BPositionIO* outDestination)
195{
196	// if copying WBI_FORMAT to WBI_FORMAT
197	if (outType == WBI_FORMAT) {
198		translate_direct_copy(inSource, outDestination);
199		return B_OK;
200	}
201
202	WonderBrushImage* wbImage = NULL;
203	ssize_t ret = identify_wbi_header(inSource, NULL, outType, &wbImage);
204	if (ret < B_OK)
205		return ret;
206
207	bool headerOnly = false;
208	bool dataOnly = false;
209
210	BBitmap* bitmap = wbImage->Bitmap();
211	if (!bitmap)
212		return B_ERROR;
213
214	uint32 width = bitmap->Bounds().IntegerWidth() + 1;
215	uint32 height = bitmap->Bounds().IntegerHeight() + 1;
216	color_space format = bitmap->ColorSpace();
217	uint32 bytesPerRow = bitmap->BytesPerRow();
218
219	if (!dataOnly) {
220		// Construct and write Be bitmap header
221		TranslatorBitmap bitsHeader;
222		bitsHeader.magic = B_TRANSLATOR_BITMAP;
223		bitsHeader.bounds.left = 0;
224		bitsHeader.bounds.top = 0;
225		bitsHeader.bounds.right = width - 1;
226		bitsHeader.bounds.bottom = height - 1;
227		bitsHeader.rowBytes = bytesPerRow;
228		bitsHeader.colors = format;
229		bitsHeader.dataSize = bitsHeader.rowBytes * height;
230		if ((ret = swap_data(B_UINT32_TYPE, &bitsHeader,
231			sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN)) < B_OK) {
232			delete bitmap;
233			delete wbImage;
234			return ret;
235		} else
236			ret = outDestination->Write(&bitsHeader, sizeof(TranslatorBitmap));
237	}
238
239	if (ret >= B_OK && !headerOnly) {
240		// read one row at a time and write out the results
241		uint8* row = (uint8*)bitmap->Bits();
242		for (uint32 y = 0; y < height && ret >= B_OK; y++) {
243			ret = outDestination->Write(row, bytesPerRow);
244			row += bytesPerRow;
245		}
246
247	}
248
249	delete bitmap;
250	delete wbImage;
251
252	if (ret >= B_OK)
253		ret = B_OK;
254
255	return (status_t)ret;
256}
257
258
259