AVI_DLL.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 /* FILE AVI_DLL.C    DLL to build AVI video movie from TEMPORARY files */
00007 
00008 
00009 #include <stdlib.h>
00010 #include <stdio.h>
00011 #include <windows.h>
00012 
00013 #ifdef __X__NT__
00014 #define X__Malloc(s)    LocalAlloc(LMEM_FIXED,s)
00015 #define X__Free(p)      LocalFree((HLOCAL)p)
00016 #define X__Realloc(p,s) LocalReAlloc((HLOCAL)p,s,LMEM_MOVEABLE)
00017 #else
00018 #define X__Malloc(s)    GlobalAlloc(GMEM_FIXED,s)
00019 #define X__Free(p)      GlobalFree((HGLOBAL)p)
00020 #define X__Realloc(p,s) GlobalReAlloc((HGLOBAL)p,s,GMEM_MOVEABLE)
00021 #endif
00022 #if !__WATCOMC__
00023 #define fflush(a) 0
00024 #endif
00025 
00026 extern void configureAVIfile(HWND, char *, void *);
00027 extern void openAVIfile(char *Name, LPBITMAPINFOHEADER lpbi, int compress, long speed);
00028 extern void appendAVIfile(LPBITMAPINFOHEADER lpbi);
00029 extern void closeAVIfile(void);
00030 
00031 #if __X__MIPS__
00032 BOOL WINAPI _CRT_INIT(HINSTANCE ,DWORD , LPVOID );
00033 #endif
00034 
00035 static unsigned long   *colorstats0;
00036 static unsigned short  *colorstats1;
00037 static short compressbuffer[1024];
00038 static char     linebuffer2[1024];
00039 static unsigned char linebuffer[2048];
00040 static unsigned char gif_p_red[256],gif_p_green[256],gif_p_blue[256];
00041 static LPSTR     lpBitmapHeader = NULL;
00042 static LPSTR     lpBitmapBits   = NULL;
00043 static RGBQUAD   *pRgb          = NULL;
00044 static int x4_size;
00045 
00046 #define GOOD 2
00047 #define GIFCOLOURS 256
00048 #define ALIGNULONG(i)   ((i+3)/4*4)
00049 
00050 long getcolor(unsigned short crgb, long Npalette);
00051 void SortColours(long Ngif, long N_colours);
00052 void UnCompressWordLine(short bufsize, short *buffer,
00053                          unsigned short *output);
00054 
00055 static void Cshort(unsigned char *c, short v){
00056   unsigned char ch,cl;
00057   ch = (unsigned char)(v >> 8);
00058   cl = (unsigned char)(v & 0x00ff);
00059   *c++ = cl;
00060   *c++ = ch;
00061 }
00062 
00063 static void Clong(unsigned char *c, long v){
00064   unsigned char ch,c2,c1,cl;
00065   ch = (unsigned char)((v >> 24) & 0x000000ff);
00066   c2 = (unsigned char)((v >> 16) & 0x000000ff);
00067   c1 = (unsigned char)((v >>  8) & 0x000000ff);
00068   cl = (unsigned char)(v & 0x000000ff);
00069   *c++ = cl;
00070   *c++ = c1;
00071   *c++ = c2;
00072   *c++ = ch;
00073 }
00074 
00075 static void Ashort(unsigned char *c,short v){
00076   unsigned char ch,cl;
00077   short ah,al,a;
00078   al = (short)(*c);
00079   ah = (short)(*(c+1));
00080   a  = (ah << 8) | al;
00081   a += v;
00082   ch = (unsigned char)(a >> 8);
00083   cl = (unsigned char)(a & 0x00ff);
00084   *c     = cl;
00085   *(c+1) = ch;
00086 }
00087 
00088 static void Along(unsigned char *c,long v){
00089   unsigned char ch,c2,c1,cl;
00090   long ah,a2,a1,al,a;
00091   al = (long)(*c);
00092   a1 = (long)(*(c+1));
00093   a2 = (long)(*(c+2));
00094   ah = (long)(*(c+3));
00095   a  = (ah << 24) | (a2 << 16) | (a1 << 8) | al;
00096   a += v;
00097   ch = (unsigned char)((a >> 24) & 0x000000ff);
00098   c2 = (unsigned char)((a >> 16) & 0x000000ff);
00099   c1 = (unsigned char)((a >>  8) & 0x000000ff);
00100   cl = (unsigned char)(a & 0x000000ff);
00101   *c     = cl;
00102   *(c+1) = c1;
00103   *(c+2) = c2;
00104   *(c+3) = ch;
00105 }
00106 
00107 static long Tlong(unsigned char *c){
00108   long ah,a2,a1,al,a;
00109   al = (long)(*c);
00110   a1 = (long)(*(c+1));
00111   a2 = (long)(*(c+2));
00112   ah = (long)(*(c+3));
00113   a  = (ah << 24) | (a2 << 16) | (a1 << 8) | al;
00114   return a;
00115 }
00116 
00117 static short Tshort(unsigned char *c){
00118   short ah,al,a;
00119   al = (short)(*c);
00120   ah = (short)(*(c+1));
00121   a  = (ah << 8) | al;
00122   return a;
00123 }
00124 
00125 // read and decompress code
00126 
00127 #ifdef _SUNSTYLE
00128 void  UnCompressWordLine(bufsize,buffer,output)
00129 short bufsize;short *buffer; unsigned short *output;{
00130 #else
00131 void  UnCompressWordLine(short bufsize, short *buffer,unsigned short *output){
00132 #endif
00133  short p,k;
00134  long i;
00135  k=0; while(k < bufsize){
00136    p = *buffer++; k++;
00137    if(p < 0)
00138      for(i=0; i<= -p; i++){*output++ = *buffer++; k++;}
00139    else{
00140      for(i=0; i<=  p; i++) *output++ = *buffer;
00141      buffer++; k++;
00142    }
00143  }
00144 }
00145 
00146 #ifdef _SUNSTYLE
00147 static long distance(argb,brgb) unsigned short argb; unsigned short brgb; {
00148 #else
00149 static long distance(unsigned short argb, unsigned short brgb){
00150 #endif
00151     long b,g,r;
00152     b  = (long)( argb        & 0x1f);
00153     g  = (long)((argb >>  5) & 0x1f);
00154     r  = (long)((argb >> 10) & 0x1f);
00155     b -= (long)( brgb        & 0x1f);
00156     g -= (long)((brgb >>  5) & 0x1f);
00157     r -= (long)((brgb >> 10) & 0x1f);
00158     return (r*r + g*g + b*b);
00159 /*    return labs(r) + labs(g) + labs(b);
00160 */
00161 }
00162 
00163 #ifdef _SUNSTYLE
00164 long getcolor(crgb, Npalette) unsigned short crgb; long Npalette; {
00165 #else
00166 long getcolor(unsigned short crgb, long Npalette){
00167 #endif
00168   long i,j,best,dist;
00169 /* look for an exact match in the color table (or minimal distance) */
00170     for (i=0; i < Npalette; i++) {
00171        if (colorstats1[i] == crgb) return (i);
00172        if (i == 0) {
00173          best = 0;
00174          dist = distance(colorstats1[i],crgb);
00175        }
00176        else if ((j=distance(colorstats1[i],crgb)) < dist) {
00177          best = i;
00178          dist = j;
00179        }
00180     }
00181     return(best);
00182 }
00183 
00184 #ifdef _SUNSTYLE
00185 void SortColours(Ngif,N_colours) long Ngif; long N_colours; {
00186 #else
00187 void SortColours(long Ngif, long N_colours){
00188 #endif
00189  long i,j,gap,t0,maxdis,used;
00190  unsigned short t1;
00191  for (i = 0; i < N_colours; i++) {
00192      colorstats1[i] = i;
00193  }
00194  for (gap = N_colours/2; gap > 0; gap /=2) {
00195   for (i = gap; i < N_colours; i++) {
00196     for (j = i-gap; j >= 0 &&
00197         colorstats0[j] < colorstats0[j+gap]; j -= gap) {
00198       t0 = colorstats0[j];
00199       t1 = colorstats1[j];
00200       colorstats0[j] = colorstats0[j+gap];
00201       colorstats1[j] = colorstats1[j+gap];
00202       colorstats0[j+gap] = t0;
00203       colorstats1[j+gap] = t1;
00204     }
00205   }
00206  }
00207  for (used = 0; used < N_colours && colorstats0[used] > 0; used++){;}
00208  if (used > Ngif) {
00209   for (maxdis = 2; maxdis < 1024; maxdis *= 2) {
00210    for (i=Ngif/2; i < Ngif; i++) {
00211     for (j = 0; j < i; j++) {
00212       if (distance(colorstats1[i],colorstats1[j])<maxdis) {
00213        for (j=i+1; j< used; j++) {
00214          colorstats0[j-1] = colorstats0[j];
00215          colorstats1[j-1] = colorstats1[j];
00216        }
00217        --used;
00218        --i;
00219        break;
00220       }
00221     }
00222     if (used <= Ngif) break;
00223    }
00224    if (used <= Ngif) break;
00225   }
00226  }
00227  return;
00228 }
00229 
00230 // end of read and uncompress code
00231 
00232 static BOOL MakeBitmapStructure(int x_size, int y_size){
00233  int i;
00234  long imagesize;
00235  LPBITMAPINFOHEADER lpbi;
00236  x4_size = ALIGNULONG(x_size);
00237  imagesize = (DWORD)x4_size*(DWORD)y_size;
00238  lpBitmapHeader = (LPSTR)X__Malloc((long)sizeof(BITMAPINFOHEADER)
00239                                 +256L*sizeof(RGBQUAD)+imagesize);
00240  if(lpBitmapHeader == NULL){
00241    return FALSE;
00242  }
00243  lpbi=(LPBITMAPINFOHEADER)lpBitmapHeader;
00244  lpbi->biSize=sizeof(BITMAPINFOHEADER);
00245  lpbi->biWidth=(DWORD)x_size;
00246  lpbi->biHeight=(DWORD)y_size;
00247  lpbi->biPlanes=1;
00248  lpbi->biBitCount=8;
00249  lpbi->biCompression=BI_RGB;
00250  lpbi->biSizeImage=(DWORD)imagesize;
00251  lpbi->biXPelsPerMeter=0;
00252  lpbi->biYPelsPerMeter=0;
00253  lpbi->biClrUsed=256;
00254  lpbi->biClrImportant=256;
00255  pRgb=(RGBQUAD *)((LPSTR)lpbi + lpbi->biSize);
00256  for(i=0;i<256;i++){
00257    pRgb[i].rgbRed = gif_p_red[i]      << 2;
00258    pRgb[i].rgbGreen = gif_p_green[i]  << 2;
00259    pRgb[i].rgbBlue = gif_p_blue[i]    << 2;
00260  }
00261  lpBitmapBits=(LPSTR)(lpbi);
00262  lpBitmapBits += (lpbi->biSize+256*sizeof(RGBQUAD));
00263  if(lpBitmapBits == NULL){
00264    return FALSE;
00265  }
00266  memset(lpBitmapBits,0,imagesize);
00267  return TRUE;
00268 }
00269 
00270 static void MakeBitmapImage(unsigned char *S,int x, int y){
00271  int i,j;
00272  unsigned char *B,*s;
00273  B=(unsigned char *)lpBitmapBits;
00274  for(i=0;i<y;i++){
00275    s=(S+(y-i-1)*x);
00276    for(j=0;j<x;j++){
00277      *B++ = *s++;
00278    }
00279  }
00280 }
00281 
00282 /* range_l is last included frame+1 */
00283 
00284 #if __SC__
00285 //void CALLBACK _BuildAvi
00286 #else
00287 void _BuildAvi
00288 #endif
00289   (HWND parent_window, HWND status_window,
00290    int range_f, int range_l, char *flic_file,
00291    char *stem_file,
00292    int ResolutionX,int ResolutionY,
00293    int nCOLOUR, long speed, long tzeros,
00294    unsigned long *cstats0,unsigned short *cstats1){
00295  char filename[128],speed_string[128],*pp,format[64];
00296  long used,cpix,size,x_x,y_y;
00297  unsigned short val,Nt,RGB[1024];
00298  int i,j,frame,frames_found;
00299  unsigned char *Screen1,*screen;
00300  FILE *ipf;
00301  colorstats0=cstats0;
00302  colorstats1=cstats1;
00303  if(strrchr(flic_file,'.') != NULL)*strrchr(flic_file,'.')='\0';
00304  strcat(flic_file,".avi");
00305 // {
00306 //  char str[128];
00307 //  sprintf(str,"Stem=[%s]",stem_file);
00308 //  MessageBox(GetFocus(),(LPCTSTR)str,(LPCTSTR)"Flic",MB_OK|MB_TASKMODAL);
00309 //  sprintf(str,"flic=[%s] ff=%ld lf=%ld",flic_file,range_f,range_l);
00310 //  MessageBox(GetFocus(),(LPCTSTR)str,(LPCTSTR)"Flic",MB_OK|MB_TASKMODAL);
00311 //  sprintf(str,"x=%ld y=%ld speed=%ld",ResolutionX,ResolutionY,speed);
00312 //  MessageBox(GetFocus(),(LPCTSTR)str,(LPCTSTR)"Flic",MB_OK|MB_TASKMODAL);
00313 // }
00314  if((range_l - range_f) < 3)return;  /* don't animate < 3 frames */
00315  size=ResolutionX*ResolutionY;
00316  configureAVIfile(parent_window,NULL,NULL);
00317  if(speed < 0)speed=5;
00318  if((Screen1 = (unsigned char *)X__Malloc(size)) == NULL){
00319    MessageBox(GetFocus(),(LPCTSTR)"Out of memory",(LPCTSTR)"Flic",MB_OK|MB_TASKMODAL);
00320    return;
00321  }
00322  memset(Screen1,'0',size);
00323  SendMessage(status_window,WM_SETTEXT,0,(LPARAM)"Building color palette");
00324  SortColours(GIFCOLOURS,nCOLOUR);
00325  /* note << 1 is because the FLI/FLC is using 64**3 colours */
00326  for(i=0;i<GIFCOLOURS;i++){
00327    gif_p_red[i]  =(unsigned char)((colorstats1[i] >> 10) & 0x1F) << 1;
00328    gif_p_green[i]=(unsigned char)((colorstats1[i] >>  5) & 0x1F) << 1;
00329    gif_p_blue[i] =(unsigned char)((colorstats1[i]      ) & 0x1F) << 1;
00330  }
00331  for(i=0;i<nCOLOUR;i++)colorstats0[i] = GIFCOLOURS+1;
00332  if(!MakeBitmapStructure(ResolutionX,ResolutionY)){
00333    X__Free(Screen1);
00334    MessageBox(GetFocus(),(LPCTSTR)"Out of memory",(LPCTSTR)"Flic",MB_OK|MB_TASKMODAL);
00335    return;
00336  }
00337  for(frame=range_f;frame<=range_l;frame++){
00338    sprintf(speed_string,"Building frame %03ld",min(frame,range_l));
00339    SendMessage(status_window,WM_SETTEXT,0,(LPARAM)speed_string);
00340    sprintf(format,"%s%ld%s","%s%0",tzeros,"d.16b");
00341    if(frame < range_l)sprintf(filename,format,stem_file,frame);
00342    else               sprintf(filename,format,stem_file,range_f);
00343    if((ipf=fopen(strlwr(filename),"rb")) == NULL){
00344      goto FATALOPEN1;
00345    }
00346    if( fread((char *)&x_x,sizeof(long),1,ipf) != 1 ||
00347        fread((char *)&y_y,sizeof(long),1,ipf) != 1)goto FATALREAD;
00348    if(x_x != ResolutionX || y_y != ResolutionY)goto FATALREAD;
00349    screen=Screen1;
00350    for (i = 0; i < ResolutionY; i++) {
00351      if(fread((char *)&Nt,sizeof(short),1,ipf) != 1)goto FATALREAD;
00352      if(Nt == 0){
00353        if(fread((char *)RGB,sizeof(unsigned short),ResolutionX,ipf)
00354           != ResolutionX)goto FATALREAD;
00355      }
00356      else{
00357        if(fread((char *)compressbuffer,sizeof(short),Nt,ipf) != Nt)
00358          goto FATALREAD;
00359        UnCompressWordLine(Nt,compressbuffer,RGB);
00360      }
00361      for (j = 0; j < ResolutionX; j++) {
00362        val=RGB[j];
00363        if((cpix = (long)colorstats0[(long)val]) > GIFCOLOURS){
00364          cpix=getcolor(val,GIFCOLOURS);
00365          colorstats0[(long)val]=(unsigned long)cpix;
00366        }
00367        *screen++ = (unsigned char)cpix;
00368      }
00369    }
00370    fclose(ipf);
00371    MakeBitmapImage(Screen1,ResolutionX,ResolutionY);
00372    if(frame == range_f){
00373      openAVIfile(flic_file,(LPBITMAPINFOHEADER)lpBitmapHeader,1,15);
00374      appendAVIfile((LPBITMAPINFOHEADER)lpBitmapHeader);
00375    }
00376    else if(frame == range_l){
00377      closeAVIfile();
00378    }
00379    else{
00380      appendAVIfile((LPBITMAPINFOHEADER)lpBitmapHeader);
00381    }
00382  }
00383  if(MessageBox(GetFocus(),(LPCTSTR)"Delete Temporary files",
00384           (LPCTSTR)"Flic",MB_YESNO|MB_TASKMODAL|MB_ICONQUESTION) == IDYES){
00385    FILE *FF;
00386    sprintf(format,"%s%ld%s","%s%0",tzeros,"d.16b");
00387    sprintf(filename,format,stem_file,range_f);
00388    if((FF=fopen(filename,"r")) != NULL){
00389      fclose(FF);
00390      for(i=range_f;i<range_l;i++){
00391        sprintf(format,"%s%ld%s","%s%0",tzeros,"d.16b");
00392        sprintf(filename,format,stem_file,i);
00393        if(DeleteFile(filename) == FALSE){
00394          MessageBox(GetFocus(),(LPCTSTR)strcat(filename," Failed during delete"),
00395          (LPCTSTR)"Flic",MB_OK|MB_TASKMODAL);
00396          break;
00397        }
00398      }
00399    }
00400    else MessageBox(GetFocus(),(LPCTSTR)"Failed to delete temporary files",
00401           (LPCTSTR)"Flic",MB_OK|MB_TASKMODAL);
00402  }
00403  goto XXIT;
00404  FATALREAD:
00405    MessageBox(GetFocus(),(LPCTSTR)"Read failed on temporary file",(LPCTSTR)"Error",MB_OK|MB_TASKMODAL);
00406    fclose(ipf); goto XXIT;
00407  FATALOPEN1:
00408    MessageBox(GetFocus(),(LPCTSTR)"Temporary file open failed",(LPCTSTR)"Error",MB_OK|MB_TASKMODAL);
00409    goto XXIT;
00410  XXIT:
00411  X__Free(Screen1);
00412  if(lpBitmapHeader != NULL)X__Free(lpBitmapHeader);
00413 }
00414 
00415 /************************** DLL entry point ********************************/
00416 
00417 #if __WATCOMC__
00418 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00419 #else
00420 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00421 #endif
00422   switch (dwReason) {
00423     case DLL_PROCESS_ATTACH: {
00424 #if __X__MIPS__
00425       if(!_CRT_INIT(hDLL,dwReason,lpReserved))return(int)FALSE;
00426 #endif
00427 //      MessageBox (GetFocus(),"AVI builder attaching","Debug",MB_OK);
00428       break;
00429     }
00430     case DLL_PROCESS_DETACH:
00431 #if __X__MIPS__
00432       if(!_CRT_INIT(hDLL,dwReason,lpReserved))return(int)FALSE;
00433 #endif
00434 //      MessageBox (GetFocus(),"AVI builder detaching","Debug",MB_OK);
00435       break;
00436   }
00437   return (int)TRUE;
00438 }
00439 
00440 #if __SC__
00441 #pragma startaddress(DllMain)
00442 #endif
00443 

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