2 * Copyright (c) 1998 Andrzej Bialecki
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * Small PNG viewer with scripting abilities
38 #include <sys/types.h>
40 #include <sys/consio.h>
41 #include <sys/mouse.h>
51 int kbd_action(int x, int y, char hotkey);
62 int (*func)(int x, int y, char hotkey);
65 struct menu_item std_menu[]= {
66 {"q Quit",'q',kbd_action},
67 {"n Next",'n',kbd_action},
68 {"p Previous",'p',kbd_action},
69 {"Z Zoom in",'Z',kbd_action},
70 {"z Zoom out",'z',kbd_action},
71 {"r Rotate",'r',kbd_action},
72 {"R Refresh",'R',kbd_action},
73 {"l Left",'l',kbd_action},
74 {"h Right",'h',kbd_action},
75 {"j Up",'j',kbd_action},
76 {"k Down",'k',kbd_action},
88 int max_screen_colors=15;
100 fprintf(stderr,"\nVGL graphics viewer, 1.0 (c) Andrzej Bialecki.\n");
101 fprintf(stderr,"\nUsage:\n");
102 fprintf(stderr,"\t%s [-r n] [-g n.n] filename\n",progname);
103 fprintf(stderr,"\nwhere:\n");
104 fprintf(stderr,"\t-r n\tchoose resolution:\n");
105 fprintf(stderr,"\t\t0 - 640x480x16 (default)\n");
106 fprintf(stderr,"\t\t1 - 640x200x256\n");
107 fprintf(stderr,"\t\t2 - 320x240x256\n");
108 fprintf(stderr,"\t-g n.n\tset screen gamma (1.3 by default)\n");
109 fprintf(stderr,"\n");
113 pop_up(char *title,int x, int y)
116 int x1,y1,width,height,i,j;
117 int last_pos,cur_pos,max_item;
121 sav.Type=VGLDisplay->Type;
122 clr.Type=VGLDisplay->Type;
127 while(std_menu[i].descr!=NULL) {
130 if(strlen(std_menu[i].descr)>width) width=strlen(std_menu[i].descr);
139 sav.Bitmap=(byte *)calloc(width*height,1);
140 clr.Bitmap=(byte *)calloc(width*height,1);
141 if(x>(VGLDisplay->Xsize-width)) x1=VGLDisplay->Xsize-width;
143 if(y>(VGLDisplay->Ysize-height)) y1=VGLDisplay->Ysize-height;
145 VGLMouseMode(VGL_MOUSEHIDE);
146 VGLBitmapCopy(VGLDisplay,x1,y1,&sav,0,0,width,height);
147 VGLFilledBox(VGLDisplay,x1,y1,x1+width-1,y1+height-1,pal_colors-1);
148 VGLBitmapString(VGLDisplay,x1+1,y1+1,title,0,pal_colors-1,0,0);
149 VGLLine(VGLDisplay,x1,y1+9,x1+width,y1+9,0);
151 while(std_menu[i].descr!=NULL) {
152 VGLBitmapString(VGLDisplay,x1+1,y1+11+i*9,std_menu[i].descr,0,pal_colors-1,0,0);
156 VGLMouseMode(VGL_MOUSESHOW);
159 VGLMouseStatus(&x,&y,&buttons);
161 if((cur_pos<0)||(cur_pos>max_item-1)) {
162 if(last_pos==-1) last_pos=0;
163 VGLBitmapString(VGLDisplay,x1+1,y1+11+last_pos*9,std_menu[last_pos].descr,0,pal_colors-1,0,0);
165 } else if(last_pos!=cur_pos) {
166 if(last_pos==-1) last_pos=0;
167 VGLBitmapString(VGLDisplay,x1+1,y1+11+last_pos*9,std_menu[last_pos].descr,0,pal_colors-1,0,0);
168 VGLBitmapString(VGLDisplay,x1+1,y1+11+cur_pos*9,std_menu[cur_pos].descr,pal_colors/2+1,pal_colors-1,0,0);
171 } while (buttons & MOUSE_BUTTON3DOWN);
172 VGLMouseMode(VGL_MOUSEHIDE);
173 /* XXX Screws up totally when r==3. Libvgl bug! */
174 VGLBitmapCopy(&clr,0,0,VGLDisplay,x1,y1,width,height);
175 VGLBitmapCopy(&sav,0,0,VGLDisplay,x1,y1,width,height);
176 VGLMouseMode(VGL_MOUSESHOW);
180 if((cur_pos>=0) && (cur_pos<max_item)) {
181 std_menu[cur_pos].func(x,y,std_menu[cur_pos].hotkey);
188 display( VGLBitmap *pic,
197 VGLMouseMode(VGL_MOUSEHIDE);
199 /* XXX Broken in r!=2. Libvgl bug. */
200 //VGLClear(VGLDisplay,0);
201 VGLBitmapCopy(&bkg,0,0,VGLDisplay,0,0,bkg.Xsize,bkg.Ysize);
204 if(e->zoom!=1 || e->rotate) {
205 target.Bitmap=(byte *)calloc(pic->Xsize*pic->Ysize*e->zoom*e->zoom,1);
207 target.Xsize=pic->Ysize*e->zoom;
208 target.Ysize=pic->Xsize*e->zoom;
210 target.Xsize=pic->Xsize*e->zoom;
211 target.Ysize=pic->Ysize*e->zoom;
213 target.Type=pic->Type;
214 for(x=0;x<pic->Xsize;x++) {
215 for(y=0;y<pic->Ysize;y++) {
216 for(i=0;i<e->zoom;i++) {
217 for(j=0;j<e->zoom;j++) {
219 VGLSetXY(&target,target.Xsize-(e->zoom*y+i),e->zoom*x+j,VGLGetXY(pic,x,y));
221 VGLSetXY(&target,e->zoom*x+i,e->zoom*y+j,VGLGetXY(pic,x,y));
228 target.Bitmap=(byte *)calloc(pic->Xsize*pic->Ysize,sizeof(byte));
229 target.Xsize=pic->Xsize;
230 target.Ysize=pic->Ysize;
231 target.Type=pic->Type;
232 VGLBitmapCopy(pic,0,0,&target,0,0,pic->Xsize,pic->Ysize);
235 target.Bitmap=(byte *)calloc(pic->Xsize*pic->Ysize,sizeof(byte));
236 target.Xsize=pic->Xsize;
237 target.Ysize=pic->Ysize;
238 target.Type=pic->Type;
239 VGLBitmapCopy(pic,0,0,&target,0,0,pic->Xsize,pic->Ysize);
241 VGLSetPalette(red, green, blue);
243 VGLBitmapCopy(&target,0,0,VGLDisplay,e->Xshift,e->Yshift,target.Xsize,target.Ysize);
245 VGLBitmapCopy(&target,0,0,VGLDisplay,0,0,target.Xsize,target.Ysize);
247 VGLMouseMode(VGL_MOUSESHOW);
252 png_load(char *filename)
256 u_char header[NUMBER];
258 png_infop info_ptr,end_info;
259 png_uint_32 width,height;
260 int bit_depth,color_type,interlace_type;
261 int compression_type,filter_type;
262 int channels,rowbytes;
266 png_bytep *row_pointers;
270 fd=fopen(filename,"rb");
277 fread(header,1,NUMBER,fd);
278 if(!png_check_sig(header,NUMBER)) {
279 fprintf(stderr,"Not a PNG file.\n");
282 png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING,(void *)NULL,
284 info_ptr=png_create_info_struct(png_ptr);
285 end_info=png_create_info_struct(png_ptr);
286 if(!png_ptr || !info_ptr || !end_info) {
288 fprintf(stderr,"failed to allocate needed structs!\n");
289 png_destroy_read_struct(&png_ptr,&info_ptr,&end_info);
292 png_set_sig_bytes(png_ptr,NUMBER);
293 png_init_io(png_ptr,fd);
294 png_read_info(png_ptr,info_ptr);
295 png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth,
296 &color_type,&interlace_type,&compression_type,&filter_type);
297 png_get_PLTE(png_ptr,info_ptr,&palette,&num_palette);
298 channels=png_get_channels(png_ptr,info_ptr);
299 rowbytes=png_get_rowbytes(png_ptr,info_ptr);
301 png_set_strip_16(png_ptr);
302 if(color_type & PNG_COLOR_MASK_ALPHA)
303 png_set_strip_alpha(png_ptr);
304 if(png_get_gAMA(png_ptr,info_ptr,&gamma))
305 png_set_gamma(png_ptr,screen_gamma,gamma);
307 png_set_gamma(png_ptr,screen_gamma,0.45);
310 if(color_type & PNG_COLOR_MASK_COLOR) {
311 if(png_get_valid(png_ptr,info_ptr,PNG_INFO_PLTE)) {
312 png_uint_16p histogram;
313 png_get_hIST(png_ptr,info_ptr,&histogram);
314 png_set_dither(png_ptr,palette,num_palette,max_screen_colors,histogram,0);
316 png_color std_color_cube[16]={
334 png_set_dither(png_ptr,std_color_cube,max_screen_colors,max_screen_colors,NULL,0);
338 png_set_packing(png_ptr);
339 if(png_get_valid(png_ptr,info_ptr,PNG_INFO_sBIT)) {
340 png_color_8p sig_bit;
342 png_get_sBIT(png_ptr,info_ptr,&sig_bit);
343 png_set_shift(png_ptr,sig_bit);
345 png_read_update_info(png_ptr,info_ptr);
346 png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth,
347 &color_type,&interlace_type,&compression_type,&filter_type);
348 png_get_PLTE(png_ptr,info_ptr,&palette,&num_palette);
349 channels=png_get_channels(png_ptr,info_ptr);
350 rowbytes=png_get_rowbytes(png_ptr,info_ptr);
351 row_pointers=malloc(height*sizeof(png_bytep));
352 for(i=0;i<height;i++) {
353 row_pointers[i]=malloc(rowbytes);
355 png_read_image(png_ptr,row_pointers);
356 png_read_end(png_ptr,end_info);
357 png_destroy_read_struct(&png_ptr,&info_ptr,&end_info);
367 for(i=0;i<num_palette;i++) {
368 pal_red[i]=(palette+i)->red>>k;
369 pal_green[i]=(palette+i)->green>>k;
370 pal_blue[i]=(palette+i)->blue>>k;
372 pal_colors=num_palette;
373 if(pic.Bitmap!=NULL) free(pic.Bitmap);
374 pic.Bitmap=(byte *)calloc(rowbytes*height,sizeof(byte));
378 for(i=0;i<rowbytes;i++) {
379 for(j=0;j<height;j++) {
381 i,j,row_pointers[j][i]);
385 a.Xshift=(VGLDisplay->Xsize-pic.Xsize)/2;
386 a.Yshift=(VGLDisplay->Ysize-pic.Ysize)/2;
403 kbd_action(int x, int y, char key)
406 if(key!='n') auto_chg=0;
417 if(a.zoom<1) a.zoom=1;
421 a.Xshift+=VGLDisplay->Xsize/5;
425 a.Xshift-=VGLDisplay->Xsize/5;
429 a.Yshift+=VGLDisplay->Ysize/5;
433 a.Yshift-=VGLDisplay->Ysize/5;
440 if(a.rotate) a.rotate=0;
452 png_load(pres[cur_img]);
463 png_load(pres[cur_img]);
472 main(int argc, char *argv[])
479 struct termios t_new,t_old;
487 log=fopen("/png/view.log","w");
489 while((c=getopt(argc,argv,"r:g:"))!=-1) {
493 if(res>0) max_screen_colors=256;
496 screen_gamma=atof(optarg);
506 VGLInit(SW_CG640x480);
509 VGLInit(SW_VGA_CG320);
512 VGLInit(SW_VGA_MODEX);
515 fprintf(stderr,"No such resolution!\n");
520 fprintf(log,"VGL initialised\n");
524 res=png_load(argv[optind]);
532 fsc=fopen(argv[optind],"r");
534 fprintf(log,"Trying script %s\n",argv[optind]);
537 buf[strlen(buf)-1]='\0';
538 if(strncmp("VIEW SCRIPT",buf,11)!=NULL) {
543 auto_chg=atoi(buf+12);
546 buf[strlen(buf)-1]='\0';
552 pres=(char **)calloc(nimg,sizeof(char *));
553 for(i=0;i<nimg;i++) {
555 buf[strlen(buf)-1]='\0';
561 fprintf(log,"Script with %d entries\n",nimg);
563 png_load(pres[cur_img]);
565 VGLMouseInit(VGL_MOUSEHIDE);
566 /* Prepare the keyboard */
568 memcpy(&t_new,&t_old,sizeof(struct termios));
570 tcsetattr(0,TCSAFLUSH,&t_new);
571 fcntl(0,F_SETFL,O_ASYNC);
572 /* XXX VGLClear doesn't work.. :-(( Prepare a blank background */
573 bkg.Bitmap=(byte *)calloc(VGLDisplay->Xsize*VGLDisplay->Ysize,1);
574 bkg.Xsize=VGLDisplay->Xsize;
575 bkg.Ysize=VGLDisplay->Ysize;
576 bkg.Type=VGLDisplay->Type;
577 signal(SIGIO,kbd_handler);
579 a.Xshift=(VGLDisplay->Xsize-pic.Xsize)/2;
580 a.Yshift=(VGLDisplay->Ysize-pic.Ysize)/2;
584 display(&pic,pal_red,pal_green,pal_blue,&a);
588 fprintf(log,"kbd_action(%c)\n",act);
595 fprintf(log,"changed, redisplaying\n");
597 display(&pic,pal_red,pal_green,pal_blue,&a);
606 VGLMouseStatus(&x,&y,&buttons);
607 if(buttons & MOUSE_BUTTON3DOWN) {
609 fprintf(log,"pop_up called\n");