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
26 * $FreeBSD: src/release/picobsd/tinyware/view/view.c,v 1.4 1999/08/28 01:34:02 peter Exp $
30 * Small PNG viewer with scripting abilities
38 #include <sys/types.h>
39 #include <machine/console.h>
40 #include <machine/mouse.h>
50 int kbd_action __P((int x, int y, char hotkey));
61 int (*func)(int x, int y, char hotkey);
64 struct menu_item std_menu[]= {
65 {"q Quit",'q',kbd_action},
66 {"n Next",'n',kbd_action},
67 {"p Previous",'p',kbd_action},
68 {"Z Zoom in",'Z',kbd_action},
69 {"z Zoom out",'z',kbd_action},
70 {"r Rotate",'r',kbd_action},
71 {"R Refresh",'R',kbd_action},
72 {"l Left",'l',kbd_action},
73 {"h Right",'h',kbd_action},
74 {"j Up",'j',kbd_action},
75 {"k Down",'k',kbd_action},
87 int max_screen_colors=15;
99 fprintf(stderr,"\nVGL graphics viewer, 1.0 (c) Andrzej Bialecki.\n");
100 fprintf(stderr,"\nUsage:\n");
101 fprintf(stderr,"\t%s [-r n] [-g n.n] filename\n",progname);
102 fprintf(stderr,"\nwhere:\n");
103 fprintf(stderr,"\t-r n\tchoose resolution:\n");
104 fprintf(stderr,"\t\t0 - 640x480x16 (default)\n");
105 fprintf(stderr,"\t\t1 - 640x200x256\n");
106 fprintf(stderr,"\t\t2 - 320x240x256\n");
107 fprintf(stderr,"\t-g n.n\tset screen gamma (1.3 by default)\n");
108 fprintf(stderr,"\n");
112 pop_up(char *title,int x, int y)
115 int x1,y1,width,height,i,j;
116 int last_pos,cur_pos,max_item;
120 sav.Type=VGLDisplay->Type;
121 clr.Type=VGLDisplay->Type;
126 while(std_menu[i].descr!=NULL) {
129 if(strlen(std_menu[i].descr)>width) width=strlen(std_menu[i].descr);
138 sav.Bitmap=(byte *)calloc(width*height,1);
139 clr.Bitmap=(byte *)calloc(width*height,1);
140 if(x>(VGLDisplay->Xsize-width)) x1=VGLDisplay->Xsize-width;
142 if(y>(VGLDisplay->Ysize-height)) y1=VGLDisplay->Ysize-height;
144 VGLMouseMode(VGL_MOUSEHIDE);
145 VGLBitmapCopy(VGLDisplay,x1,y1,&sav,0,0,width,height);
146 VGLFilledBox(VGLDisplay,x1,y1,x1+width-1,y1+height-1,pal_colors-1);
147 VGLBitmapString(VGLDisplay,x1+1,y1+1,title,0,pal_colors-1,0,0);
148 VGLLine(VGLDisplay,x1,y1+9,x1+width,y1+9,0);
150 while(std_menu[i].descr!=NULL) {
151 VGLBitmapString(VGLDisplay,x1+1,y1+11+i*9,std_menu[i].descr,0,pal_colors-1,0,0);
155 VGLMouseMode(VGL_MOUSESHOW);
158 VGLMouseStatus(&x,&y,&buttons);
160 if((cur_pos<0)||(cur_pos>max_item-1)) {
161 if(last_pos==-1) last_pos=0;
162 VGLBitmapString(VGLDisplay,x1+1,y1+11+last_pos*9,std_menu[last_pos].descr,0,pal_colors-1,0,0);
164 } else if(last_pos!=cur_pos) {
165 if(last_pos==-1) last_pos=0;
166 VGLBitmapString(VGLDisplay,x1+1,y1+11+last_pos*9,std_menu[last_pos].descr,0,pal_colors-1,0,0);
167 VGLBitmapString(VGLDisplay,x1+1,y1+11+cur_pos*9,std_menu[cur_pos].descr,pal_colors/2+1,pal_colors-1,0,0);
170 } while (buttons & MOUSE_BUTTON3DOWN);
171 VGLMouseMode(VGL_MOUSEHIDE);
172 /* XXX Screws up totally when r==3. Libvgl bug! */
173 VGLBitmapCopy(&clr,0,0,VGLDisplay,x1,y1,width,height);
174 VGLBitmapCopy(&sav,0,0,VGLDisplay,x1,y1,width,height);
175 VGLMouseMode(VGL_MOUSESHOW);
179 if((cur_pos>=0) && (cur_pos<max_item)) {
180 std_menu[cur_pos].func(x,y,std_menu[cur_pos].hotkey);
187 display( VGLBitmap *pic,
196 VGLMouseMode(VGL_MOUSEHIDE);
198 /* XXX Broken in r!=2. Libvgl bug. */
199 //VGLClear(VGLDisplay,0);
200 VGLBitmapCopy(&bkg,0,0,VGLDisplay,0,0,bkg.Xsize,bkg.Ysize);
203 if(e->zoom!=1 || e->rotate) {
204 target.Bitmap=(byte *)calloc(pic->Xsize*pic->Ysize*e->zoom*e->zoom,1);
206 target.Xsize=pic->Ysize*e->zoom;
207 target.Ysize=pic->Xsize*e->zoom;
209 target.Xsize=pic->Xsize*e->zoom;
210 target.Ysize=pic->Ysize*e->zoom;
212 target.Type=pic->Type;
213 for(x=0;x<pic->Xsize;x++) {
214 for(y=0;y<pic->Ysize;y++) {
215 for(i=0;i<e->zoom;i++) {
216 for(j=0;j<e->zoom;j++) {
218 VGLSetXY(&target,target.Xsize-(e->zoom*y+i),e->zoom*x+j,VGLGetXY(pic,x,y));
220 VGLSetXY(&target,e->zoom*x+i,e->zoom*y+j,VGLGetXY(pic,x,y));
227 target.Bitmap=(byte *)calloc(pic->Xsize*pic->Ysize,sizeof(byte));
228 target.Xsize=pic->Xsize;
229 target.Ysize=pic->Ysize;
230 target.Type=pic->Type;
231 VGLBitmapCopy(pic,0,0,&target,0,0,pic->Xsize,pic->Ysize);
234 target.Bitmap=(byte *)calloc(pic->Xsize*pic->Ysize,sizeof(byte));
235 target.Xsize=pic->Xsize;
236 target.Ysize=pic->Ysize;
237 target.Type=pic->Type;
238 VGLBitmapCopy(pic,0,0,&target,0,0,pic->Xsize,pic->Ysize);
240 VGLSetPalette(red, green, blue);
242 VGLBitmapCopy(&target,0,0,VGLDisplay,e->Xshift,e->Yshift,target.Xsize,target.Ysize);
244 VGLBitmapCopy(&target,0,0,VGLDisplay,0,0,target.Xsize,target.Ysize);
246 VGLMouseMode(VGL_MOUSESHOW);
251 png_load(char *filename)
255 u_char header[NUMBER];
257 png_infop info_ptr,end_info;
258 png_uint_32 width,height;
259 int bit_depth,color_type,interlace_type;
260 int compression_type,filter_type;
261 int channels,rowbytes;
265 png_bytep *row_pointers;
269 fd=fopen(filename,"rb");
276 fread(header,1,NUMBER,fd);
277 if(!png_check_sig(header,NUMBER)) {
278 fprintf(stderr,"Not a PNG file.\n");
281 png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING,(void *)NULL,
283 info_ptr=png_create_info_struct(png_ptr);
284 end_info=png_create_info_struct(png_ptr);
285 if(!png_ptr || !info_ptr || !end_info) {
287 fprintf(stderr,"failed to allocate needed structs!\n");
288 png_destroy_read_struct(&png_ptr,&info_ptr,&end_info);
291 png_set_sig_bytes(png_ptr,NUMBER);
292 png_init_io(png_ptr,fd);
293 png_read_info(png_ptr,info_ptr);
294 png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth,
295 &color_type,&interlace_type,&compression_type,&filter_type);
296 png_get_PLTE(png_ptr,info_ptr,&palette,&num_palette);
297 channels=png_get_channels(png_ptr,info_ptr);
298 rowbytes=png_get_rowbytes(png_ptr,info_ptr);
300 png_set_strip_16(png_ptr);
301 if(color_type & PNG_COLOR_MASK_ALPHA)
302 png_set_strip_alpha(png_ptr);
303 if(png_get_gAMA(png_ptr,info_ptr,&gamma))
304 png_set_gamma(png_ptr,screen_gamma,gamma);
306 png_set_gamma(png_ptr,screen_gamma,0.45);
309 if(color_type & PNG_COLOR_MASK_COLOR) {
310 if(png_get_valid(png_ptr,info_ptr,PNG_INFO_PLTE)) {
311 png_uint_16p histogram;
312 png_get_hIST(png_ptr,info_ptr,&histogram);
313 png_set_dither(png_ptr,palette,num_palette,max_screen_colors,histogram,0);
315 png_color std_color_cube[16]={
333 png_set_dither(png_ptr,std_color_cube,max_screen_colors,max_screen_colors,NULL,0);
337 png_set_packing(png_ptr);
338 if(png_get_valid(png_ptr,info_ptr,PNG_INFO_sBIT)) {
339 png_color_8p sig_bit;
341 png_get_sBIT(png_ptr,info_ptr,&sig_bit);
342 png_set_shift(png_ptr,sig_bit);
344 png_read_update_info(png_ptr,info_ptr);
345 png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth,
346 &color_type,&interlace_type,&compression_type,&filter_type);
347 png_get_PLTE(png_ptr,info_ptr,&palette,&num_palette);
348 channels=png_get_channels(png_ptr,info_ptr);
349 rowbytes=png_get_rowbytes(png_ptr,info_ptr);
350 row_pointers=malloc(height*sizeof(png_bytep));
351 for(i=0;i<height;i++) {
352 row_pointers[i]=malloc(rowbytes);
354 png_read_image(png_ptr,row_pointers);
355 png_read_end(png_ptr,end_info);
356 png_destroy_read_struct(&png_ptr,&info_ptr,&end_info);
366 for(i=0;i<num_palette;i++) {
367 pal_red[i]=(palette+i)->red>>k;
368 pal_green[i]=(palette+i)->green>>k;
369 pal_blue[i]=(palette+i)->blue>>k;
371 pal_colors=num_palette;
372 if(pic.Bitmap!=NULL) free(pic.Bitmap);
373 pic.Bitmap=(byte *)calloc(rowbytes*height,sizeof(byte));
377 for(i=0;i<rowbytes;i++) {
378 for(j=0;j<height;j++) {
380 i,j,row_pointers[j][i]);
384 a.Xshift=(VGLDisplay->Xsize-pic.Xsize)/2;
385 a.Yshift=(VGLDisplay->Ysize-pic.Ysize)/2;
402 kbd_action(int x, int y, char key)
405 if(key!='n') auto_chg=0;
416 if(a.zoom<1) a.zoom=1;
420 a.Xshift+=VGLDisplay->Xsize/5;
424 a.Xshift-=VGLDisplay->Xsize/5;
428 a.Yshift+=VGLDisplay->Ysize/5;
432 a.Yshift-=VGLDisplay->Ysize/5;
439 if(a.rotate) a.rotate=0;
451 png_load(pres[cur_img]);
462 png_load(pres[cur_img]);
471 main(int argc, char *argv[])
478 struct termios t_new,t_old;
486 log=fopen("/png/view.log","w");
488 while((c=getopt(argc,argv,"r:g:"))!=-1) {
492 if(res>0) max_screen_colors=256;
495 screen_gamma=atof(optarg);
505 VGLInit(SW_CG640x480);
508 VGLInit(SW_VGA_CG320);
511 VGLInit(SW_VGA_MODEX);
514 fprintf(stderr,"No such resolution!\n");
519 fprintf(log,"VGL initialised\n");
523 res=png_load(argv[optind]);
531 fsc=fopen(argv[optind],"r");
533 fprintf(log,"Trying script %s\n",argv[optind]);
536 buf[strlen(buf)-1]='\0';
537 if(strncmp("VIEW SCRIPT",buf,11)!=NULL) {
542 auto_chg=atoi(buf+12);
545 buf[strlen(buf)-1]='\0';
551 pres=(char **)calloc(nimg,sizeof(char *));
552 for(i=0;i<nimg;i++) {
554 buf[strlen(buf)-1]='\0';
560 fprintf(log,"Script with %d entries\n",nimg);
562 png_load(pres[cur_img]);
564 VGLMouseInit(VGL_MOUSEHIDE);
565 /* Prepare the keyboard */
567 memcpy(&t_new,&t_old,sizeof(struct termios));
569 tcsetattr(0,TCSAFLUSH,&t_new);
570 fcntl(0,F_SETFL,O_ASYNC);
571 /* XXX VGLClear doesn't work.. :-(( Prepare a blank background */
572 bkg.Bitmap=(byte *)calloc(VGLDisplay->Xsize*VGLDisplay->Ysize,1);
573 bkg.Xsize=VGLDisplay->Xsize;
574 bkg.Ysize=VGLDisplay->Ysize;
575 bkg.Type=VGLDisplay->Type;
576 signal(SIGIO,kbd_handler);
578 a.Xshift=(VGLDisplay->Xsize-pic.Xsize)/2;
579 a.Yshift=(VGLDisplay->Ysize-pic.Ysize)/2;
583 display(&pic,pal_red,pal_green,pal_blue,&a);
587 fprintf(log,"kbd_action(%c)\n",act);
594 fprintf(log,"changed, redisplaying\n");
596 display(&pic,pal_red,pal_green,pal_blue,&a);
605 VGLMouseStatus(&x,&y,&buttons);
606 if(buttons & MOUSE_BUTTON3DOWN) {
608 fprintf(log,"pop_up called\n");