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