19949213aSStephan Aßmus //////////////////////////////////////////////////////////////////////////////// 29949213aSStephan Aßmus // 39949213aSStephan Aßmus // File: GIFTranslator.cpp 49949213aSStephan Aßmus // 59949213aSStephan Aßmus // Date: December 1999 69949213aSStephan Aßmus // 79949213aSStephan Aßmus // Author: Daniel Switkin 89949213aSStephan Aßmus // 99949213aSStephan Aßmus // Copyright 2003 (c) by Daniel Switkin. This file is made publically available 109949213aSStephan Aßmus // under the BSD license, with the stipulations that this complete header must 119949213aSStephan Aßmus // remain at the top of the file indefinitely, and credit must be given to the 129949213aSStephan Aßmus // original author in any about box using this software. 139949213aSStephan Aßmus // 149949213aSStephan Aßmus //////////////////////////////////////////////////////////////////////////////// 159949213aSStephan Aßmus 169949213aSStephan Aßmus #include "GIFTranslator.h" 179949213aSStephan Aßmus #include "GIFWindow.h" 189949213aSStephan Aßmus #include "GIFView.h" 199949213aSStephan Aßmus #include "GIFSave.h" 209949213aSStephan Aßmus #include "GIFLoad.h" 219949213aSStephan Aßmus #include <ByteOrder.h> 229949213aSStephan Aßmus #include <TypeConstants.h> 239949213aSStephan Aßmus #include <DataIO.h> 249949213aSStephan Aßmus #include <TranslatorAddOn.h> 259949213aSStephan Aßmus #include <TranslatorFormats.h> 269949213aSStephan Aßmus #include <InterfaceDefs.h> 279949213aSStephan Aßmus #include <stdio.h> 289949213aSStephan Aßmus #include <stdlib.h> 299949213aSStephan Aßmus #include <string.h> 309949213aSStephan Aßmus 319949213aSStephan Aßmus #ifndef GIF_TYPE 329949213aSStephan Aßmus #define GIF_TYPE 'GIF ' 339949213aSStephan Aßmus #endif 349949213aSStephan Aßmus 359949213aSStephan Aßmus // This global will be externed in other files - set once here 369949213aSStephan Aßmus // for the entire translator 379949213aSStephan Aßmus bool debug = false; 389949213aSStephan Aßmus 399949213aSStephan Aßmus bool DetermineType(BPositionIO *source, bool *is_gif); 409949213aSStephan Aßmus status_t GetBitmap(BPositionIO *in, BBitmap **out); 419949213aSStephan Aßmus 429949213aSStephan Aßmus /* Required data */ 439949213aSStephan Aßmus char translatorName[] = "GIF Images"; 449949213aSStephan Aßmus char translatorInfo[] = "GIF image translator v1.4"; 459949213aSStephan Aßmus int32 translatorVersion = 0x140; 469949213aSStephan Aßmus 479949213aSStephan Aßmus translation_format inputFormats[] = { 489949213aSStephan Aßmus { GIF_TYPE, B_TRANSLATOR_BITMAP, 0.8, 0.8, "image/gif", "GIF image" }, 499949213aSStephan Aßmus { B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.3, 0.3, "image/x-be-bitmap", "Be Bitmap image" }, 509949213aSStephan Aßmus { 0 } 519949213aSStephan Aßmus }; 529949213aSStephan Aßmus 539949213aSStephan Aßmus translation_format outputFormats[] = { 549949213aSStephan Aßmus { GIF_TYPE, B_TRANSLATOR_BITMAP, 0.8, 0.8, "image/gif", "GIF image" }, 559949213aSStephan Aßmus { B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.3, 0.3, "image/x-be-bitmap", "Be Bitmap image" }, 569949213aSStephan Aßmus { 0 } 579949213aSStephan Aßmus }; 589949213aSStephan Aßmus 599949213aSStephan Aßmus 609949213aSStephan Aßmus /* Build a pretty view for DataTranslations */ 619949213aSStephan Aßmus status_t 629949213aSStephan Aßmus MakeConfig(BMessage *ioExtension, BView **outView, BRect *outExtent) 639949213aSStephan Aßmus { 649949213aSStephan Aßmus outExtent->Set(0, 0, 239, 239); 659949213aSStephan Aßmus GIFView *gifview = new GIFView(*outExtent, "TranslatorView"); 669949213aSStephan Aßmus *outView = gifview; 679949213aSStephan Aßmus return B_OK; 689949213aSStephan Aßmus } 699949213aSStephan Aßmus 709949213aSStephan Aßmus 719949213aSStephan Aßmus /* Look at first few bytes in stream to determine type - throw it back 729949213aSStephan Aßmus if it is not a GIF or a BBitmap that we understand */ 739949213aSStephan Aßmus bool 749949213aSStephan Aßmus DetermineType(BPositionIO *source, bool *is_gif) 759949213aSStephan Aßmus { 769949213aSStephan Aßmus unsigned char header[7]; 779949213aSStephan Aßmus *is_gif = true; 789949213aSStephan Aßmus if (source->Read(header, 6) != 6) return false; 799949213aSStephan Aßmus header[6] = 0x00; 809949213aSStephan Aßmus 819949213aSStephan Aßmus if (strcmp((char *)header, "GIF87a") != 0 && strcmp((char *)header, "GIF89a") != 0) { 829949213aSStephan Aßmus *is_gif = false; 839949213aSStephan Aßmus int32 magic = (header[0] << 24) + (header[1] << 16) + (header[2] << 8) + header[3]; 849949213aSStephan Aßmus if (magic != B_TRANSLATOR_BITMAP) return false; 859949213aSStephan Aßmus source->Seek(5 * 4 - 2, SEEK_CUR); 869949213aSStephan Aßmus color_space cs; 879949213aSStephan Aßmus if (source->Read(&cs, 4) != 4) return false; 889949213aSStephan Aßmus cs = (color_space)B_BENDIAN_TO_HOST_INT32(cs); 899949213aSStephan Aßmus if (cs != B_RGB32 && cs != B_RGBA32 && cs != B_RGB32_BIG && cs != B_RGBA32_BIG) return false; 909949213aSStephan Aßmus } 919949213aSStephan Aßmus 929949213aSStephan Aßmus source->Seek(0, SEEK_SET); 939949213aSStephan Aßmus return true; 949949213aSStephan Aßmus } 959949213aSStephan Aßmus 969949213aSStephan Aßmus 979949213aSStephan Aßmus /* Dump data from stream into a BBitmap */ 989949213aSStephan Aßmus status_t 999949213aSStephan Aßmus GetBitmap(BPositionIO *in, BBitmap **out) 1009949213aSStephan Aßmus { 1019949213aSStephan Aßmus TranslatorBitmap header; 1029949213aSStephan Aßmus 1039949213aSStephan Aßmus status_t err = in->Read(&header, sizeof(header)); 1049949213aSStephan Aßmus if (err != sizeof(header)) 1059949213aSStephan Aßmus return B_IO_ERROR; 1069949213aSStephan Aßmus 1079949213aSStephan Aßmus header.magic = B_BENDIAN_TO_HOST_INT32(header.magic); 1089949213aSStephan Aßmus header.bounds.left = B_BENDIAN_TO_HOST_FLOAT(header.bounds.left); 1099949213aSStephan Aßmus header.bounds.top = B_BENDIAN_TO_HOST_FLOAT(header.bounds.top); 1109949213aSStephan Aßmus header.bounds.right = B_BENDIAN_TO_HOST_FLOAT(header.bounds.right); 1119949213aSStephan Aßmus header.bounds.bottom = B_BENDIAN_TO_HOST_FLOAT(header.bounds.bottom); 1129949213aSStephan Aßmus header.rowBytes = B_BENDIAN_TO_HOST_INT32(header.rowBytes); 1139949213aSStephan Aßmus header.colors = (color_space)B_BENDIAN_TO_HOST_INT32(header.colors); 1149949213aSStephan Aßmus header.dataSize = B_BENDIAN_TO_HOST_INT32(header.dataSize); 1159949213aSStephan Aßmus 1169949213aSStephan Aßmus BBitmap *bitmap = new BBitmap(header.bounds, header.colors); 1179949213aSStephan Aßmus *out = bitmap; 1189949213aSStephan Aßmus if (bitmap == NULL) return B_NO_MEMORY; 1199949213aSStephan Aßmus unsigned char *bits = (unsigned char *)bitmap->Bits(); 1209949213aSStephan Aßmus if (bits == NULL) { 1219949213aSStephan Aßmus delete bitmap; 1229949213aSStephan Aßmus return B_NO_MEMORY; 1239949213aSStephan Aßmus } 1249949213aSStephan Aßmus err = in->Read(bits, header.dataSize); 1259949213aSStephan Aßmus if (err == (status_t)header.dataSize) return B_OK; 1269949213aSStephan Aßmus else return B_IO_ERROR; 1279949213aSStephan Aßmus } 1289949213aSStephan Aßmus 1299949213aSStephan Aßmus 1309949213aSStephan Aßmus /* Required Identify function - may need to read entire header, not sure */ 1319949213aSStephan Aßmus status_t 1329949213aSStephan Aßmus Identify(BPositionIO *inSource, const translation_format *inFormat, 1339949213aSStephan Aßmus BMessage *ioExtension, translator_info *outInfo, uint32 outType) 1349949213aSStephan Aßmus { 1359949213aSStephan Aßmus 1369949213aSStephan Aßmus const char *debug_text = getenv("GIF_TRANSLATOR_DEBUG"); 1379949213aSStephan Aßmus if ((debug_text != NULL) && (atoi(debug_text) != 0)) debug = true; 1389949213aSStephan Aßmus 1399949213aSStephan Aßmus if (outType == 0) outType = B_TRANSLATOR_BITMAP; 1409949213aSStephan Aßmus if (outType != GIF_TYPE && outType != B_TRANSLATOR_BITMAP) return B_NO_TRANSLATOR; 1419949213aSStephan Aßmus 1429949213aSStephan Aßmus bool is_gif; 1439949213aSStephan Aßmus if (!DetermineType(inSource, &is_gif)) return B_NO_TRANSLATOR; 1449949213aSStephan Aßmus if (!is_gif && inFormat != NULL && inFormat->type != B_TRANSLATOR_BITMAP) 1459949213aSStephan Aßmus return B_NO_TRANSLATOR; 1469949213aSStephan Aßmus 1479949213aSStephan Aßmus outInfo->group = B_TRANSLATOR_BITMAP; 1489949213aSStephan Aßmus if (is_gif) { 1499949213aSStephan Aßmus outInfo->type = GIF_TYPE; 1509949213aSStephan Aßmus outInfo->quality = 0.8; 1519949213aSStephan Aßmus outInfo->capability = 0.8; 1529949213aSStephan Aßmus strcpy(outInfo->name, "GIF image"); 1539949213aSStephan Aßmus strcpy(outInfo->MIME, "image/gif"); 1549949213aSStephan Aßmus } 1559949213aSStephan Aßmus else { 1569949213aSStephan Aßmus outInfo->type = B_TRANSLATOR_BITMAP; 1579949213aSStephan Aßmus outInfo->quality = 0.3; 1589949213aSStephan Aßmus outInfo->capability = 0.3; 1599949213aSStephan Aßmus strcpy(outInfo->name, "Be Bitmap image"); 1609949213aSStephan Aßmus strcpy(outInfo->MIME, "image/x-be-bitmap"); 1619949213aSStephan Aßmus } 1629949213aSStephan Aßmus return B_OK; 1639949213aSStephan Aßmus } 1649949213aSStephan Aßmus 1659949213aSStephan Aßmus 1669949213aSStephan Aßmus /* Main required function - assumes that an incoming GIF must be translated 1679949213aSStephan Aßmus to a BBitmap, and vice versa - this could be improved */ 1689949213aSStephan Aßmus status_t 1699949213aSStephan Aßmus Translate(BPositionIO *inSource, const translator_info *inInfo, 1709949213aSStephan Aßmus BMessage *ioExtension, uint32 outType, BPositionIO *outDestination) 1719949213aSStephan Aßmus { 1729949213aSStephan Aßmus 1739949213aSStephan Aßmus const char *debug_text = getenv("GIF_TRANSLATOR_DEBUG"); 1749949213aSStephan Aßmus if ((debug_text != NULL) && (atoi(debug_text) != 0)) debug = true; 1759949213aSStephan Aßmus 1769949213aSStephan Aßmus if (outType == 0) outType = B_TRANSLATOR_BITMAP; 1779949213aSStephan Aßmus if (outType != GIF_TYPE && outType != B_TRANSLATOR_BITMAP) { 1789949213aSStephan Aßmus return B_NO_TRANSLATOR; 1799949213aSStephan Aßmus } 1809949213aSStephan Aßmus 1819949213aSStephan Aßmus bool is_gif; 1829949213aSStephan Aßmus if (!DetermineType(inSource, &is_gif)) return B_NO_TRANSLATOR; 1839949213aSStephan Aßmus if (!is_gif && inInfo->type != B_TRANSLATOR_BITMAP) return B_NO_TRANSLATOR; 1849949213aSStephan Aßmus 1859949213aSStephan Aßmus status_t err = B_OK; 1869949213aSStephan Aßmus bigtime_t now = system_time(); 1879949213aSStephan Aßmus // Going from BBitmap to GIF 1889949213aSStephan Aßmus if (!is_gif) { 189*7bc02c61SStefano Ceccherini BBitmap *bitmap = NULL; 190*7bc02c61SStefano Ceccherini err = GetBitmap(inSource, &bitmap); 191*7bc02c61SStefano Ceccherini if (err != B_OK) 192*7bc02c61SStefano Ceccherini return err; 193*7bc02c61SStefano Ceccherini GIFSave *gs = new GIFSave(bitmap, outDestination); 1949949213aSStephan Aßmus if (gs->fatalerror) { 1959949213aSStephan Aßmus delete gs; 196*7bc02c61SStefano Ceccherini delete bitmap; 1979949213aSStephan Aßmus return B_NO_MEMORY; 1989949213aSStephan Aßmus } 1999949213aSStephan Aßmus delete gs; 200*7bc02c61SStefano Ceccherini delete bitmap; 2019949213aSStephan Aßmus } else { // GIF to BBitmap 2029949213aSStephan Aßmus GIFLoad *gl = new GIFLoad(inSource, outDestination); 2039949213aSStephan Aßmus if (gl->fatalerror) { 2049949213aSStephan Aßmus delete gl; 2059949213aSStephan Aßmus return B_NO_MEMORY; 2069949213aSStephan Aßmus } 2079949213aSStephan Aßmus delete gl; 2089949213aSStephan Aßmus } 2099949213aSStephan Aßmus 2109949213aSStephan Aßmus if (debug) { 2119949213aSStephan Aßmus now = system_time() - now; 2129949213aSStephan Aßmus printf("Translate() - Translation took %Ld microseconds\n", now); 2139949213aSStephan Aßmus } 2149949213aSStephan Aßmus return B_OK; 2159949213aSStephan Aßmus } 2169949213aSStephan Aßmus 2179949213aSStephan Aßmus 2189949213aSStephan Aßmus GIFTranslator::GIFTranslator() 2199949213aSStephan Aßmus : BApplication("application/x-vnd.Jules-GIFTranslator") 2209949213aSStephan Aßmus { 2219949213aSStephan Aßmus BRect rect(100, 100, 339, 339); 2229949213aSStephan Aßmus gifwindow = new GIFWindow(rect, "GIF Settings"); 2239949213aSStephan Aßmus gifwindow->Show(); 2249949213aSStephan Aßmus } 2259949213aSStephan Aßmus 2269949213aSStephan Aßmus 2279949213aSStephan Aßmus int 2289949213aSStephan Aßmus main() 2299949213aSStephan Aßmus { 2309949213aSStephan Aßmus GIFTranslator myapp; 2319949213aSStephan Aßmus myapp.Run(); 2329949213aSStephan Aßmus return 0; 2339949213aSStephan Aßmus } 2349949213aSStephan Aßmus 235