#include "videoshow.h" #include "display.h" #define MODE_PLAY 1 #define MODE_PAUSE 2 #define MODE_STEP 3 #define MODE_NEXT 4 static int SDLDepth = 16; static int VideoStack = 1; static int WriteFrame = 0; int Mode = MODE_PLAY; int VideoCut = 0; int Offset = 0; double UMask = 0.0; static int Requested_FPS = 0; extern int DetectBrokenFrames; int DrawFrame = 1; int SeekColour = 0; char * GainComp = NULL; unsigned long FrameOffsets[10000]; int FrameCount = 0; static int FrameChannel(char *fname); static void Sharpen(unsigned int *buffer, int width, int height); static void Smooth(unsigned int *buffer, int width, int height); static int Convert_8_16_bpp(struct Image *img); int isBrokenFrame(struct Image *img); static int add_to_playlist(char *); static int play_all(void); #define PROPERTIES_MAX 7 #define PROPERTIES_DEF 0 int PropList[PROPERTIES_MAX + 1]; static int cur_channel = PROPERTIES_DEF; static void VKeyPress(int key, int mod) { double g; switch(key) { case SDLK_ESCAPE: case SDLK_q: SDL_Quit(); exit(1); break; case SDLK_n: Mode = MODE_NEXT; break; case SDLK_SPACE: if (Mode == MODE_PLAY) Mode = MODE_PAUSE; else Mode = MODE_PLAY; break; case SDLK_l: case SDLK_RIGHT: Mode = MODE_STEP; break; case SDLK_h: case SDLK_LEFT: if (FrameCount>1) { Mode = MODE_STEP; FrameCount-=2; } break; case SDLK_2: DrawFrame=0; SeekColour = 2; break; case SDLK_3: DrawFrame=0; SeekColour = 3; break; case SDLK_4: DrawFrame=0; SeekColour = 4; break; case SDLK_5: DrawFrame=0; SeekColour = 5; break; case SDLK_6: DrawFrame=0; SeekColour = 6; break; case SDLK_w: WriteFrame = 1; break; case SDLK_r: SetProperty_gain(PropList[cur_channel], 1.0); break; case SDLK_RIGHTBRACKET: AdjustProperty_gain(PropList[cur_channel], 0.1); break; case SDLK_LEFTBRACKET: g = AdjustProperty_gain(PropList[cur_channel], -0.1); if (g<0.5) SetProperty_gain(PropList[cur_channel], 0.5); break; } } static void VKeyRelease(int key, int mod) { } int FCount=0; static int FrameChannel(char *fname) { char *ptr = fname + strlen(fname)-1; int ch = atoi(ptr-4); if (ch<0 || ch>6) ch = 0; return ch; } void display_image(struct Image *img) { static struct Image *d_img = NULL; int i,npixels = img->width * img->height; SDL_Event ev; static int have_window = -1; static int Width=-1,Height=-1; static unsigned long tm; static int frame_count=0; struct tm *t; unsigned short *data,*ddata; char str[128]; char img_name[64]; double tm_sec = img->tm_sec; unsigned long long tm_tsc = img->tm_tsc; unsigned int hr = tm_sec/3600; unsigned int min = (tm_sec - hr*3600)/60; double secs = tm_sec - hr*3600 - min*60; if (img->src_fname) strcpy(img_name,img->src_fname); else strcpy(img_name,"unknown"); if (DetectBrokenFrames && isBrokenFrame(img)) return; if (FCount==0) tm = time(0); if (AMean) AlphaTrimmedMean(img,1,2); if (img->depth == 8) Convert_8_16_bpp(img); if (! DrawFrame) { int c = FrameChannel(img->src_fname); if (c == SeekColour) DrawFrame=1; } if (DrawFrame) { if (GainComp) ApplyGainCompensation(img); if (VideoCut) { CalculateCutout(img); CutOut(img); } if (d_img == NULL) { d_img = ConvertImage(img,IMG_FIT,16); } data = (unsigned short *) img->data; ddata = (unsigned short *) d_img->data; if (frame_count == 0) for(i=0; iwidth || Height != d_img->height) { if (have_window) SDL_Quit(); SDLDepth = 16; have_window = InitDisplay("VideoShow",d_img->width,d_img->height,SDLDepth); if (! have_window) { SDLDepth = 32; fprintf(stderr,"16bpp failed, trying 32...\n"); have_window = InitDisplay("VideoShow",d_img->width,d_img->height,SDLDepth); if (! have_window) FatalError("Cannot start SDL"); } Width = d_img->width; Height = d_img->height; } #ifdef MSWIN32 sprintf(str,"%-20s %02d:%02d:%2.6lf / %I64u", img_name, hr,min,secs, tm_tsc); #else sprintf(str,"%-20s %02d:%02d:%2.6lf / %llu", img_name, hr,min,secs, tm_tsc); #endif DrawString(d_img, d_img->height - 20, 10, str); DisplayImage(d_img, PropList[cur_channel], 0, 0); frame_count=0; if (Requested_FPS > 0) Usleep(1000000 / Requested_FPS); } if (Mode == MODE_STEP) Mode = MODE_PAUSE; while(1) { while(SDL_PollEvent(&ev)) { switch(ev.type) { case SDL_KEYDOWN: VKeyPress(ev.key.keysym.sym, ev.key.keysym.mod); break; case SDL_KEYUP: VKeyRelease(ev.key.keysym.sym, ev.key.keysym.mod); break; } } if (WriteFrame == 1) { printf("Write [%s]\n",d_img->dst_fname); WriteImage(d_img); WriteFrame=0; } if (Mode == MODE_PLAY || Mode == MODE_STEP || Mode == MODE_NEXT) break; Usleep(100000); } ++FCount; if (time(0) - tm > 2) { FCount /= 2; printf("%-15.15s fps: %5.5d ",img_name,FCount); printf("%02d:%02d:%2.6lf", hr,min,secs); #ifdef MSWIN32 printf(" / %I64u\r", tm_tsc); #else printf(" / %llu\r", tm_tsc); #endif fflush(stdout); FCount=0; } return; } static int comp(const void *ptr1, const void *ptr2) { char **s1 = (char **)ptr1; char **s2 = (char **)ptr2; char *p1 = *s1; char *p2 = *s2; int i1,i2; // seek to end of string p1 += strlen(p1); p2 += strlen(p2); if (strcasecmp(p1-4,".fta")==0 && strcasecmp(p2-4,".fta")==0) { // comparison on these archive files is purely string return strcasecmp(*s1,*s2); } // seek back until we find the last path entry while(p1 != *s1 && *(p1-1) != '/' && *(p1-1) != '\\') --p1; while(p2 != *s2 && *(p2-1) != '/' && *(p2-1) != '\\') --p2; // Go forward until we find a digit while(*p1 && ! isdigit(*p1)) ++p1; while(*p2 && ! isdigit(*p2)) ++p2; // Hopefully we are now on a substring that can be used for comparison i1 = atoi(p1); i2 = atoi(p2); if (i1i2) return 1; return 0; } static char *filelist[100000]; static int FileCount=0; void playdir(char *dir) { struct dirent *e; int i; DIR *d = opendir(dir); char fname[256]; Mode = MODE_PLAY; FileCount = 0; while(e = readdir(d)) { if (strlen(e->d_name)>4 && e->d_name[0] != '.') { sprintf(fname,"%s/%s",dir,e->d_name); if (! access(fname,R_OK|F_OK) && isSupportedFile(fname)) { filelist[FileCount++] = strdup(fname); if ((FileCount%1000) == 0) { printf("Loaded %d files...\n",FileCount); fflush(stdout); } } } } closedir(d); printf("Sorting %d files...\n",FileCount); fflush(stdout); qsort(filelist,FileCount,sizeof(char *),comp); for(i=0; i [%s]\n",next_fname); strcpy(ftmp,next_fname); playarchive(ftmp); } else break; } } else { //printf("%-5d\r",count); count++; fflush(stdout); img = LoadImage(fname,NULL); display_image(img); DestroyImage(img); } } void playarchive(char *arch) { struct Image *img; extern FILE *fopen64(); FILE *in = OpenArchive(arch); int count,err,flags=0; if (! in) { FatalError("Cannot open archive"); } FrameCount=0; FrameOffsets[0] = 0; if (!strcmp(arch+strlen(arch)-4,".ftz")) flags = ARCHIVE_COMPRESSED; while(1) { int fd = fileno(in); if (lseek(fd,FrameOffsets[FrameCount],SEEK_SET) < 0) perror(""); if (Mode == MODE_NEXT) break; if (DrawFrame) img = ArchiveLoadNextImage(in,&err,flags|ARCHIVE_LOAD); else img = ArchiveLoadNextImage(in,&err,flags|ARCHIVE_SKIP); if (err==0) break; // end of archive if (err<0) FatalError("Error while reading archive"); //printf("%-5d (%-5d)\r",FrameCount,FrameOffsets[FrameCount]); fflush(stdout); FrameCount++; FrameOffsets[FrameCount] = lseek(fd,0L,SEEK_CUR); if (DrawFrame && PopFilter) pop_filter(img); display_image(img); DestroyImage(img); if (SeekColour && DrawFrame==0) break; } } #define SHARPEN_DIV 6 void Sharpen(unsigned int *buffer, int width, int height) { int x,y,o; static unsigned int *bptr = NULL; static int bufsize = 0; int npixels = width * height; if (npixels != bufsize) { if (bptr != NULL) free(bptr); bptr = Malloc(npixels * 4); bufsize = npixels; } for(o=y=2; y0) bptr[o] = v; else bptr[o]=0; } memcpy(buffer,bptr,npixels*4); } void UnsharpMask(unsigned int *buffer, int width, int height, double m) { static int Npixels = -1; static unsigned int *bptr = NULL; int npixels = width * height; if (npixels != Npixels) { if (bptr != NULL) free(bptr); bptr = Malloc(npixels * 4); Npixels = npixels; } memcpy(bptr, buffer, npixels*4); Smooth(bptr, width, height); SubtractScale(buffer,bptr,npixels,m); Smooth(buffer,width, height); } void Smooth(unsigned int *buffer, int width, int height) { int x,y,o; static unsigned int *bptr = NULL; static int bufsize = 0; int npixels = width * height; if (npixels != bufsize) { if (bptr != NULL) free(bptr); bptr = Malloc(npixels * 4); bufsize = npixels; } for(o=y=0; y 0) { int v = *buf1; v -= *buf2 * m; if (v<0) v=0; *buf1 = v; buf1++; buf2++; } } static int Convert_8_16_bpp(struct Image *img) { int depth = img->depth; int width = img->width; int height = img->height; if (depth == 8) { register unsigned int X; int o = width * height; unsigned short *buffer = Malloc(o * 2); unsigned char *ptr = (unsigned char *)img->data; while(o-- >= 0) { X = ptr[o]; X<<=8; buffer[o]=X; } free(img->data); img->data = (unsigned char *)buffer; img->depth = 16; if (img->type == IMG_FIT) { struct fits_info *fi = img->info; fi->bzero = 32768; } } return 1; } #ifdef MSWIN32 #include extern int main(int argc, char* argv[]); int WINAPI WinMain(HINSTANCE instance, HINSTANCE prev_instance, char* command_line, int show_command) { main(__argc, __argv); } #endif char **playlist; int playlist_size=0; int playcount=0; static int add_to_playlist(char *name) { if (playlist == NULL || playlist_size==0) { playlist_size=1000; playlist = (char **) Malloc(sizeof(char *) * playlist_size); } if (playcount == playlist_size) { playlist_size += 1000; playlist = (char **) realloc(playlist, sizeof(char *) * playlist_size); } playlist[playcount++] = name; return 0; } static int play_all() { int i; for(i=0; i