////////////////////////////////////////////////////////////////////////////////
//
// File: GIFTranslator.cpp
//
// Date: December 1999
//
// Author: Daniel Switkin
//
// Copyright 2003 (c) by Daniel Switkin. This file is made publically available
// under the BSD license, with the stipulations that this complete header must
// remain at the top of the file indefinitely, and credit must be given to the
// original author in any about box using this software.
//
////////////////////////////////////////////////////////////////////////////////
// Additional authors: Stephan Aßmus, <superstippi@gmx.de>
// John Scipione, <jscipione@gmail.com>
#include "GIFTranslator.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <Application.h>
#include <ByteOrder.h>
#include <Catalog.h>
#include <DataIO.h>
#include <InterfaceDefs.h>
#include <TranslatorAddOn.h>
#include <TranslatorFormats.h>
#include <TypeConstants.h>
#include "GIFLoad.h"
#include "GIFSave.h"
#include "GIFView.h"
#include "TranslatorWindow.h"
#ifndef GIF_TYPE
#define GIF_TYPE 'GIF '
#endif
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "GIFTranslator"
bool debug = false;
// this global will be externed in other files - set once here
// for the entire translator
bool DetermineType(BPositionIO* source, bool* isGif);
status_t GetBitmap(BPositionIO* in, BBitmap** out);
static const translation_format sInputFormats[] = {
{
GIF_TYPE,
B_TRANSLATOR_BITMAP,
GIF_IN_QUALITY,
GIF_IN_CAPABILITY,
"image/gif",
"GIF image"
},
{
B_TRANSLATOR_BITMAP,
B_TRANSLATOR_BITMAP,
BBM_IN_QUALITY,
BBM_IN_CAPABILITY,
"image/x-be-bitmap",
"Be Bitmap Format (GIFTranslator)"
}
};
static const translation_format sOutputFormats[] = {
{
GIF_TYPE,
B_TRANSLATOR_BITMAP,
GIF_OUT_QUALITY,
GIF_OUT_CAPABILITY,
"image/gif",
"GIF image"
},
{
B_TRANSLATOR_BITMAP,
B_TRANSLATOR_BITMAP,
BBM_OUT_QUALITY,
BBM_OUT_CAPABILITY,
"image/x-be-bitmap",
"Be Bitmap Format (GIFTranslator)"
}
};
// Default settings for the Translator
static const TranSetting sDefaultSettings[] = {
{ B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false },
{ B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false },
{ GIF_SETTING_INTERLACED, TRAN_SETTING_BOOL, false },
{ GIF_SETTING_USE_TRANSPARENT, TRAN_SETTING_BOOL, true },
{ GIF_SETTING_USE_TRANSPARENT_AUTO, TRAN_SETTING_BOOL, true },
{ GIF_SETTING_USE_DITHERING, TRAN_SETTING_BOOL, false },
{ GIF_SETTING_PALETTE_MODE, TRAN_SETTING_INT32, 3 },
{ GIF_SETTING_PALETTE_SIZE, TRAN_SETTING_INT32, 8 },
{ GIF_SETTING_TRANSPARENT_RED, TRAN_SETTING_INT32, 255 },
{ GIF_SETTING_TRANSPARENT_GREEN, TRAN_SETTING_INT32, 255 },
{ GIF_SETTING_TRANSPARENT_BLUE, TRAN_SETTING_INT32, 255 }
};
const uint32 kNumInputFormats = sizeof(sInputFormats)
/ sizeof(translation_format);
const uint32 kNumOutputFormats = sizeof(sOutputFormats)
/ sizeof(translation_format);
const uint32 kNumDefaultSettings = sizeof(sDefaultSettings)
/ sizeof(TranSetting);
/*! Look at first few bytes in stream to determine type - throw it back
if it is not a GIF or a BBitmap that we understand.
*/
bool
DetermineType(BPositionIO* source, bool* isGif)
{
unsigned char header[7];
*isGif = true;
if (source->Read(header, 6) != 6)
return false;
header[6] = 0x00;
if (strcmp((char*)header, "GIF87a") != 0
&& strcmp((char*)header, "GIF89a") != 0) {
*isGif = false;
int32 magic = (header[0] << 24) + (header[1] << 16) + (header[2] << 8)
+ header[3];
if (magic != B_TRANSLATOR_BITMAP)
return false;
source->Seek(5 * 4 - 2, SEEK_CUR);
color_space cs;
if (source->Read(&cs, 4) != 4)
return false;
cs = (color_space)B_BENDIAN_TO_HOST_INT32(cs);
if (cs != B_RGB32 && cs != B_RGBA32 && cs != B_RGB32_BIG
&& cs != B_RGBA32_BIG) {
return false;
}
}
source->Seek(0, SEEK_SET);
return true;
}
status_t
GetBitmap(BPositionIO* in, BBitmap** out)
{
TranslatorBitmap header;
status_t result = in->Read(&header, sizeof(header));
if (result != sizeof(header))
return B_IO_ERROR;
header.magic = B_BENDIAN_TO_HOST_INT32(header.magic);
header.bounds.left = B_BENDIAN_TO_HOST_FLOAT(header.bounds.left);
header.bounds.top = B_BENDIAN_TO_HOST_FLOAT(header.bounds.top);
header.bounds.right = B_BENDIAN_TO_HOST_FLOAT(header.bounds.right);
header.bounds.bottom = B_BENDIAN_TO_HOST_FLOAT(header.bounds.bottom);
header.rowBytes = B_BENDIAN_TO_HOST_INT32(header.rowBytes);
header.colors = (color_space)B_BENDIAN_TO_HOST_INT32(header.colors);
header.dataSize = B_BENDIAN_TO_HOST_INT32(header.dataSize);
// dump data from stream into a BBitmap
*out = new(std::nothrow) BBitmap(header.bounds, header.colors);
if (*out == NULL)
return B_NO_MEMORY;
if (!(*out)->IsValid()) {
delete *out;
return B_NO_MEMORY;
}
result = in->Read((*out)->Bits(), header.dataSize);
if (result != (status_t)header.dataSize) {
delete *out;
return B_IO_ERROR;
}
return B_OK;
}
/*! Required identify function - may need to read entire header, not sure
*/
status_t
GIFTranslator::DerivedIdentify(BPositionIO* inSource,
const translation_format* inFormat, BMessage* ioExtension,
translator_info* outInfo, uint32 outType)
{
const char* debug_text = getenv("GIF_TRANSLATOR_DEBUG");
if (debug_text != NULL && atoi(debug_text) != 0)
debug = true;
if (outType == 0)
outType = B_TRANSLATOR_BITMAP;
if (outType != GIF_TYPE && outType != B_TRANSLATOR_BITMAP)
return B_NO_TRANSLATOR;
bool isGif;
if (!DetermineType(inSource, &isGif))
return B_NO_TRANSLATOR;
if (!isGif && inFormat != NULL && inFormat->type != B_TRANSLATOR_BITMAP)
return B_NO_TRANSLATOR;
outInfo->group = B_TRANSLATOR_BITMAP;
if (isGif) {
outInfo->type = GIF_TYPE;
outInfo->quality = GIF_IN_QUALITY;
outInfo->capability = GIF_IN_CAPABILITY;
strlcpy(outInfo->name, B_TRANSLATE("GIF image"), sizeof(outInfo->name));
strcpy(outInfo->MIME, "image/gif");
} else {
outInfo->type = B_TRANSLATOR_BITMAP;
outInfo->quality = BBM_IN_QUALITY;
outInfo->capability = BBM_IN_CAPABILITY;
strlcpy(outInfo->name, B_TRANSLATE("Be Bitmap Format (GIFTranslator)"),
sizeof(outInfo->name));
strcpy(outInfo->MIME, "image/x-be-bitmap");
}
return B_OK;
}
/*! Main required function - assumes that an incoming GIF must be translated
to a BBitmap, and vice versa - this could be improved
*/
status_t
GIFTranslator::DerivedTranslate(BPositionIO* inSource,
const translator_info* inInfo, BMessage* ioExtension, uint32 outType,
BPositionIO* outDestination, int32 baseType)
{
const char* debug_text = getenv("GIF_TRANSLATOR_DEBUG");
if (debug_text != NULL && atoi(debug_text) != 0)
debug = true;
if (outType == 0)
outType = B_TRANSLATOR_BITMAP;
if (outType != GIF_TYPE && outType != B_TRANSLATOR_BITMAP)
return B_NO_TRANSLATOR;
bool isGif;
if (!DetermineType(inSource, &isGif))
return B_NO_TRANSLATOR;
if (!isGif && inInfo->type != B_TRANSLATOR_BITMAP)
return B_NO_TRANSLATOR;
status_t result = B_OK;
bigtime_t now = system_time();
if (!isGif) {
// BBitmap to GIF
BBitmap* bitmap;
result = GetBitmap(inSource, &bitmap);
if (result != B_OK)
return result;
GIFSave* gifSave = new(std::nothrow) GIFSave(bitmap, outDestination,
fSettings);
if (gifSave == NULL) {
delete bitmap;
return B_NO_MEMORY;
}
if (gifSave->fatalerror) {
delete gifSave;
delete bitmap;
return B_NO_MEMORY;
}
delete gifSave;
delete bitmap;
} else {
// GIF to BBitmap
GIFLoad* gifLoad = new(std::nothrow) GIFLoad(inSource, outDestination);
if (gifLoad == NULL)
return B_NO_MEMORY;
if (gifLoad->fatalerror) {
delete gifLoad;
return B_NO_MEMORY;
}
delete gifLoad;
}
if (debug) {
now = system_time() - now;
syslog(LOG_INFO, "Translate() - Translation took %Ld microseconds\n",
now);
}
return B_OK;
}
BTranslator*
make_nth_translator(int32 n, image_id you, uint32 flags, ...)
{
if (n == 0)
return new(std::nothrow) GIFTranslator();
return NULL;
}
GIFTranslator::GIFTranslator()
:
BaseTranslator(B_TRANSLATE("GIF images"),
B_TRANSLATE("GIF image translator"),
GIF_TRANSLATOR_VERSION,
sInputFormats, kNumInputFormats,
sOutputFormats, kNumOutputFormats,
"GIFTranslator_Settings",
sDefaultSettings, kNumDefaultSettings,
B_TRANSLATOR_BITMAP, B_GIF_FORMAT)
{
}
GIFTranslator::~GIFTranslator()
{
}
BView*
GIFTranslator::NewConfigView(TranslatorSettings* settings)
{
return new(std::nothrow) GIFView(settings);
}
int
main()
{
BApplication app("application/x-vnd.Haiku-GIFTranslator");
status_t result = LaunchTranslatorWindow(new(std::nothrow) GIFTranslator,
B_TRANSLATE("GIF Settings"), kRectView);
if (result == B_OK) {
app.Run();
return 0;
}
return 1;
}
↑ V576 Potentially incorrect format string is passed to the 'syslog' function. Prefix 'L' is not applicable to conversion specifier 'd'.