2 fbv -- simple image viewer for the linux framebuffer
3 Copyright (C) 2000, 2001, 2003 Mateusz Golicz
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <sys/types.h>
30 #define min(a,b) ((a) < (b) ? (a) : (b))
31 #define max(a,b) ((a) > (b) ? (a) : (b))
32 #define SHOWDELAY 100000
36 extern unsigned char * simple_resize(unsigned char * orgin,int ox,int oy,int dx,int dy);
37 extern unsigned char * alpha_resize(unsigned char * orgin,int ox,int oy,int dx,int dy);
38 extern unsigned char * color_average_resize(unsigned char * orgin,int ox,int oy,int dx,int dy);
41 int clear=1,delay=0,hide=1,dispinfo=1,allowstrech=0,opt_alpha = 0, allow_enlarging = 0, ignore_ratio = 0;
43 struct formathandler *fh_root=NULL;
45 struct termios oldtermios;
46 struct termios ourtermios;
48 int imm_getchar(int s,int us)
55 tv.tv_sec=s; tv.tv_usec=us;
56 if(select(1,&fds,NULL,NULL,&tv))
67 tcgetattr(0,&oldtermios);
68 memcpy(&ourtermios,&oldtermios,sizeof(struct termios));
69 ourtermios.c_lflag&=!(ECHO|ICANON);
70 tcsetattr(0,TCSANOW,&ourtermios);
74 tcsetattr(0,TCSANOW,&oldtermios);
78 void add_format(int (*picsize)(char *,int *,int*),int (*picread)(char *,unsigned char *,unsigned char**,int,int), int (*id)(char*))
80 struct formathandler *fhn;
81 fhn=(struct formathandler*) malloc(sizeof(struct formathandler));
82 fhn->get_size=picsize; fhn->get_pic=picread; fhn->id_pic=id;
83 fhn->next=fh_root; fh_root=fhn;
85 #ifdef FBV_SUPPORT_GIF
86 extern int fh_gif_getsize(char *,int *,int*);
87 extern int fh_gif_load(char *,unsigned char *,unsigned char **, int,int);
88 extern int fh_gif_id(char *);
90 #ifdef FBV_SUPPORT_JPEG
91 extern int fh_jpeg_getsize(char *,int *,int*);
92 extern int fh_jpeg_load(char *,unsigned char *,unsigned char **, int,int);
93 extern int fh_jpeg_id(char *);
95 #ifdef FBV_SUPPORT_PNG
96 extern int fh_png_getsize(char *,int *,int*);
97 extern int fh_png_load(char *,unsigned char *,unsigned char **,int,int);
98 extern int fh_png_id(char *);
100 #ifdef FBV_SUPPORT_BMP
101 extern int fh_bmp_getsize(char *,int *,int*);
102 extern int fh_bmp_load(char *,unsigned char *,unsigned char **, int,int);
103 extern int fh_bmp_id(char *);
106 void init_handlers(void)
108 #ifdef FBV_SUPPORT_GIF
109 add_format(fh_gif_getsize,fh_gif_load,fh_gif_id);
111 #ifdef FBV_SUPPORT_JPEG
112 add_format(fh_jpeg_getsize,fh_jpeg_load,fh_jpeg_id);
114 #ifdef FBV_SUPPORT_PNG
115 add_format(fh_png_getsize,fh_png_load,fh_png_id);
117 #ifdef FBV_SUPPORT_BMP
118 add_format(fh_bmp_getsize,fh_bmp_load,fh_bmp_id);
122 struct formathandler * fh_getsize(char *name,int *x,int *y)
124 struct formathandler *fh;
125 for(fh=fh_root;fh!=NULL;fh=fh->next)
128 if(fh->get_size(name,x,y)==FH_ERROR_OK) return(fh);
133 int show_image(char *name)
135 int x,y,xs,ys,xpos,ypos,xdelta,ydelta,c,eol,xstep,ystep,rfrsh,imx,imy;
136 unsigned char *buffer;
137 unsigned char *alpha = NULL;
138 struct formathandler *fh;
140 if((fh=fh_getsize(name,&x,&y)))
142 buffer=(unsigned char *) malloc(x*y*3);
143 if(fh->get_pic(name,buffer,&alpha,x,y)==FH_ERROR_OK)
145 if(clear) { printf("\033[H\033[J"); fflush(stdout); usleep(SHOWDELAY); } /* temporary solution */
146 if(dispinfo) printf("%s\n%s\n%d x %d\n",IDSTRING,name,x,y);
148 getCurrentRes(&xs,&ys);
149 if((x>xs || y>ys) && allowstrech)
174 buffer=simple_resize(buffer,x,y,imx,imy);
176 buffer=color_average_resize(buffer,x,y,imx,imy);
179 alpha=alpha_resize(alpha,x,y,imx,imy);
184 if(((x < xs) || (y < ys)) && allow_enlarging)
200 if(x<xs) xpos=(xs-x)/2; else xpos=0;
201 if(y<ys) ypos=(ys-y)/2; else ypos=0;
204 xstep=min(max(x/20,1),xs);
205 ystep=min(max(y/20,1),ys);
207 for(eol=-1,rfrsh=1;eol==-1;)
210 fb_display(buffer, opt_alpha ? alpha : NULL, x,y,xdelta,ydelta,xpos,ypos);
219 if(xdelta<0) xdelta=0;
225 if(xdelta>(x-xs)) xdelta=x-xs;
230 if(ydelta<0) ydelta=0;
236 if(ydelta>(y-ys)) ydelta=y-ys;
239 case ' ': case 10: eol=1; break;
240 case 'r': rfrsh=1; break;
241 case '.': case '>': eol=NEXT_IMG; break;
242 case ',': case '<': case 127: case 255: eol=PREV_IMG; break;
243 case 'q': eol=0; break;
248 if(imm_getchar(delay / 10,delay % 10)=='q') eol=0; else eol=1;
253 if(clear) { printf("\033[0m\033[H\033[J"); fflush(stdout); }
256 printf("Unable to read file !\n");
261 printf("Unable to read file or file format not recognized!\n");
266 void help(char *name)
268 printf("Usage: %s [options] image1 image2 image3 ...\n\n"
269 "Available options:\n"
270 " --help | -h : Show this help\n"
271 " --alpha | -a : Use alpha channel (if applicable)\n"
272 " --noclear | -c : Do not clear the screen before/after displaying image\n"
273 " --unhide | -u : Do not hide/show the cursor before/after displaying image\n"
274 " --noinfo | -i : Supress image information\n"
275 " --stretch | -f : Strech (using a simple resizing routine) the image to fit onto screen if necessary\n"
276 " --colorstretch | -k : Strech (using a 'color average' resizing routine) the image to fit onto screen if necessary\n"
277 " --enlarge | -e : Enlarge the image to fit the whole screen if necessary\n"
278 " --ignore-ratio | -r : Ignore the image aspect while resizing\n"
279 " --delay | -s <delay> slideshow, wait 'delay' tenths of a second before displaying each image\n\n"
280 "Use a,d,w and x to scroll the image\n\n"
281 "fbv 0.99 Copyright (C) 2000 - 2003 Mateusz Golicz, Tomasz Sterna.\n", name);
287 int main(int argc,char **argv)
291 static struct option long_options[] =
293 {"help", no_argument, 0, 'h'},
294 {"noclear", no_argument, 0, 'c'},
295 {"alpha", no_argument, 0, 'a'},
296 {"unhide", no_argument, 0, 'h'},
297 {"noinfo", no_argument, 0, 'i'},
298 {"stretch", no_argument, 0, 'f'},
299 {"colorstrech", no_argument, 0, 'k'},
300 {"delay", required_argument, 0, 's'},
301 {"enlarge", no_argument, 0, 'e'},
302 {"ignore-ratio", no_argument, 0, 'r'},
314 opt=getopt_long_only(argc,argv,"achukfis:er",long_options,NULL);
318 case 'a': opt_alpha = 1; break;
319 case 'c': clear=0; break;
320 case 's': if(optarg) delay=atoi(optarg); break;
321 case 'u': hide=0; break;
322 case 'h': help(argv[0]); break;
323 case 'i': dispinfo=0; break;
324 case 'f': allowstrech=1; break;
325 case 'k': allowstrech=2; break;
326 case 'e': allow_enlarging = 1; break;
327 case 'r': ignore_ratio = 1; break;
330 if(argv[optind]==NULL) {printf("You have to specify a filename!\n"); return(1);}
331 while(imm_getchar(0,0)!=EOF);
332 if(hide) printf("\033[?25l");
333 for(a=optind;argv[a]!=NULL;a++)
335 r=show_image(argv[a]);
345 if(hide) printf("\033[?25h");