1*9949213aSStephan Aßmus //////////////////////////////////////////////////////////////////////////////// 2*9949213aSStephan Aßmus // 3*9949213aSStephan Aßmus // File: GIFTranslator.cpp 4*9949213aSStephan Aßmus // 5*9949213aSStephan Aßmus // Date: December 1999 6*9949213aSStephan Aßmus // 7*9949213aSStephan Aßmus // Author: Daniel Switkin 8*9949213aSStephan Aßmus // 9*9949213aSStephan Aßmus // Copyright 2003 (c) by Daniel Switkin. This file is made publically available 10*9949213aSStephan Aßmus // under the BSD license, with the stipulations that this complete header must 11*9949213aSStephan Aßmus // remain at the top of the file indefinitely, and credit must be given to the 12*9949213aSStephan Aßmus // original author in any about box using this software. 13*9949213aSStephan Aßmus // 14*9949213aSStephan Aßmus //////////////////////////////////////////////////////////////////////////////// 15*9949213aSStephan Aßmus 16*9949213aSStephan Aßmus #include "GIFTranslator.h" 17*9949213aSStephan Aßmus #include "GIFWindow.h" 18*9949213aSStephan Aßmus #include "GIFView.h" 19*9949213aSStephan Aßmus #include "GIFSave.h" 20*9949213aSStephan Aßmus #include "GIFLoad.h" 21*9949213aSStephan Aßmus #include <ByteOrder.h> 22*9949213aSStephan Aßmus #include <TypeConstants.h> 23*9949213aSStephan Aßmus #include <DataIO.h> 24*9949213aSStephan Aßmus #include <TranslatorAddOn.h> 25*9949213aSStephan Aßmus #include <TranslatorFormats.h> 26*9949213aSStephan Aßmus #include <InterfaceDefs.h> 27*9949213aSStephan Aßmus #include <stdio.h> 28*9949213aSStephan Aßmus #include <stdlib.h> 29*9949213aSStephan Aßmus #include <string.h> 30*9949213aSStephan Aßmus 31*9949213aSStephan Aßmus #ifndef GIF_TYPE 32*9949213aSStephan Aßmus #define GIF_TYPE 'GIF ' 33*9949213aSStephan Aßmus #endif 34*9949213aSStephan Aßmus 35*9949213aSStephan Aßmus // This global will be externed in other files - set once here 36*9949213aSStephan Aßmus // for the entire translator 37*9949213aSStephan Aßmus bool debug = false; 38*9949213aSStephan Aßmus 39*9949213aSStephan Aßmus bool DetermineType(BPositionIO *source, bool *is_gif); 40*9949213aSStephan Aßmus status_t GetBitmap(BPositionIO *in, BBitmap **out); 41*9949213aSStephan Aßmus 42*9949213aSStephan Aßmus /* Required data */ 43*9949213aSStephan Aßmus char translatorName[] = "GIF Images"; 44*9949213aSStephan Aßmus char translatorInfo[] = "GIF image translator v1.4"; 45*9949213aSStephan Aßmus int32 translatorVersion = 0x140; 46*9949213aSStephan Aßmus 47*9949213aSStephan Aßmus translation_format inputFormats[] = { 48*9949213aSStephan Aßmus { GIF_TYPE, B_TRANSLATOR_BITMAP, 0.8, 0.8, "image/gif", "GIF image" }, 49*9949213aSStephan Aßmus { B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.3, 0.3, "image/x-be-bitmap", "Be Bitmap image" }, 50*9949213aSStephan Aßmus { 0 } 51*9949213aSStephan Aßmus }; 52*9949213aSStephan Aßmus 53*9949213aSStephan Aßmus translation_format outputFormats[] = { 54*9949213aSStephan Aßmus { GIF_TYPE, B_TRANSLATOR_BITMAP, 0.8, 0.8, "image/gif", "GIF image" }, 55*9949213aSStephan Aßmus { B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.3, 0.3, "image/x-be-bitmap", "Be Bitmap image" }, 56*9949213aSStephan Aßmus { 0 } 57*9949213aSStephan Aßmus }; 58*9949213aSStephan Aßmus 59*9949213aSStephan Aßmus 60*9949213aSStephan Aßmus /* Build a pretty view for DataTranslations */ 61*9949213aSStephan Aßmus status_t 62*9949213aSStephan Aßmus MakeConfig(BMessage *ioExtension, BView **outView, BRect *outExtent) 63*9949213aSStephan Aßmus { 64*9949213aSStephan Aßmus outExtent->Set(0, 0, 239, 239); 65*9949213aSStephan Aßmus GIFView *gifview = new GIFView(*outExtent, "TranslatorView"); 66*9949213aSStephan Aßmus *outView = gifview; 67*9949213aSStephan Aßmus return B_OK; 68*9949213aSStephan Aßmus } 69*9949213aSStephan Aßmus 70*9949213aSStephan Aßmus 71*9949213aSStephan Aßmus /* Look at first few bytes in stream to determine type - throw it back 72*9949213aSStephan Aßmus if it is not a GIF or a BBitmap that we understand */ 73*9949213aSStephan Aßmus bool 74*9949213aSStephan Aßmus DetermineType(BPositionIO *source, bool *is_gif) 75*9949213aSStephan Aßmus { 76*9949213aSStephan Aßmus unsigned char header[7]; 77*9949213aSStephan Aßmus *is_gif = true; 78*9949213aSStephan Aßmus if (source->Read(header, 6) != 6) return false; 79*9949213aSStephan Aßmus header[6] = 0x00; 80*9949213aSStephan Aßmus 81*9949213aSStephan Aßmus if (strcmp((char *)header, "GIF87a") != 0 && strcmp((char *)header, "GIF89a") != 0) { 82*9949213aSStephan Aßmus *is_gif = false; 83*9949213aSStephan Aßmus int32 magic = (header[0] << 24) + (header[1] << 16) + (header[2] << 8) + header[3]; 84*9949213aSStephan Aßmus if (magic != B_TRANSLATOR_BITMAP) return false; 85*9949213aSStephan Aßmus source->Seek(5 * 4 - 2, SEEK_CUR); 86*9949213aSStephan Aßmus color_space cs; 87*9949213aSStephan Aßmus if (source->Read(&cs, 4) != 4) return false; 88*9949213aSStephan Aßmus cs = (color_space)B_BENDIAN_TO_HOST_INT32(cs); 89*9949213aSStephan Aßmus if (cs != B_RGB32 && cs != B_RGBA32 && cs != B_RGB32_BIG && cs != B_RGBA32_BIG) return false; 90*9949213aSStephan Aßmus } 91*9949213aSStephan Aßmus 92*9949213aSStephan Aßmus source->Seek(0, SEEK_SET); 93*9949213aSStephan Aßmus return true; 94*9949213aSStephan Aßmus } 95*9949213aSStephan Aßmus 96*9949213aSStephan Aßmus 97*9949213aSStephan Aßmus /* Dump data from stream into a BBitmap */ 98*9949213aSStephan Aßmus status_t 99*9949213aSStephan Aßmus GetBitmap(BPositionIO *in, BBitmap **out) 100*9949213aSStephan Aßmus { 101*9949213aSStephan Aßmus TranslatorBitmap header; 102*9949213aSStephan Aßmus 103*9949213aSStephan Aßmus status_t err = in->Read(&header, sizeof(header)); 104*9949213aSStephan Aßmus if (err != sizeof(header)) 105*9949213aSStephan Aßmus return B_IO_ERROR; 106*9949213aSStephan Aßmus 107*9949213aSStephan Aßmus header.magic = B_BENDIAN_TO_HOST_INT32(header.magic); 108*9949213aSStephan Aßmus header.bounds.left = B_BENDIAN_TO_HOST_FLOAT(header.bounds.left); 109*9949213aSStephan Aßmus header.bounds.top = B_BENDIAN_TO_HOST_FLOAT(header.bounds.top); 110*9949213aSStephan Aßmus header.bounds.right = B_BENDIAN_TO_HOST_FLOAT(header.bounds.right); 111*9949213aSStephan Aßmus header.bounds.bottom = B_BENDIAN_TO_HOST_FLOAT(header.bounds.bottom); 112*9949213aSStephan Aßmus header.rowBytes = B_BENDIAN_TO_HOST_INT32(header.rowBytes); 113*9949213aSStephan Aßmus header.colors = (color_space)B_BENDIAN_TO_HOST_INT32(header.colors); 114*9949213aSStephan Aßmus header.dataSize = B_BENDIAN_TO_HOST_INT32(header.dataSize); 115*9949213aSStephan Aßmus 116*9949213aSStephan Aßmus BBitmap *bitmap = new BBitmap(header.bounds, header.colors); 117*9949213aSStephan Aßmus *out = bitmap; 118*9949213aSStephan Aßmus if (bitmap == NULL) return B_NO_MEMORY; 119*9949213aSStephan Aßmus unsigned char *bits = (unsigned char *)bitmap->Bits(); 120*9949213aSStephan Aßmus if (bits == NULL) { 121*9949213aSStephan Aßmus delete bitmap; 122*9949213aSStephan Aßmus return B_NO_MEMORY; 123*9949213aSStephan Aßmus } 124*9949213aSStephan Aßmus err = in->Read(bits, header.dataSize); 125*9949213aSStephan Aßmus if (err == (status_t)header.dataSize) return B_OK; 126*9949213aSStephan Aßmus else return B_IO_ERROR; 127*9949213aSStephan Aßmus } 128*9949213aSStephan Aßmus 129*9949213aSStephan Aßmus 130*9949213aSStephan Aßmus /* Required Identify function - may need to read entire header, not sure */ 131*9949213aSStephan Aßmus status_t 132*9949213aSStephan Aßmus Identify(BPositionIO *inSource, const translation_format *inFormat, 133*9949213aSStephan Aßmus BMessage *ioExtension, translator_info *outInfo, uint32 outType) 134*9949213aSStephan Aßmus { 135*9949213aSStephan Aßmus 136*9949213aSStephan Aßmus const char *debug_text = getenv("GIF_TRANSLATOR_DEBUG"); 137*9949213aSStephan Aßmus if ((debug_text != NULL) && (atoi(debug_text) != 0)) debug = true; 138*9949213aSStephan Aßmus 139*9949213aSStephan Aßmus if (outType == 0) outType = B_TRANSLATOR_BITMAP; 140*9949213aSStephan Aßmus if (outType != GIF_TYPE && outType != B_TRANSLATOR_BITMAP) return B_NO_TRANSLATOR; 141*9949213aSStephan Aßmus 142*9949213aSStephan Aßmus bool is_gif; 143*9949213aSStephan Aßmus if (!DetermineType(inSource, &is_gif)) return B_NO_TRANSLATOR; 144*9949213aSStephan Aßmus if (!is_gif && inFormat != NULL && inFormat->type != B_TRANSLATOR_BITMAP) 145*9949213aSStephan Aßmus return B_NO_TRANSLATOR; 146*9949213aSStephan Aßmus 147*9949213aSStephan Aßmus outInfo->group = B_TRANSLATOR_BITMAP; 148*9949213aSStephan Aßmus if (is_gif) { 149*9949213aSStephan Aßmus outInfo->type = GIF_TYPE; 150*9949213aSStephan Aßmus outInfo->quality = 0.8; 151*9949213aSStephan Aßmus outInfo->capability = 0.8; 152*9949213aSStephan Aßmus strcpy(outInfo->name, "GIF image"); 153*9949213aSStephan Aßmus strcpy(outInfo->MIME, "image/gif"); 154*9949213aSStephan Aßmus } 155*9949213aSStephan Aßmus else { 156*9949213aSStephan Aßmus outInfo->type = B_TRANSLATOR_BITMAP; 157*9949213aSStephan Aßmus outInfo->quality = 0.3; 158*9949213aSStephan Aßmus outInfo->capability = 0.3; 159*9949213aSStephan Aßmus strcpy(outInfo->name, "Be Bitmap image"); 160*9949213aSStephan Aßmus strcpy(outInfo->MIME, "image/x-be-bitmap"); 161*9949213aSStephan Aßmus } 162*9949213aSStephan Aßmus return B_OK; 163*9949213aSStephan Aßmus } 164*9949213aSStephan Aßmus 165*9949213aSStephan Aßmus 166*9949213aSStephan Aßmus /* Main required function - assumes that an incoming GIF must be translated 167*9949213aSStephan Aßmus to a BBitmap, and vice versa - this could be improved */ 168*9949213aSStephan Aßmus status_t 169*9949213aSStephan Aßmus Translate(BPositionIO *inSource, const translator_info *inInfo, 170*9949213aSStephan Aßmus BMessage *ioExtension, uint32 outType, BPositionIO *outDestination) 171*9949213aSStephan Aßmus { 172*9949213aSStephan Aßmus 173*9949213aSStephan Aßmus const char *debug_text = getenv("GIF_TRANSLATOR_DEBUG"); 174*9949213aSStephan Aßmus if ((debug_text != NULL) && (atoi(debug_text) != 0)) debug = true; 175*9949213aSStephan Aßmus 176*9949213aSStephan Aßmus if (outType == 0) outType = B_TRANSLATOR_BITMAP; 177*9949213aSStephan Aßmus if (outType != GIF_TYPE && outType != B_TRANSLATOR_BITMAP) { 178*9949213aSStephan Aßmus return B_NO_TRANSLATOR; 179*9949213aSStephan Aßmus } 180*9949213aSStephan Aßmus 181*9949213aSStephan Aßmus bool is_gif; 182*9949213aSStephan Aßmus if (!DetermineType(inSource, &is_gif)) return B_NO_TRANSLATOR; 183*9949213aSStephan Aßmus if (!is_gif && inInfo->type != B_TRANSLATOR_BITMAP) return B_NO_TRANSLATOR; 184*9949213aSStephan Aßmus 185*9949213aSStephan Aßmus status_t err = B_OK; 186*9949213aSStephan Aßmus bigtime_t now = system_time(); 187*9949213aSStephan Aßmus // Going from BBitmap to GIF 188*9949213aSStephan Aßmus if (!is_gif) { 189*9949213aSStephan Aßmus BBitmap **b = (BBitmap **)malloc(4); 190*9949213aSStephan Aßmus *b = NULL; 191*9949213aSStephan Aßmus err = GetBitmap(inSource, b); 192*9949213aSStephan Aßmus if (err != B_OK) return err; 193*9949213aSStephan Aßmus GIFSave *gs = new GIFSave(*b, outDestination); 194*9949213aSStephan Aßmus if (gs->fatalerror) { 195*9949213aSStephan Aßmus delete gs; 196*9949213aSStephan Aßmus if (*b != NULL) delete *b; 197*9949213aSStephan Aßmus delete b; 198*9949213aSStephan Aßmus return B_NO_MEMORY; 199*9949213aSStephan Aßmus } 200*9949213aSStephan Aßmus delete gs; 201*9949213aSStephan Aßmus delete *b; 202*9949213aSStephan Aßmus delete b; 203*9949213aSStephan Aßmus } else { // GIF to BBitmap 204*9949213aSStephan Aßmus GIFLoad *gl = new GIFLoad(inSource, outDestination); 205*9949213aSStephan Aßmus if (gl->fatalerror) { 206*9949213aSStephan Aßmus delete gl; 207*9949213aSStephan Aßmus return B_NO_MEMORY; 208*9949213aSStephan Aßmus } 209*9949213aSStephan Aßmus delete gl; 210*9949213aSStephan Aßmus } 211*9949213aSStephan Aßmus 212*9949213aSStephan Aßmus if (debug) { 213*9949213aSStephan Aßmus now = system_time() - now; 214*9949213aSStephan Aßmus printf("Translate() - Translation took %Ld microseconds\n", now); 215*9949213aSStephan Aßmus } 216*9949213aSStephan Aßmus return B_OK; 217*9949213aSStephan Aßmus } 218*9949213aSStephan Aßmus 219*9949213aSStephan Aßmus 220*9949213aSStephan Aßmus GIFTranslator::GIFTranslator() 221*9949213aSStephan Aßmus : BApplication("application/x-vnd.Jules-GIFTranslator") 222*9949213aSStephan Aßmus { 223*9949213aSStephan Aßmus BRect rect(100, 100, 339, 339); 224*9949213aSStephan Aßmus gifwindow = new GIFWindow(rect, "GIF Settings"); 225*9949213aSStephan Aßmus gifwindow->Show(); 226*9949213aSStephan Aßmus } 227*9949213aSStephan Aßmus 228*9949213aSStephan Aßmus 229*9949213aSStephan Aßmus int 230*9949213aSStephan Aßmus main() 231*9949213aSStephan Aßmus { 232*9949213aSStephan Aßmus GIFTranslator myapp; 233*9949213aSStephan Aßmus myapp.Run(); 234*9949213aSStephan Aßmus return 0; 235*9949213aSStephan Aßmus } 236*9949213aSStephan Aßmus 237