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()
113 : BaseTranslator(B_TRANSLATE("WebP images"),
114 B_TRANSLATE("WebP image translator"),
115 WEBP_TRANSLATOR_VERSION
,
116 sInputFormats
, kNumInputFormats
,
117 sOutputFormats
, kNumOutputFormats
,
118 "WebPTranslator_Settings", sDefaultSettings
, kNumDefaultSettings
,
119 B_TRANSLATOR_BITMAP
, WEBP_IMAGE_FORMAT
)
124 WebPTranslator::~WebPTranslator()
130 WebPTranslator::DerivedIdentify(BPositionIO
* stream
,
131 const translation_format
* format
, BMessage
* settings
,
132 translator_info
* info
, uint32 outType
)
135 outType
= B_TRANSLATOR_BITMAP
;
136 if (outType
!= B_TRANSLATOR_BITMAP
)
137 return B_NO_TRANSLATOR
;
139 // Check RIFF and 'WEBPVP8 ' signatures...
142 if (stream
->Read(buf
, size
) != size
)
145 const uint32 kRIFFMagic
= B_HOST_TO_BENDIAN_INT32('RIFF');
146 const uint32 kWEBPMagic
= B_HOST_TO_BENDIAN_INT32('WEBP');
147 const uint32 kVP8Magic
= B_HOST_TO_BENDIAN_INT32('VP8 ');
148 if (buf
[0] != kRIFFMagic
|| buf
[2] != kWEBPMagic
|| buf
[3] != kVP8Magic
)
149 return B_ILLEGAL_DATA
;
151 info
->type
= WEBP_IMAGE_FORMAT
;
152 info
->group
= B_TRANSLATOR_BITMAP
;
153 info
->quality
= WEBP_IN_QUALITY
;
154 info
->capability
= WEBP_IN_CAPABILITY
;
155 snprintf(info
->name
, sizeof(info
->name
), B_TRANSLATE("WebP image"));
156 strcpy(info
->MIME
, "image/webp");
163 WebPTranslator::DerivedTranslate(BPositionIO
* stream
,
164 const translator_info
* info
, BMessage
* ioExtension
,
165 uint32 outType
, BPositionIO
* target
, int32 baseType
)
168 // if stream is in bits format
169 return _TranslateFromBits(stream
, ioExtension
, outType
, target
);
170 else if (baseType
== 0)
171 // if stream is NOT in bits format
172 return _TranslateFromWebP(stream
, ioExtension
, outType
, target
);
174 // if BaseTranslator dit not properly identify the data as
176 return B_NO_TRANSLATOR
;
181 WebPTranslator::NewConfigView(TranslatorSettings
* settings
)
183 return new ConfigView(settings
);
188 WebPTranslator::_TranslateFromBits(BPositionIO
* stream
, BMessage
* ioExtension
,
189 uint32 outType
, BPositionIO
* target
)
192 outType
= WEBP_IMAGE_FORMAT
;
193 if (outType
!= WEBP_IMAGE_FORMAT
)
194 return B_NO_TRANSLATOR
;
196 TranslatorBitmap bitsHeader
;
199 status
= identify_bits_header(stream
, NULL
, &bitsHeader
);
203 if (bitsHeader
.colors
== B_CMAP8
) {
204 // TODO: support whatever colospace by intermediate colorspace conversion
205 printf("Error! Colorspace not supported\n");
206 return B_NO_TRANSLATOR
;
209 int32 bitsBytesPerPixel
= 0;
210 switch (bitsHeader
.colors
) {
218 bitsBytesPerPixel
= 4;
224 bitsBytesPerPixel
= 3;
233 bitsBytesPerPixel
= 2;
238 bitsBytesPerPixel
= 1;
245 if (bitsBytesPerPixel
< 3) {
247 return B_NO_TRANSLATOR
;
253 if (!WebPPictureInit(&picture
) || !WebPConfigInit(&config
)) {
254 printf("Error! Version mismatch!\n");
258 WebPPreset preset
= (WebPPreset
)fSettings
->SetGetInt32(WEBP_SETTING_PRESET
);
259 config
.quality
= (float)fSettings
->SetGetInt32(WEBP_SETTING_QUALITY
);
261 if (!WebPConfigPreset(&config
, (WebPPreset
)preset
, config
.quality
)) {
262 printf("Error! Could initialize configuration with preset.");
266 config
.method
= fSettings
->SetGetInt32(WEBP_SETTING_METHOD
);
267 config
.preprocessing
= fSettings
->SetGetBool(WEBP_SETTING_PREPROCESSING
);
269 if (!WebPValidateConfig(&config
)) {
270 printf("Error! Invalid configuration.\n");
274 picture
.width
= bitsHeader
.bounds
.IntegerWidth() + 1;
275 picture
.height
= bitsHeader
.bounds
.IntegerHeight() + 1;
277 int stride
= bitsHeader
.rowBytes
;
278 int bitsSize
= picture
.height
* stride
;
279 uint8
* bits
= (uint8
*)malloc(bitsSize
);
283 if (stream
->Read(bits
, bitsSize
) != bitsSize
) {
288 if (!WebPPictureImportBGRA(&picture
, bits
, stride
)) {
289 printf("Error! WebPEncode() failed!\n");
295 picture
.writer
= _EncodedWriter
;
296 picture
.custom_ptr
= target
;
297 picture
.stats
= NULL
;
299 if (!WebPEncode(&config
, &picture
)) {
300 printf("Error! WebPEncode() failed!\n");
301 status
= B_NO_TRANSLATOR
;
305 WebPPictureFree(&picture
);
311 WebPTranslator::_TranslateFromWebP(BPositionIO
* stream
, BMessage
* ioExtension
,
312 uint32 outType
, BPositionIO
* target
)
315 outType
= B_TRANSLATOR_BITMAP
;
316 if (outType
!= B_TRANSLATOR_BITMAP
)
317 return B_NO_TRANSLATOR
;
319 off_t streamLength
= 0;
320 stream
->GetSize(&streamLength
);
322 off_t streamSize
= stream
->Seek(0, SEEK_END
);
323 stream
->Seek(0, SEEK_SET
);
325 void* streamData
= malloc(streamSize
);
326 if (streamData
== NULL
)
329 if (stream
->Read(streamData
, streamSize
) != streamSize
) {
335 uint8
* out
= WebPDecodeBGRA((const uint8
*)streamData
, streamSize
, &width
,
340 return B_ILLEGAL_DATA
;
342 FreeAllocation
_(out
);
344 uint32 dataSize
= width
* 4 * height
;
346 TranslatorBitmap bitmapHeader
;
347 bitmapHeader
.magic
= B_TRANSLATOR_BITMAP
;
348 bitmapHeader
.bounds
.Set(0, 0, width
- 1, height
- 1);
349 bitmapHeader
.rowBytes
= width
* 4;
350 bitmapHeader
.colors
= B_RGBA32
;
351 bitmapHeader
.dataSize
= width
* 4 * height
;
353 // write out Be's Bitmap header
354 swap_data(B_UINT32_TYPE
, &bitmapHeader
, sizeof(TranslatorBitmap
),
355 B_SWAP_HOST_TO_BENDIAN
);
356 ssize_t bytesWritten
= target
->Write(&bitmapHeader
,
357 sizeof(TranslatorBitmap
));
358 if (bytesWritten
< B_OK
)
361 if ((size_t)bytesWritten
!= sizeof(TranslatorBitmap
))
364 bool headerOnly
= false;
365 if (ioExtension
!= NULL
)
366 ioExtension
->FindBool(B_TRANSLATOR_EXT_HEADER_ONLY
, &headerOnly
);
371 uint32 dataLeft
= dataSize
;
374 bytesWritten
= target
->Write(p
, 4);
375 if (bytesWritten
< B_OK
)
378 if (bytesWritten
!= 4)
390 WebPTranslator::_EncodedWriter(const uint8_t* data
, size_t dataSize
,
391 const WebPPicture
* const picture
)
393 BPositionIO
* target
= (BPositionIO
*)picture
->custom_ptr
;
394 return dataSize
? (target
->Write(data
, dataSize
) == (ssize_t
)dataSize
) : 1;
402 make_nth_translator(int32 n
, image_id you
, uint32 flags
, ...)
407 return new WebPTranslator();