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