1 ////////////////////////////////////////////////////////////////////////////////
3 // File: GIFTranslator.cpp
7 // Author: Daniel Switkin
9 // Copyright 2003 (c) by Daniel Switkin. This file is made publically available
10 // under the BSD license, with the stipulations that this complete header must
11 // remain at the top of the file indefinitely, and credit must be given to the
12 // original author in any about box using this software.
14 ////////////////////////////////////////////////////////////////////////////////
16 // Additional authors: Stephan Aßmus, <superstippi@gmx.de>
17 // John Scipione, <jscipione@gmail.com>
19 #include "GIFTranslator.h"
26 #include <Application.h>
27 #include <ByteOrder.h>
30 #include <InterfaceDefs.h>
31 #include <TranslatorAddOn.h>
32 #include <TranslatorFormats.h>
33 #include <TypeConstants.h>
38 #include "TranslatorWindow.h"
42 #define GIF_TYPE 'GIF '
45 #undef B_TRANSLATION_CONTEXT
46 #define B_TRANSLATION_CONTEXT "GIFTranslator"
50 // this global will be externed in other files - set once here
51 // for the entire translator
53 bool DetermineType(BPositionIO
* source
, bool* isGif
);
54 status_t
GetBitmap(BPositionIO
* in
, BBitmap
** out
);
56 static const translation_format sInputFormats
[] = {
71 "Be Bitmap Format (GIFTranslator)"
75 static const translation_format sOutputFormats
[] = {
90 "Be Bitmap Format (GIFTranslator)"
94 // Default settings for the Translator
95 static const TranSetting sDefaultSettings
[] = {
96 { B_TRANSLATOR_EXT_HEADER_ONLY
, TRAN_SETTING_BOOL
, false },
97 { B_TRANSLATOR_EXT_DATA_ONLY
, TRAN_SETTING_BOOL
, false },
98 { GIF_SETTING_INTERLACED
, TRAN_SETTING_BOOL
, false },
99 { GIF_SETTING_USE_TRANSPARENT
, TRAN_SETTING_BOOL
, true },
100 { GIF_SETTING_USE_TRANSPARENT_AUTO
, TRAN_SETTING_BOOL
, true },
101 { GIF_SETTING_USE_DITHERING
, TRAN_SETTING_BOOL
, false },
102 { GIF_SETTING_PALETTE_MODE
, TRAN_SETTING_INT32
, 3 },
103 { GIF_SETTING_PALETTE_SIZE
, TRAN_SETTING_INT32
, 8 },
104 { GIF_SETTING_TRANSPARENT_RED
, TRAN_SETTING_INT32
, 255 },
105 { GIF_SETTING_TRANSPARENT_GREEN
, TRAN_SETTING_INT32
, 255 },
106 { GIF_SETTING_TRANSPARENT_BLUE
, TRAN_SETTING_INT32
, 255 }
109 const uint32 kNumInputFormats
= sizeof(sInputFormats
)
110 / sizeof(translation_format
);
111 const uint32 kNumOutputFormats
= sizeof(sOutputFormats
)
112 / sizeof(translation_format
);
113 const uint32 kNumDefaultSettings
= sizeof(sDefaultSettings
)
114 / sizeof(TranSetting
);
117 /*! Look at first few bytes in stream to determine type - throw it back
118 if it is not a GIF or a BBitmap that we understand.
121 DetermineType(BPositionIO
* source
, bool* isGif
)
123 unsigned char header
[7];
125 if (source
->Read(header
, 6) != 6)
130 if (strcmp((char*)header
, "GIF87a") != 0
131 && strcmp((char*)header
, "GIF89a") != 0) {
133 int32 magic
= (header
[0] << 24) + (header
[1] << 16) + (header
[2] << 8)
135 if (magic
!= B_TRANSLATOR_BITMAP
)
138 source
->Seek(5 * 4 - 2, SEEK_CUR
);
140 if (source
->Read(&cs
, 4) != 4)
143 cs
= (color_space
)B_BENDIAN_TO_HOST_INT32(cs
);
144 if (cs
!= B_RGB32
&& cs
!= B_RGBA32
&& cs
!= B_RGB32_BIG
145 && cs
!= B_RGBA32_BIG
) {
150 source
->Seek(0, SEEK_SET
);
156 GetBitmap(BPositionIO
* in
, BBitmap
** out
)
158 TranslatorBitmap header
;
159 status_t result
= in
->Read(&header
, sizeof(header
));
160 if (result
!= sizeof(header
))
163 header
.magic
= B_BENDIAN_TO_HOST_INT32(header
.magic
);
164 header
.bounds
.left
= B_BENDIAN_TO_HOST_FLOAT(header
.bounds
.left
);
165 header
.bounds
.top
= B_BENDIAN_TO_HOST_FLOAT(header
.bounds
.top
);
166 header
.bounds
.right
= B_BENDIAN_TO_HOST_FLOAT(header
.bounds
.right
);
167 header
.bounds
.bottom
= B_BENDIAN_TO_HOST_FLOAT(header
.bounds
.bottom
);
168 header
.rowBytes
= B_BENDIAN_TO_HOST_INT32(header
.rowBytes
);
169 header
.colors
= (color_space
)B_BENDIAN_TO_HOST_INT32(header
.colors
);
170 header
.dataSize
= B_BENDIAN_TO_HOST_INT32(header
.dataSize
);
172 // dump data from stream into a BBitmap
173 *out
= new(std::nothrow
) BBitmap(header
.bounds
, header
.colors
);
177 if (!(*out
)->IsValid()) {
182 result
= in
->Read((*out
)->Bits(), header
.dataSize
);
183 if (result
!= (status_t
)header
.dataSize
) {
192 /*! Required identify function - may need to read entire header, not sure
195 GIFTranslator::DerivedIdentify(BPositionIO
* inSource
,
196 const translation_format
* inFormat
, BMessage
* ioExtension
,
197 translator_info
* outInfo
, uint32 outType
)
199 const char* debug_text
= getenv("GIF_TRANSLATOR_DEBUG");
200 if (debug_text
!= NULL
&& atoi(debug_text
) != 0)
204 outType
= B_TRANSLATOR_BITMAP
;
206 if (outType
!= GIF_TYPE
&& outType
!= B_TRANSLATOR_BITMAP
)
207 return B_NO_TRANSLATOR
;
210 if (!DetermineType(inSource
, &isGif
))
211 return B_NO_TRANSLATOR
;
213 if (!isGif
&& inFormat
!= NULL
&& inFormat
->type
!= B_TRANSLATOR_BITMAP
)
214 return B_NO_TRANSLATOR
;
216 outInfo
->group
= B_TRANSLATOR_BITMAP
;
218 outInfo
->type
= GIF_TYPE
;
219 outInfo
->quality
= GIF_IN_QUALITY
;
220 outInfo
->capability
= GIF_IN_CAPABILITY
;
221 strlcpy(outInfo
->name
, B_TRANSLATE("GIF image"), sizeof(outInfo
->name
));
222 strcpy(outInfo
->MIME
, "image/gif");
224 outInfo
->type
= B_TRANSLATOR_BITMAP
;
225 outInfo
->quality
= BBM_IN_QUALITY
;
226 outInfo
->capability
= BBM_IN_CAPABILITY
;
227 strlcpy(outInfo
->name
, B_TRANSLATE("Be Bitmap Format (GIFTranslator)"),
228 sizeof(outInfo
->name
));
229 strcpy(outInfo
->MIME
, "image/x-be-bitmap");
236 /*! Main required function - assumes that an incoming GIF must be translated
237 to a BBitmap, and vice versa - this could be improved
240 GIFTranslator::DerivedTranslate(BPositionIO
* inSource
,
241 const translator_info
* inInfo
, BMessage
* ioExtension
, uint32 outType
,
242 BPositionIO
* outDestination
, int32 baseType
)
244 const char* debug_text
= getenv("GIF_TRANSLATOR_DEBUG");
245 if (debug_text
!= NULL
&& atoi(debug_text
) != 0)
249 outType
= B_TRANSLATOR_BITMAP
;
251 if (outType
!= GIF_TYPE
&& outType
!= B_TRANSLATOR_BITMAP
)
252 return B_NO_TRANSLATOR
;
255 if (!DetermineType(inSource
, &isGif
))
256 return B_NO_TRANSLATOR
;
258 if (!isGif
&& inInfo
->type
!= B_TRANSLATOR_BITMAP
)
259 return B_NO_TRANSLATOR
;
261 status_t result
= B_OK
;
262 bigtime_t now
= system_time();
267 result
= GetBitmap(inSource
, &bitmap
);
271 GIFSave
* gifSave
= new(std::nothrow
) GIFSave(bitmap
, outDestination
,
273 if (gifSave
== NULL
) {
278 if (gifSave
->fatalerror
) {
287 GIFLoad
* gifLoad
= new(std::nothrow
) GIFLoad(inSource
, outDestination
);
291 if (gifLoad
->fatalerror
) {
299 now
= system_time() - now
;
300 syslog(LOG_INFO
, "Translate() - Translation took %Ld microseconds\n",
308 make_nth_translator(int32 n
, image_id you
, uint32 flags
, ...)
311 return new(std::nothrow
) GIFTranslator();
317 GIFTranslator::GIFTranslator()
319 BaseTranslator(B_TRANSLATE("GIF images"),
320 B_TRANSLATE("GIF image translator"),
321 GIF_TRANSLATOR_VERSION
,
322 sInputFormats
, kNumInputFormats
,
323 sOutputFormats
, kNumOutputFormats
,
324 "GIFTranslator_Settings",
325 sDefaultSettings
, kNumDefaultSettings
,
326 B_TRANSLATOR_BITMAP
, B_GIF_FORMAT
)
331 GIFTranslator::~GIFTranslator()
337 GIFTranslator::NewConfigView(TranslatorSettings
* settings
)
339 return new(std::nothrow
) GIFView(settings
);
346 BApplication
app("application/x-vnd.Haiku-GIFTranslator");
347 status_t result
= LaunchTranslatorWindow(new(std::nothrow
) GIFTranslator
,
348 B_TRANSLATE("GIF Settings"), kRectView
);
349 if (result
== B_OK
) {