/* * Program name: shim * Version: 1.1 beta * Source file: shim.c (main source file) * Description: A simple command line utility to show graphical images * of various formats. Use for more information. * * Comments: In general functions return -1 on failure and 0 on success. * * Copyright (C) 2005-2007 Jeroen van Aart * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include /* image library for loading various image formats */ #include /* functions to zoom and rotate image */ #include "shim_func.h" /* contains all function prototypes used in this program */ const int DEFSEC=20; /* default time to wait until displaying a new image when -s=0 is being used */ /* * setup and prepare SDL for usage */ int setupsdl(void) { /* Initialize defaults, Video */ if((SDL_Init(SDL_INIT_VIDEO)==-1)) { printf("Could not initialise SDL: %s.\n", SDL_GetError()); return(-1); } /* prevent cursor from being displayed */ SDL_ShowCursor(SDL_DISABLE); } /* * graciously exit the program */ void cleanend(struct Shim_Data *shimdata) { SDL_Quit(); free(shimdata); exit(0); } /* * process the arguments given at program startup, if any */ void process_arguments(struct Shim_Data *shimdata,int argc, char **argv) { int c,i; shimdata->fullscreen=0;shimdata->slideshow=0;shimdata->always=0; shimdata->angle=0;shimdata->zoom=1.0;shimdata->output=0; shimdata->smooth=0; /* * if argc=1 then the program was called without any options, * argv in this case contains only the program name */ if(argc==1) { print_shorthelp(*(argv+0)); return; } /* loop along the possible list of arguments */ while((--argc>0) && (**++argv=='-')) { while(c=*++*argv) { switch(c) { case 'f': /* -f display images in fullscreen */ shimdata->fullscreen=1; break; case 'g': /* -g (gladkaja) use smoothing with zoom and/or rotate */ shimdata->smooth=1; break; case 'h': /* -h display help text and exit */ print_help(*(argv-1)); return; case 'o': /* -o do not display images, instead output image to a new file */ shimdata->output=1; break; case 'r': /* -r rotate image */ /* if option -R already has been used then angle=180 */ if(shimdata->angle==270) shimdata->angle=180; else /* only option -r has been given */ shimdata->angle=90; break; case 'R': /* -R rotate image */ /* if option -r already has been used then angle=180 */ if(shimdata->angle==90) shimdata->angle=180; else /* only option -R has been given */ shimdata->angle=270; break; case 's': /* -s display images in a slideshow */ shimdata->slideshow=1; /* check if syntax of -s=xx is correct, if given */ shimdata->sec=process_s(argc,argv); if(shimdata->sec==-1) { /* incorrect syntax, program will exit */ printf("syntax error option %c\n",c); return; } break; case 'a': /* -a continue displaying in slideshow mode forever */ shimdata->always=1; break; case 'v': /* -v show version information and exit */ do_version(); return; case 'z': /* -z zoom image to half the original size */ /* if option -Z already has been used then ignore this */ if(shimdata->zoom!=2) shimdata->zoom=0.5; break; case 'Z': /* -Z zoom image to double the original size */ /* if option -z already has been used then ignore this */ if(shimdata->zoom!=0.5) shimdata->zoom=2; break; default: /* anything not recognised causes an error and program exits */ printf("illegal option %c\n",c); return; } } } /* * option -o results in options -a and -s being ignored * because the latter two options are related to images being displayed */ if(shimdata->output==1) { shimdata->always=0;shimdata->slideshow=0; } /* * when we get here it means option syntax, * for those options not to cause this function to return, * was correct, or the only argument(s) were filenames * so lets try to open SDL */ if(setupsdl()==-1) return; if(shimdata->slideshow==1) { showimage_slide(shimdata,argc,argv); } else { for(i=0;ioutput==0)) do_delay(shimdata,10); } } } /* * check the arguments given with the -s option(slideshow) */ int process_s(int argc,char **argv) { int l,x; if(*++*argv=='=') { *++*argv; x=atoi(*argv); l=strlen(*argv); *--*argv; if(x==0) x=DEFSEC; if(checkifnum(l,argv)==0) return(x); } return(-1); } /* * Checks if the given string has only numeric values or not, * returns -1 if string contains more than just numeric values, else 0 */ int checkifnum(int l,char **argv) { int i; char c; for (i=0;iimage=IMG_Load(name); /* check if image loading was succesful */ if(!shimdata->image) { printf("Error loading %s: %s\n",name,IMG_GetError()); return(-1); } /* see if image needs to be rotated */ if(shimdata->angle!=0) { /* rotate using angle set in shimdata->angle (90 or 270) */ shimdata->image=rotozoomSurface(shimdata->image,shimdata->angle,shimdata->zoom,shimdata->smooth); } else { if((shimdata->zoom==0.5) || (shimdata->zoom==2)) shimdata->image=zoomSurface(shimdata->image,shimdata->zoom,shimdata->zoom,shimdata->smooth); } /* if user does not want o save images to a file */ if(shimdata->output==0) { if(shimdata->fullscreen==0) { /* setup videomode using image data default depth and surface in system memory */ shimdata->screen=SDL_SetVideoMode(shimdata->image->w,shimdata->image->h,0,SDL_SWSURFACE); if(shimdata->screen==NULL) { printf("Error displaying image: %s\n",IMG_GetError()); printf("Zooming to halfsize...\n"); shimdata->image=zoomSurface(shimdata->image,0.5,0.5,shimdata->smooth); shimdata->screen=SDL_SetVideoMode(shimdata->image->w,shimdata->image->h,0,SDL_SWSURFACE); } SDL_WM_SetCaption(name,name); } else { /* user gave option -f so go fullscreen */ shimdata->screen=SDL_SetVideoMode(shimdata->image->w,shimdata->image->h,0,SDL_SWSURFACE|SDL_FULLSCREEN); if(shimdata->screen==NULL) { printf("Error displaying image: %s\n", IMG_GetError()); printf("Zooming to halfsize...\n"); shimdata->image=zoomSurface(shimdata->image,0.5,0.5,shimdata->smooth); shimdata->screen=SDL_SetVideoMode(shimdata->image->w,shimdata->image->h,0,SDL_SWSURFACE|SDL_FULLSCREEN); } } if(shimdata->screen==NULL) { printf("Error opening display: %s\n", IMG_GetError()); return(-1); } /* display image */ if(SDL_BlitSurface(shimdata->image,NULL,shimdata->screen,NULL)==-1) { printf("Error displaying image: %s\n", IMG_GetError()); return(-1); } SDL_UpdateRect(shimdata->screen,0,0,0,0); } else { /* save images instead of displaying them * will segfault if not using +1 */ savename=malloc(strlen(name)+strlen("_shim_to.bmp")+1); /* oops, out of memory */ if(savename==NULL) exit(0); sprintf(savename,"%s%s",name,"_shim_to.bmp"); printf("Saving to %s\n",savename); if(SDL_SaveBMP(shimdata->image,savename)==-1) printf("Error saving file: %s\n",SDL_GetError()); free(savename); } /* do some event looping */ if((shimdata->msec<=0) && (shimdata->output==0)) eventloop(shimdata); return(0); } /* * shows an image when the -s option(slideshow) has been used */ void showimage_slide(struct Shim_Data *shimdata,int argc,char **argv) { int i; shimdata->msec=shimdata->sec*1000; for(i=0;imsec); else { /* * in a slideshow, option -s, * a continuous loop will occur when showimages always returns failure and -a has been used * to avoid a continuous loop we call do_delay() with msec=10, if showimage returns failure * user can quit by hitting ctrl c, using kill etc. */ do_delay(shimdata,10); } if((shimdata->always) && (i>=argc-1)) i=-1; } } /* * zooms or rotates images and displays it * zoom can be 0.5 to reduce image size or 1.5 to increase image size * when rotation is required angle will be NOT 0 * in that case zoom is ignored and no zoom will take place * returns -1 on failure, 0 on success */ int showimage_zoom(struct Shim_Data *shimdata,double zoom,int angle) { SDL_Rect temprect; if(angle==0) shimdata->image=zoomSurface(shimdata->image,zoom,zoom,shimdata->smooth); else { temprect.w=shimdata->image->w;temprect.h=shimdata->image->h; shimdata->image=rotozoomSurface(shimdata->image,angle,1.0,shimdata->smooth); shimdata->image->w=temprect.h;shimdata->image->h=temprect.w; } if(shimdata->fullscreen==0) shimdata->screen=SDL_SetVideoMode(shimdata->image->w,shimdata->image->h,0,SDL_SWSURFACE); else shimdata->screen=SDL_SetVideoMode(shimdata->image->w,shimdata->image->h,0,SDL_SWSURFACE|SDL_FULLSCREEN); if(shimdata->screen==NULL) { printf("Error opening display: %s\n", IMG_GetError()); return(-1); } /* display image */ if(SDL_BlitSurface(shimdata->image,NULL,shimdata->screen,NULL)==-1) { printf("Error displaying image: %s\n", IMG_GetError()); return(-1); } SDL_UpdateRect(shimdata->screen,0,0,0,0); /* do some event looping */ if(shimdata->msec<=0) eventloop(shimdata); else do_delay(shimdata,shimdata->msec); return(0); } /* * during msec amount of time this function repeatedely calls checkevent_poll * and then waits for a while using delay, used with -s option(slideshow) */ void do_delay(struct Shim_Data *shimdata,int msec) { int i; for(i=0;ifullscreen==0) shimdata->fullscreen=1; else shimdata->fullscreen=0; if(shimdata->screen!=NULL) SDL_WM_ToggleFullScreen(shimdata->screen); break; /* n means next picture */ case SDLK_n: return(-1); /* r means rotating picture */ case SDLK_r: if((shimdata->screen!=NULL) && (shimdata->image!=NULL)) showimage_zoom(shimdata,0,90); return(-1); /* x means zooming picture to a bigger size */ case SDLK_x: if((shimdata->screen!=NULL) && (shimdata->image!=NULL)) showimage_zoom(shimdata,2,0); return(-1); /* z means zooming picture to a smaller size */ case SDLK_z: if((shimdata->screen!=NULL) && (shimdata->image!=NULL)) showimage_zoom(shimdata,0.5,0); return(-1); /* escape means quit */ case SDLK_ESCAPE: cleanend(shimdata); default: break; } default: break; } } return(0); } /* * polls for an event which may have happened and acts accordingly */ int checkevent_poll(struct Shim_Data *shimdata) { SDL_Event event; /* wait for an event */ if(SDL_PollEvent(&event)) { switch(event.type) { /* most likely user tried to close the window, but can also be CTRL-c, kill signal etc. */ case SDL_QUIT: cleanend(shimdata); case SDL_KEYUP: switch(event.key.keysym.sym) { /* f means toggle fullscreen */ case SDLK_f: if(shimdata->fullscreen==0) shimdata->fullscreen=1; else shimdata->fullscreen=0; if(shimdata->screen!=NULL) SDL_WM_ToggleFullScreen(shimdata->screen); break; /* n means next picture */ case SDLK_n: return(-1); /* r means rotating picture */ case SDLK_r: if((shimdata->screen!=NULL) && (shimdata->image!=NULL)) showimage_zoom(shimdata,0,90); return(-1); /* x means zooming picture to a bigger size */ case SDLK_x: if((shimdata->screen!=NULL) && (shimdata->image!=NULL)) showimage_zoom(shimdata,2,0); return(-1); /* z means zooming picture to a smaller size */ case SDLK_z: if((shimdata->screen!=NULL) && (shimdata->image!=NULL)) showimage_zoom(shimdata,0.5,0); return(-1); /* escape means quit */ case SDLK_ESCAPE: cleanend(shimdata); default: break; } default: break; } } return(0); } /* * show version information when -v option(version) has been given */ void do_version() { printf("shim (showimage) 1.1b\n(C) 2005-2007 Jeroen van Aart - aq@ownaq.com\nhttp://www.aseq.de (main site)\nhttp://freshmeat.net/projects/shim\n\n"); printf("This program has been released under the GNU General Public License\nand comes without any WARRANTY.\nSee the readme for more information.\n"); } /* * handles the -h(help) argument */ void print_help(char *name) { printf("Usage: %s [OPTION]... FILE [FILE]...\n",name); printf("Displays image FILEs.\n\n"); printf("Pressing will switch to the next file to be displayed\nor exit if the last file has been reached.\n"); printf("Pressing will rotate the image 90 degrees.\n"); printf("Pressing will zoom the image to double the size.\n"); printf("Pressing will zoom the image to half the size.\n"); printf("Pressing will exit, closing the window also will exit.\n\n"); printf("-f fullscreen\n"); printf("-h display this help and exit\n"); printf("-s=x do a slideshow with x seconds between displays,\n if x is 0 a default of 20 is used\n"); printf("-a only has effect when -s is used, will slide forever\n"); printf("-o save files instead of displaing them, -a and -s will be ignored\n"); printf("-r rotate image 90 degrees\n"); printf("-R rotate image 270 degrees, if -r and -R are both given then rotate 180 degrees\n"); printf("-z zoom image to half size (-Z will be ignored)\n"); printf("-Z zoom image to double size (-z will be ignored)\n"); printf("-g (gladkaja) use anti-aliasing when zooming and/or rotating image, default is none\n"); printf("-v output version information and exit\n"); } /* * when program is started without any arguments this will print a short help text */ void print_shorthelp(char *name) { printf("Usage: %s -a -f -g -h -o -r -R -s=xx -v -z -Z FILE [FILE]...\n",name); } /* * MAIN * ********************** HERE BE DRAGONS ********************** */ int main(int argc, char **argv) { struct Shim_Data *shimdata=malloc(sizeof(struct Shim_Data)); /* oh dear, out of memory? we're outa here */ if(shimdata==NULL) exit(0); process_arguments(shimdata,argc,argv); cleanend(shimdata); }