gif_map.c

Go to the documentation of this file.
00001 /* --
00002 OpenFX version 2.0 - Modelling, Animation and Rendering Package
00003 Copyright (C) 2000 - 2007 OpenFX Development Team
00004 -- */
00005 
00006 /*  GIF_MAP.C  */
00007 
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <windows.h>
00011 
00012 #include "giflib.h"
00013 
00014 #include "../common/mem.h"
00015 
00016 #define GIFCOLOURS 256
00017 
00018 extern short GIF_decoder(short linewidth);
00019 
00020 
00021 static HINSTANCE hThisInstance;
00022 
00023 static long colourmap_size,brush_size;
00024 static long ScreenXMax,ScreenYMax,ScreenColorBits;
00025 static PixelType *ScanLine;
00026 
00027 
00028 GifColorType GifColourMap[GIFCOLOURS];
00029 GifFileType *GifFile;
00030 unsigned char *decoderline;
00031 static UCHAR *screen;
00032 static BOOL  gif_iLace;
00033 static long  gif_row,gif_inc,gif_width,gif_height;
00034 
00035 static HANDLE Bit_Handle;
00036 
00037 static unsigned char *Bit_Handle_Buffer,*Bit_Handle_Pointer;
00038 
00039 long get_byte(void){
00040   return (long)(*Bit_Handle_Pointer++);
00041 }
00042 
00043 long out_line (unsigned char *pixels, long linelen){
00044  memcpy((screen + gif_row*gif_width),pixels,gif_width);
00045  gif_row+=abs(gif_inc);
00046  if(gif_row >= gif_height){
00047   if     (gif_inc == -8){gif_inc=8; gif_row=4;}
00048   else if(gif_inc ==  8){gif_inc=4; gif_row=2;}
00049   else if(gif_inc ==  4){gif_inc=2; gif_row=1;}
00050  }
00051  return 0;
00052 }
00053 
00054 static long LoadGifImageMap(char *fn, long *xxx, long *yyy, BOOL size_only,
00055    unsigned char *pr, unsigned char *pg, unsigned char *pb){
00056    int map_xmax, map_ymax;
00057    unsigned char *pp,*P=NULL,*pR=NULL,*pG=NULL,*pB=NULL;
00058    DWORD file_size,dwRead;
00059    long i,j,status;
00060    unsigned finished, planes;
00061    unsigned char buffer[16];
00062    if((pR=(unsigned char *)X__Malloc(256)) == NULL)return(0);
00063    if((pG=(unsigned char *)X__Malloc(256)) == NULL)return(0);
00064    if((pB=(unsigned char *)X__Malloc(256)) == NULL)return(0);
00065    status = 0;
00066    Bit_Handle=CreateFile(fn,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
00067       FILE_ATTRIBUTE_READONLY,(HANDLE)NULL);
00068    if(Bit_Handle == INVALID_HANDLE_VALUE)goto BAD1;
00069 
00070    file_size=GetFileSize(Bit_Handle,NULL);
00071    Bit_Handle_Buffer=(unsigned char *)X__Malloc(file_size);
00072    if(Bit_Handle_Buffer == NULL)goto BAD;
00073    Bit_Handle_Pointer=Bit_Handle_Buffer;
00074    if(!ReadFile(Bit_Handle,Bit_Handle_Buffer,file_size,&dwRead,NULL))goto BAD;
00075    if(dwRead != file_size)goto BAD;
00076    if((decoderline = (unsigned char *) X__Malloc (2049)) == NULL)goto BAD;
00077    for (i=0;i<2049;i++)decoderline[i] = (unsigned char) 0;
00078    /* Get the screen description */
00079    gif_row=0; gif_inc=1;
00080    for (i = 0; i < 13; i++)buffer[i] = (unsigned char)get_byte();
00081    if (strncmp((char *)buffer,"GIF87a",3) ||
00082        buffer[3] < '0' || buffer[3] > '9' ||
00083        buffer[4] < '0' || buffer[4] > '9' ||
00084        buffer[5] < 'A' || buffer[5] > 'z' )goto BAD;
00085    planes = ((unsigned)buffer[10] & 0x0F) + 1;
00086    colourmap_size = (int)(1 << planes);
00087    if ((buffer[10] & 0x80) == 0)goto BAD;
00088    for (i = 0; i < colourmap_size ; i++) {
00089      pR[i]  = (unsigned char)get_byte();
00090      pG[i]  = (unsigned char)get_byte();
00091      pB[i]  = (unsigned char)get_byte();
00092    }
00093    finished = FALSE;
00094    while (!finished) {
00095       switch (get_byte()) {
00096          case ';':                /* End of the GIF dataset */
00097             finished = TRUE;
00098             status = 0;
00099             break;
00100          case '!':                /* GIF Extension Block */
00101             get_byte();           /* read (and ignore) the ID */
00102             while ((i = get_byte()) > 0) /* get data len*/
00103             for (j = 0; j < i; j++)
00104                 get_byte(); /* flush data */
00105             break;
00106          case ',': /* Start of image object. get description */
00107             for (i = 0; i < 9; i++) {
00108               buffer[i]=(unsigned char)get_byte();
00109             }
00110             if (status < 0) {
00111                finished = TRUE;
00112                break;
00113             }
00114             if((buffer[8] & 0x40) == 0x40)gif_iLace=TRUE;
00115             else                          gif_iLace=FALSE;
00116             if(gif_iLace)gif_inc = -8;
00117             map_xmax = (short)(buffer[4] | (buffer[5] << 8));
00118             map_ymax = (short)(buffer[6] | (buffer[7] << 8));
00119             brush_size=(long)(map_xmax)*(long)(map_ymax);
00120             gif_width=map_xmax;
00121             gif_height=map_ymax;
00122             *xxx=map_xmax; *yyy=map_ymax;
00123             if(size_only){
00124               X__Free(decoderline);
00125               X__Free(Bit_Handle_Buffer);
00126               X__Free(pR); X__Free(pG); X__Free(pB);
00127               CloseHandle(Bit_Handle);
00128             return 1;
00129             }
00130             if((P=(unsigned char *)X__Malloc(brush_size)) == NULL)
00131               goto BAD;
00132             screen=P;
00133             if(map_xmax > 2048 || map_ymax > 1024)goto BAD;
00134             status = GIF_decoder((short)(map_xmax)); /*put bytes in Buf*/
00135             finished = TRUE;
00136             break;
00137          default:
00138             status = -1;
00139             finished = TRUE;
00140             break;
00141       }
00142    }
00143    X__Free(decoderline);
00144    X__Free(Bit_Handle_Buffer);
00145    CloseHandle(Bit_Handle);
00146    // Now make the 24bit map;
00147 
00148    if(P == NULL)goto BAD1;
00149    if(pr == NULL || pg == NULL || pb == NULL){
00150      goto BAD1;
00151    }  
00152    pp=P;
00153    for(i=0; i < map_ymax; i++) for(j=0; j < map_xmax; j++){
00154      *pr++ = pR[*pp];
00155      *pg++ = pG[*pp];
00156      *pb++ = pB[*pp];
00157      pp++;
00158    }
00159    X__Free(pR); X__Free(pG); X__Free(pB); if(P != NULL)X__Free(P);
00160    return 1;
00161    BAD:
00162    if(Bit_Handle_Buffer != NULL)X__Free(Bit_Handle_Buffer);
00163    CloseHandle(Bit_Handle);
00164    BAD1:
00165    X__Free(pR); X__Free(pG); X__Free(pB); if(P != NULL)X__Free(P);
00166    return 0;
00167 }
00168 
00169 
00170 #if __WATCOMC__
00171 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00172 #else
00173 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00174 #endif
00175   switch (dwReason) {
00176     case DLL_PROCESS_ATTACH: {
00177       hThisInstance=hDLL;
00178       break;
00179     }
00180     case DLL_PROCESS_DETACH:
00181       break;
00182   }
00183   return TRUE;
00184 }
00185 
00186 BOOL _GetExternalImageSize
00187  (char *filename,
00188   long *x,
00189   long *y,
00190   unsigned char *source_buffer){
00191  return LoadGifImageMap(filename,x,y,1,NULL,NULL,NULL);
00192 }
00193 
00194 BOOL _GetExternalImage
00195  (char *filename,
00196   long x, long y,
00197   unsigned char *Red,
00198   unsigned char *Green,
00199   unsigned char *Blue,
00200   unsigned char *source_buffer){
00201  return LoadGifImageMap(filename,&x,&y,0,Red,Green,Blue);
00202 }
00203 
00204 
00205 typedef struct SCREENBUFFER {
00206  unsigned char R,G,B,A;
00207 } fullscreenbuffer;
00208 
00209 BOOL _PutExternalImage
00210  (char *szOutFileName,
00211   long nx, long ny,
00212   long quality,
00213   fullscreenbuffer *image){
00214  return TRUE;
00215 }
00216 
00218 
00219 #define GOOD 2
00220 #define GIFCOLOURS 256
00221 
00222 static unsigned long   *colorstats0;
00223 static unsigned short  *colorstats1;
00224 
00225 static long getcolor(unsigned short crgb, long Npalette);
00226 static void SortColours(long Ngif, long N_colours);
00227 static void UnCompressWordLine(short bufsize, short *buffer,
00228                                unsigned short *output);
00229 
00230 static short compressbuffer[1024];
00231 GifColorType GifColourMap[GIFCOLOURS];
00232 GifFileType *GifFile;
00233 unsigned char *decoderline;
00234 
00235 // read and decompress code
00236 
00237 #ifdef _SUNSTYLE
00238 void  UnCompressWordLine(bufsize,buffer,output)
00239 short bufsize;short *buffer; unsigned short *output;{
00240 #else
00241 void  UnCompressWordLine(short bufsize, short *buffer,unsigned short *output){
00242 #endif
00243  short p,k;
00244  long i;
00245  k=0; while(k < bufsize){
00246    p = *buffer++; k++;
00247    if(p < 0)
00248      for(i=0; i<= -p; i++){*output++ = *buffer++; k++;}
00249    else{
00250      for(i=0; i<=  p; i++) *output++ = *buffer;
00251      buffer++; k++;
00252    }
00253  }
00254 }
00255 
00256 #ifdef _SUNSTYLE
00257 static long distance(argb,brgb) unsigned short argb; unsigned short brgb; {
00258 #else
00259 static long distance(unsigned short argb, unsigned short brgb){
00260 #endif
00261     long b,g,r;
00262     b  = (long)( argb        & 0x1f);
00263     g  = (long)((argb >>  5) & 0x1f);
00264     r  = (long)((argb >> 10) & 0x1f);
00265     b -= (long)( brgb        & 0x1f);
00266     g -= (long)((brgb >>  5) & 0x1f);
00267     r -= (long)((brgb >> 10) & 0x1f);
00268     return (r*r + g*g + b*b);
00269 /*    return labs(r) + labs(g) + labs(b);
00270 */
00271 }
00272 
00273 static long getcolor(unsigned short crgb, long Npalette){
00274   long i,j,best,dist;
00275 /* look for an exact match in the color table (or minimal distance) */
00276     for (i=0; i < Npalette; i++) {
00277        if (colorstats1[i] == crgb) return (i);
00278        if (i == 0) {
00279          best = 0;
00280          dist = distance(colorstats1[i],crgb);
00281        }
00282        else if ((j=distance(colorstats1[i],crgb)) < dist) {
00283          best = i;
00284          dist = j;
00285        }
00286     }
00287     return(best);
00288 }
00289 
00290 static void SortColours(long Ngif, long N_colours){
00291  long i,j,gap,t0,maxdis,used;
00292  unsigned short t1;
00293  for (i = 0; i < N_colours; i++) {
00294      colorstats1[i] = i;
00295  }
00296  for (gap = N_colours/2; gap > 0; gap /=2) {
00297   for (i = gap; i < N_colours; i++) {
00298     for (j = i-gap; j >= 0 &&
00299         colorstats0[j] < colorstats0[j+gap]; j -= gap) {
00300       t0 = colorstats0[j];
00301       t1 = colorstats1[j];
00302       colorstats0[j] = colorstats0[j+gap];
00303       colorstats1[j] = colorstats1[j+gap];
00304       colorstats0[j+gap] = t0;
00305       colorstats1[j+gap] = t1;
00306     }
00307   }
00308  }
00309  for (used = 0; used < N_colours && colorstats0[used] > 0; used++){;}
00310  if (used > Ngif) {
00311   for (maxdis = 2; maxdis < 1024; maxdis *= 2) {
00312    for (i=Ngif/2; i < Ngif; i++) {
00313     for (j = 0; j < i; j++) {
00314       if (distance(colorstats1[i],colorstats1[j])<maxdis) {
00315        for (j=i+1; j< used; j++) {
00316          colorstats0[j-1] = colorstats0[j];
00317          colorstats1[j-1] = colorstats1[j];
00318        }
00319        --used;
00320        --i;
00321        break;
00322       }
00323     }
00324     if (used <= Ngif) break;
00325    }
00326    if (used <= Ngif) break;
00327   }
00328  }
00329  return;
00330 }
00331 
00332 // end of read and uncompress code
00333 // modify this to get a compression 
00334  
00335 static void _BuildGif
00336 (  HWND parent_window, HWND status_window,
00337    int range_f, int range_l, char *flic_file,
00338    char *stem_file,
00339    int ResolutionX,int ResolutionY,
00340    int nCOLOUR, long speed, long tzeros,
00341    unsigned long *cstats0,unsigned short *cstats1){
00342 
00343  char filename[128],speed_string[128],format[64];
00344  long used,cpix,size,type,x_x,y_y;
00345  unsigned short val,Nt,RGB[1024];
00346  int i,j,frame,frames_found;
00347  unsigned char *Screen1,*screen;
00348  FILE *ipf;
00349  colorstats0=cstats0;
00350  colorstats1=cstats1;
00351  if((range_l - range_f) < 3)return;  /* don't animate < 3 frames */
00352  size=ResolutionX*ResolutionY;
00353  if((Screen1 = (unsigned char *)X__Malloc(size)) == NULL){
00354    MessageBox(GetFocus(),(LPCTSTR)"Out of memory",(LPCTSTR)"Flic",MB_OK|MB_TASKMODAL);
00355    return;
00356  }
00357  memset(Screen1,'0',size);
00358  SendMessage(status_window,WM_SETTEXT,0,(LPARAM)"Building color palette");
00359  SortColours(GIFCOLOURS,nCOLOUR);
00360  for(i=0;i<GIFCOLOURS;i++){
00361    GifColourMap[i].Red   = (((colorstats1[i] >> 10) & 0x1F) << 3);
00362    GifColourMap[i].Green = (((colorstats1[i] >>  5) & 0x1F) << 3);
00363    GifColourMap[i].Blue  = (((colorstats1[i]      ) & 0x1F) << 3);
00364  }
00365  for(i=0;i<nCOLOUR;i++)colorstats0[i] = GIFCOLOURS+1;
00366  for(frame=range_f;frame<=range_l;frame++){
00367    sprintf(speed_string,"Building frame %03ld",min(frame,range_l));
00368    SendMessage(status_window,WM_SETTEXT,0,(LPARAM)speed_string);
00369    sprintf(format,"%s%ld%s","%s%0",tzeros,"d.16b");
00370    if(frame < range_l)sprintf(filename,format,stem_file,frame);
00371    else               sprintf(filename,format,stem_file,range_f);
00372 
00373    if((ipf=fopen(strlwr(filename),"rb")) == NULL){
00374      goto FATALOPEN1;
00375    }
00376    if( fread((char *)&x_x,sizeof(long),1,ipf) != 1 ||
00377        fread((char *)&y_y,sizeof(long),1,ipf) != 1)goto FATALREAD;
00378    if(x_x != ResolutionX || y_y != ResolutionY)goto FATALREAD;
00379    screen=Screen1;
00380    for(i=0;i<ResolutionY;i++){
00381      if(fread((char *)&Nt,sizeof(short),1,ipf) != 1)goto FATALREAD;
00382      if(Nt == 0){
00383        if(fread((char *)RGB,sizeof(unsigned short),ResolutionX,ipf)
00384           != ResolutionX)goto FATALREAD;
00385      }
00386      else{
00387        if(fread((char *)compressbuffer,sizeof(short),Nt,ipf) != Nt)
00388          goto FATALREAD;
00389        UnCompressWordLine(Nt,compressbuffer,RGB);
00390      }
00391      for (j = 0; j < ResolutionX; j++) {
00392        val=RGB[j];
00393        if((cpix = (long)colorstats0[(long)val]) > GIFCOLOURS){
00394          cpix=getcolor(val,GIFCOLOURS);
00395          colorstats0[(long)val]=(unsigned long)cpix;
00396        }
00397        *screen++ = (unsigned char)cpix;
00398      }
00399    }
00400    fclose(ipf);
00401 
00403    if(frame == range_f){  // first frame
00404      if((GifFile=EGifOpenFileName((char *)strlwr(flic_file),FALSE,1)) == NULL)
00405        goto FATALWRITE;
00406      if(EGifPutScreenDesc(GifFile,ResolutionX,ResolutionY,8,
00407         0, 8, GifColourMap) == ERROR)goto FATALWRITE;
00408      if(EGifPutBrowserControlDesc(GifFile,0) == ERROR)goto FATALWRITE;
00409    }
00410    else if(frame == range_l){
00411      if(EGifCloseFile(GifFile) == ERROR) {
00412        goto FATALWRITE;
00413      }
00414    }
00415    if(frame >= range_f && frame < range_l){ /* every image */
00416      if(EGifPutControlDesc(GifFile,1,0,2,0) == ERROR){
00417        goto FATALWRITE;
00418      }
00419      if(EGifPutImageDesc(GifFile,0,0,ResolutionX,ResolutionY,FALSE,1,
00420          NULL) == ERROR){
00421        goto FATALWRITE;
00422      }
00423      for (i=0,screen=Screen1;i<ResolutionY;i++,screen += ResolutionX) {
00424        if (EGifPutLine(GifFile,(PixelType *)screen,ResolutionX) == ERROR) {
00425          goto FATALWRITE;
00426        }
00427      }
00428    }
00429  }
00431 
00432  if(MessageBox(GetFocus(),(LPCTSTR)"Delete Temporary files",
00433           (LPCTSTR)"Flic",MB_YESNO|MB_TASKMODAL|MB_ICONQUESTION) == IDYES){
00434    FILE *FF;
00435    sprintf(format,"%s%ld%s","%s%0",tzeros,"d.16b");
00436    sprintf(filename,format,stem_file,range_f);
00437    if((FF=fopen(filename,"r")) != NULL){
00438      fclose(FF);
00439      for(i=range_f;i<range_l;i++){
00440        sprintf(format,"%s%ld%s","%s%0",tzeros,"d.16b");
00441        sprintf(filename,format,stem_file,i);
00442        if(DeleteFile(filename) == FALSE){
00443          MessageBox(GetFocus(),(LPCTSTR)strcat(filename," Failed during delete"),
00444          (LPCTSTR)"Flic",MB_OK|MB_TASKMODAL);
00445          break;
00446        }
00447      }
00448    }
00449    else MessageBox(GetFocus(),(LPCTSTR)"Failed to delete temporary files",
00450           (LPCTSTR)"Flic",MB_OK|MB_TASKMODAL);
00451  }
00452  goto XXIT;
00453  FATALWRITE:
00454    MessageBox(GetFocus(),(LPCTSTR)"Failed on flic write",(LPCTSTR)"Error",MB_OK|MB_TASKMODAL);
00455    fclose(ipf); goto XXIT;
00456  FATALREAD:
00457    MessageBox(GetFocus(),(LPCTSTR)"Read failed on temporary file",(LPCTSTR)"Error",MB_OK|MB_TASKMODAL);
00458    fclose(ipf); goto XXIT;
00459  FATALOPEN1:
00460    MessageBox(GetFocus(),(LPCTSTR)"Temporary file open failed",(LPCTSTR)"Error",MB_OK|MB_TASKMODAL);
00461    goto XXIT;
00462  XXIT:
00463  X__Free(Screen1);
00464 }

Generated on Sun Apr 27 14:20:13 2014 for OpenFX by  doxygen 1.5.6