xref: /haiku/src/add-ons/translators/wonderbrush/WonderBrushTranslator.cpp (revision 922e7ba1f3228e6f28db69b0ded8f86eb32dea17)
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_TRANSLATE_CONTEXT
26 #define B_TRANSLATE_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 			strcpy(outInfo->name, B_TRANSLATE("WonderBrush image"));
138 		}
139 	} else {
140 		delete wbImage;
141 		wbImage = NULL;
142 	}
143 	if (!_wbImage) {
144 		// close WonderBrushImage if caller is not interested in handle
145 		delete wbImage;
146 	} else {
147 		// leave WonderBrushImage open (if it is) and return handle if
148 		// caller needs it
149 		*_wbImage = wbImage;
150 	}
151 
152 	return status;
153 }
154 
155 
156 status_t
157 WonderBrushTranslator::DerivedIdentify(BPositionIO* inSource,
158 	const translation_format* inFormat, BMessage* ioExtension,
159 	translator_info* outInfo, uint32 outType)
160 {
161 	return identify_wbi_header(inSource, outInfo, outType);
162 }
163 
164 
165 status_t
166 WonderBrushTranslator::DerivedTranslate(BPositionIO* inSource,
167 	const translator_info* inInfo, BMessage* ioExtension,
168 	uint32 outType, BPositionIO* outDestination, int32 baseType)
169 {
170 	if (baseType == 0)
171 		// if inSource is NOT in bits format
172 		return _TranslateFromWBI(inSource, outType, outDestination);
173 	else
174 		// if BaseTranslator did not properly identify the data as
175 		// bits or not bits
176 		return B_NO_TRANSLATOR;
177 }
178 
179 
180 BView*
181 WonderBrushTranslator::NewConfigView(TranslatorSettings* settings)
182 {
183 	return new WonderBrushView(BRect(0, 0, 225, 175),
184 		B_TRANSLATE("WBI Settings"), B_FOLLOW_ALL, B_WILL_DRAW, settings);
185 }
186 
187 
188 // #pragma mark -
189 
190 
191 status_t
192 WonderBrushTranslator::_TranslateFromWBI(BPositionIO* inSource, uint32 outType,
193 	BPositionIO* outDestination)
194 {
195 	// if copying WBI_FORMAT to WBI_FORMAT
196 	if (outType == WBI_FORMAT) {
197 		translate_direct_copy(inSource, outDestination);
198 		return B_OK;
199 	}
200 
201 	WonderBrushImage* wbImage = NULL;
202 	ssize_t ret = identify_wbi_header(inSource, NULL, outType, &wbImage);
203 	if (ret < B_OK)
204 		return ret;
205 
206 	bool headerOnly = false;
207 	bool dataOnly = false;
208 
209 	BBitmap* bitmap = wbImage->Bitmap();
210 	if (!bitmap)
211 		return B_ERROR;
212 
213 	uint32 width = bitmap->Bounds().IntegerWidth() + 1;
214 	uint32 height = bitmap->Bounds().IntegerHeight() + 1;
215 	color_space format = bitmap->ColorSpace();
216 	uint32 bytesPerRow = bitmap->BytesPerRow();
217 
218 	if (!dataOnly) {
219 		// Construct and write Be bitmap header
220 		TranslatorBitmap bitsHeader;
221 		bitsHeader.magic = B_TRANSLATOR_BITMAP;
222 		bitsHeader.bounds.left = 0;
223 		bitsHeader.bounds.top = 0;
224 		bitsHeader.bounds.right = width - 1;
225 		bitsHeader.bounds.bottom = height - 1;
226 		bitsHeader.rowBytes = bytesPerRow;
227 		bitsHeader.colors = format;
228 		bitsHeader.dataSize = bitsHeader.rowBytes * height;
229 		if ((ret = swap_data(B_UINT32_TYPE, &bitsHeader,
230 			sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN)) < B_OK) {
231 			delete bitmap;
232 			delete wbImage;
233 			return ret;
234 		} else
235 			ret = outDestination->Write(&bitsHeader, sizeof(TranslatorBitmap));
236 	}
237 
238 	if (ret >= B_OK && !headerOnly) {
239 		// read one row at a time and write out the results
240 		uint8* row = (uint8*)bitmap->Bits();
241 		for (uint32 y = 0; y < height && ret >= B_OK; y++) {
242 			ret = outDestination->Write(row, bytesPerRow);
243 			row += bytesPerRow;
244 		}
245 
246 	}
247 
248 	delete bitmap;
249 	delete wbImage;
250 
251 	if (ret >= B_OK)
252 		ret = B_OK;
253 
254 	return (status_t)ret;
255 }
256 
257 
258