Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OpenGIF.cpp

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <string.h>
00003 extern "C" {
00004   #include <gif_lib.h>
00005 }
00006 #include "Debug.h"
00007 #include "Open.h"
00008 #include "SimpleImage.h"
00009 #include "Utility.h"
00010 
00011 
00012 namespace corona {
00013 
00014   int InputFunc(GifFileType* gif, GifByteType* bytes, int size) {
00015     File* file = (File*)gif->UserData;
00016     return file->read(bytes, size);
00017   }
00018 
00019   Image* OpenGIF(File* file) {
00020     COR_GUARD("OpenGIF");
00021 
00022     // open GIF file
00023     GifFileType* gif = DGifOpen(file, InputFunc);
00024     if (!gif) {
00025       COR_LOG("DGifOpen failed");
00026       return 0;
00027     }
00028 
00029     // read GIF image
00030     if (DGifSlurp(gif) != GIF_OK) {
00031       COR_LOG("DGifSlurp failed");
00032       DGifCloseFile(gif);
00033       return 0;
00034     }
00035     ColorMapObject* cmap = gif->SColorMap;
00036 
00037     // validate attributes
00038     if (cmap == 0 ||
00039         gif->ImageCount < 1 ||
00040         cmap->ColorCount != (1 << cmap->BitsPerPixel))
00041     {
00042       COR_IF_DEBUG {
00043         char str[1024];
00044         sprintf(str, "incorrect gif attributes:\n");
00045         sprintf(str + strlen(str), " ImageCount: %d\n", gif->ImageCount);
00046         if (cmap) {
00047           sprintf(str + strlen(str), " BitsPerPixel: %d\n", cmap->BitsPerPixel);
00048           sprintf(str + strlen(str), " ColorCount: %d\n", cmap->ColorCount);
00049         }
00050         COR_LOG(str);
00051       }
00052       
00053       DGifCloseFile(gif);
00054       return 0;
00055     }
00056 
00057     // use the first frame of the animation
00058     SavedImage* gif_image = gif->SavedImages + 0;
00059 
00060     const int width = gif->SWidth;
00061     const int height = gif->SHeight;
00062     auto_array<byte> image(new byte[width * height]);
00063     auto_array<RGBA> palette(new RGBA[256]);
00064 
00065     // look for the transparent color extension
00066     int transparent = -1;
00067     for (int i = 0; i < gif_image->ExtensionBlockCount; ++i) {
00068       ExtensionBlock* eb = gif_image->ExtensionBlocks + i;
00069       if (eb->Function == 0xF9 && 
00070           eb->ByteCount == 4) {
00071         bool has_transparency = ((eb->Bytes[0] & 1) == 1);
00072         if (has_transparency) {
00073           transparent = eb->Bytes[3];
00074         }
00075       }
00076     }
00077 
00078     // copy over the palette
00079     memset(palette, 0, 256 * 4);
00080     for (int i = 0; i < cmap->ColorCount; ++i) {
00081       palette[i].red   = cmap->Colors[i].Red;
00082       palette[i].green = cmap->Colors[i].Green;
00083       palette[i].blue  = cmap->Colors[i].Blue;
00084       palette[i].alpha = (transparent == i ? 0 : 255);
00085     }
00086 
00087     byte* in = (byte*)gif_image->RasterBits;
00088     byte* out = image;
00089     if (gif->Image.Interlace) {
00090 
00091       // deinterlace
00092 
00093       // group 1 - every 8th row, starting with row 0
00094       for (int row = 0; row < height; row += 8) {
00095         memcpy(out + width * row, in, width);
00096         in += width;
00097       }
00098 
00099       // group 2 - every 8th row, starting with row 4
00100       for (int row = 4; row < height; row += 8) {
00101         memcpy(out + width * row, in, width);
00102         in += width;
00103       }
00104 
00105       // group 3 - every 4th row, starting with row 2
00106       for (int row = 2; row < height; row += 4) {
00107         memcpy(out + width * row, in, width);
00108         in += width;
00109       }
00110 
00111       for (int row = 1; row < height; row += 2) {
00112         memcpy(out + width * row, in, width);
00113         in += width;
00114       }
00115 
00116     } else {
00117       memcpy(out, in, width * height);
00118     }
00119 
00120     DGifCloseFile(gif);
00121     return new SimpleImage(width, height, PF_I8, image.release(),
00122                            (byte*)palette.release(), 256, PF_R8G8B8A8);
00123   }
00124 
00125 }

Generated on Thu Oct 2 12:59:31 2003 for corona by doxygen1.3-rc1