xref: /haiku/src/add-ons/translators/wonderbrush/WonderBrushTranslator.cpp (revision fce97ba360ff70fb19f9cd2a57a16152f0925c06)
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 
29 using std::nothrow;
30 
31 // The input formats that this translator supports.
32 static 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.
52 static 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
73 static 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 
78 const uint32 kNumInputFormats = sizeof(sInputFormats) /
79 	sizeof(translation_format);
80 const uint32 kNumOutputFormats = sizeof(sOutputFormats) /
81 	sizeof(translation_format);
82 const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) /
83 	sizeof(TranSetting);
84 
85 
86 BTranslator*
87 make_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 
96 WonderBrushTranslator::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 
112 WonderBrushTranslator::~WonderBrushTranslator()
113 {
114 #if GAMMA_BLEND
115 	uninit_gamma_blending();
116 #endif
117 }
118 
119 
120 status_t
121 identify_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 
157 status_t
158 WonderBrushTranslator::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 
166 status_t
167 WonderBrushTranslator::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 
181 BView*
182 WonderBrushTranslator::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 
192 status_t
193 WonderBrushTranslator::_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