00001
00002
00003
00004
00005
00006
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
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 ';':
00097 finished = TRUE;
00098 status = 0;
00099 break;
00100 case '!':
00101 get_byte();
00102 while ((i = get_byte()) > 0)
00103 for (j = 0; j < i; j++)
00104 get_byte();
00105 break;
00106 case ',':
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));
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
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
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
00270
00271 }
00272
00273 static long getcolor(unsigned short crgb, long Npalette){
00274 long i,j,best,dist;
00275
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
00333
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;
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){
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){
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 }