2 * Copyright 2010-2011, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
10 #include "WebPTranslator.h"
14 #include <Messenger.h>
15 #include <TranslatorRoster.h>
21 #include "webp/encode.h"
22 #include "webp/decode.h"
24 #include "ConfigView.h"
25 #include "TranslatorSettings.h"
28 #undef B_TRANSLATION_CONTEXT
29 #define B_TRANSLATION_CONTEXT "WebPTranslator"
32 class FreeAllocation
{
34 FreeAllocation(void* buffer
)
51 // The input formats that this translator knows how to read
52 static const translation_format sInputFormats
[] = {
67 "Be Bitmap Format (WebPTranslator)"
71 // The output formats that this translator knows how to write
72 static const translation_format sOutputFormats
[] = {
87 "Be Bitmap Format (WebPTranslator)"
91 // Default settings for the Translator
92 static const TranSetting sDefaultSettings
[] = {
93 { B_TRANSLATOR_EXT_HEADER_ONLY
, TRAN_SETTING_BOOL
, false },
94 { B_TRANSLATOR_EXT_DATA_ONLY
, TRAN_SETTING_BOOL
, false },
95 { WEBP_SETTING_QUALITY
, TRAN_SETTING_INT32
, 60 },
96 { WEBP_SETTING_PRESET
, TRAN_SETTING_INT32
, 0 },
97 { WEBP_SETTING_METHOD
, TRAN_SETTING_INT32
, 2 },
98 { WEBP_SETTING_PREPROCESSING
, TRAN_SETTING_BOOL
, false },
101 const uint32 kNumInputFormats
= sizeof(sInputFormats
) /
102 sizeof(translation_format
);
103 const uint32 kNumOutputFormats
= sizeof(sOutputFormats
) /
104 sizeof(translation_format
);
105 const uint32 kNumDefaultSettings
= sizeof(sDefaultSettings
) /
112 WebPTranslator::WebPTranslator()
114 BaseTranslator(B_TRANSLATE("WebP images"),
115 B_TRANSLATE("WebP image translator"),
116 WEBP_TRANSLATOR_VERSION
,
117 sInputFormats
, kNumInputFormats
,
118 sOutputFormats
, kNumOutputFormats
,
119 "WebPTranslator_Settings", sDefaultSettings
, kNumDefaultSettings
,
120 B_TRANSLATOR_BITMAP
, WEBP_IMAGE_FORMAT
)
125 WebPTranslator::~WebPTranslator()
131 WebPTranslator::DerivedIdentify(BPositionIO
* stream
,
132 const translation_format
* format
, BMessage
* settings
,
133 translator_info
* info
, uint32 outType
)
136 outType
= B_TRANSLATOR_BITMAP
;
137 if (outType
!= B_TRANSLATOR_BITMAP
)
138 return B_NO_TRANSLATOR
;
140 // Read header and first chunck bytes...
142 ssize_t size
= sizeof(buf
);
143 if (stream
->Read(buf
, size
) != size
)
146 // Check it's a valid WebP format
147 if (!WebPGetInfo((const uint8_t*)buf
, size
, NULL
, NULL
))
148 return B_ILLEGAL_DATA
;
150 info
->type
= WEBP_IMAGE_FORMAT
;
151 info
->group
= B_TRANSLATOR_BITMAP
;
152 info
->quality
= WEBP_IN_QUALITY
;
153 info
->capability
= WEBP_IN_CAPABILITY
;
154 snprintf(info
->name
, sizeof(info
->name
), B_TRANSLATE("WebP image"));
155 strcpy(info
->MIME
, "image/webp");
162 WebPTranslator::DerivedTranslate(BPositionIO
* stream
,
163 const translator_info
* info
, BMessage
* ioExtension
, uint32 outType
,
164 BPositionIO
* target
, int32 baseType
)
167 // if stream is in bits format
168 return _TranslateFromBits(stream
, ioExtension
, outType
, target
);
169 else if (baseType
== 0)
170 // if stream is NOT in bits format
171 return _TranslateFromWebP(stream
, ioExtension
, outType
, target
);
173 // if BaseTranslator dit not properly identify the data as
175 return B_NO_TRANSLATOR
;
180 WebPTranslator::NewConfigView(TranslatorSettings
* settings
)
182 return new ConfigView(settings
);
187 WebPTranslator::_TranslateFromBits(BPositionIO
* stream
, BMessage
* ioExtension
,
188 uint32 outType
, BPositionIO
* target
)
191 outType
= WEBP_IMAGE_FORMAT
;
192 if (outType
!= WEBP_IMAGE_FORMAT
)
193 return B_NO_TRANSLATOR
;
195 TranslatorBitmap bitsHeader
;
198 status
= identify_bits_header(stream
, NULL
, &bitsHeader
);
202 if (bitsHeader
.colors
== B_CMAP8
) {
203 // TODO: support whatever colospace by intermediate colorspace conversion
204 printf("Error! Colorspace not supported\n");
205 return B_NO_TRANSLATOR
;
208 int32 bitsBytesPerPixel
= 0;
209 switch (bitsHeader
.colors
) {
217 bitsBytesPerPixel
= 4;
223 bitsBytesPerPixel
= 3;
232 bitsBytesPerPixel
= 2;
237 bitsBytesPerPixel
= 1;
244 if (bitsBytesPerPixel
< 3) {
246 return B_NO_TRANSLATOR
;
252 if (!WebPPictureInit(&picture
) || !WebPConfigInit(&config
)) {
253 printf("Error! Version mismatch!\n");
257 WebPPreset preset
= (WebPPreset
)fSettings
->SetGetInt32(WEBP_SETTING_PRESET
);
258 config
.quality
= (float)fSettings
->SetGetInt32(WEBP_SETTING_QUALITY
);
260 if (!WebPConfigPreset(&config
, (WebPPreset
)preset
, config
.quality
)) {
261 printf("Error! Could initialize configuration with preset.");
265 config
.method
= fSettings
->SetGetInt32(WEBP_SETTING_METHOD
);
266 config
.preprocessing
= fSettings
->SetGetBool(WEBP_SETTING_PREPROCESSING
);
268 if (!WebPValidateConfig(&config
)) {
269 printf("Error! Invalid configuration.\n");
273 picture
.width
= bitsHeader
.bounds
.IntegerWidth() + 1;
274 picture
.height
= bitsHeader
.bounds
.IntegerHeight() + 1;
276 int stride
= bitsHeader
.rowBytes
;
277 int bitsSize
= picture
.height
* stride
;
278 uint8
* bits
= (uint8
*)malloc(bitsSize
);
282 if (stream
->Read(bits
, bitsSize
) != bitsSize
) {
287 if (!WebPPictureImportBGRA(&picture
, bits
, stride
)) {
288 printf("Error! WebPEncode() failed!\n");
294 picture
.writer
= _EncodedWriter
;
295 picture
.custom_ptr
= target
;
296 picture
.stats
= NULL
;
298 if (!WebPEncode(&config
, &picture
)) {
299 printf("Error! WebPEncode() failed!\n");
300 status
= B_NO_TRANSLATOR
;
304 WebPPictureFree(&picture
);
310 WebPTranslator::_TranslateFromWebP(BPositionIO
* stream
, BMessage
* ioExtension
,
311 uint32 outType
, BPositionIO
* target
)
314 outType
= B_TRANSLATOR_BITMAP
;
315 if (outType
!= B_TRANSLATOR_BITMAP
)
316 return B_NO_TRANSLATOR
;
318 off_t streamLength
= 0;
319 stream
->GetSize(&streamLength
);
321 off_t streamSize
= stream
->Seek(0, SEEK_END
);
322 stream
->Seek(0, SEEK_SET
);
324 void* streamData
= malloc(streamSize
);
325 if (streamData
== NULL
)
328 if (stream
->Read(streamData
, streamSize
) != streamSize
) {
334 uint8
* out
= WebPDecodeBGRA((const uint8
*)streamData
, streamSize
, &width
,
339 return B_ILLEGAL_DATA
;
341 FreeAllocation
_(out
);
343 uint32 dataSize
= width
* 4 * height
;
345 TranslatorBitmap bitmapHeader
;
346 bitmapHeader
.magic
= B_TRANSLATOR_BITMAP
;
347 bitmapHeader
.bounds
.Set(0, 0, width
- 1, height
- 1);
348 bitmapHeader
.rowBytes
= width
* 4;
349 bitmapHeader
.colors
= B_RGBA32
;
350 bitmapHeader
.dataSize
= width
* 4 * height
;
352 // write out Be's Bitmap header
353 swap_data(B_UINT32_TYPE
, &bitmapHeader
, sizeof(TranslatorBitmap
),
354 B_SWAP_HOST_TO_BENDIAN
);
355 ssize_t bytesWritten
= target
->Write(&bitmapHeader
,
356 sizeof(TranslatorBitmap
));
357 if (bytesWritten
< B_OK
)
360 if ((size_t)bytesWritten
!= sizeof(TranslatorBitmap
))
363 bool headerOnly
= false;
364 if (ioExtension
!= NULL
)
365 ioExtension
->FindBool(B_TRANSLATOR_EXT_HEADER_ONLY
, &headerOnly
);
370 uint32 dataLeft
= dataSize
;
373 bytesWritten
= target
->Write(p
, 4);
374 if (bytesWritten
< B_OK
)
377 if (bytesWritten
!= 4)
389 WebPTranslator::_EncodedWriter(const uint8_t* data
, size_t dataSize
,
390 const WebPPicture
* const picture
)
392 BPositionIO
* target
= (BPositionIO
*)picture
->custom_ptr
;
393 return dataSize
? (target
->Write(data
, dataSize
) == (ssize_t
)dataSize
) : 1;
401 make_nth_translator(int32 n
, image_id you
, uint32 flags
, ...)
406 return new WebPTranslator();