📄 fbi.c
字号:
break; } switch_last = fb_switch_state; return;}/* ---------------------------------------------------------------------- */static void free_image(struct ida_image *img){ if (img) { if (img->data) free(img->data); free(img); }}static struct ida_image*read_image(char *filename){ char command[1024]; struct ida_loader *loader = NULL; struct ida_image *img; struct list_head *item; char blk[512]; FILE *fp; unsigned int y; void *data; new_image = 1; /* open file */ if (NULL == (fp = fopen(filename, "r"))) { fprintf(stderr,"open %s: %s\n",filename,strerror(errno)); return NULL; } memset(blk,0,sizeof(blk)); fread(blk,1,sizeof(blk),fp); rewind(fp); /* pick loader */ list_for_each(item,&loaders) { loader = list_entry(item, struct ida_loader, list); if (NULL == loader->magic) break; if (0 == memcmp(blk+loader->moff,loader->magic,loader->mlen)) break; loader = NULL; } if (NULL == loader) { /* no loader found, try to use ImageMagick's convert */ sprintf(command,"convert \"%s\" ppm:-",filename); if (NULL == (fp = popen(command,"r"))) return NULL; loader = &ppm_loader; } /* load image */ img = malloc(sizeof(*img)); memset(img,0,sizeof(*img)); data = loader->init(fp,filename,0,&img->i,0); if (NULL == data) { fprintf(stderr,"loading %s [%s] FAILED\n",filename,loader->name); free_image(img); return NULL; } img->data = malloc(img->i.width * img->i.height * 3); for (y = 0; y < img->i.height; y++) { if (switch_last != fb_switch_state) console_switch(1); loader->read(img->data + img->i.width * 3 * y, y, data); } loader->done(data); return img;}static struct ida_image*scale_image(struct ida_image *src, float scale){ struct op_resize_parm p; struct ida_rect rect; struct ida_image *dest; void *data; unsigned int y; dest = malloc(sizeof(*dest)); memset(dest,0,sizeof(*dest)); memset(&rect,0,sizeof(rect)); memset(&p,0,sizeof(p)); p.width = src->i.width * scale; p.height = src->i.height * scale; p.dpi = src->i.dpi; if (0 == p.width) p.width = 1; if (0 == p.height) p.height = 1; data = desc_resize.init(src,&rect,&dest->i,&p); dest->data = malloc(dest->i.width * dest->i.height * 3); for (y = 0; y < dest->i.height; y++) { if (switch_last != fb_switch_state) console_switch(1); desc_resize.work(src,&rect, dest->data + 3 * dest->i.width * y, y, data); } desc_resize.done(data); return dest;}static float auto_scale(struct ida_image *img){ float xs,ys,scale; xs = (float)fb_var.xres / img->i.width; ys = (float)fb_var.yres / img->i.height; scale = (xs < ys) ? xs : ys; return scale;}/* ---------------------------------------------------------------------- */static unsigned char *convert_line(int bpp, int line, int owidth, char unsigned *dest, char unsigned *buffer){ unsigned char *ptr = (void*)dest; unsigned short *ptr2 = (void*)dest; unsigned long *ptr4 = (void*)dest; int x; switch (fb_var.bits_per_pixel) { case 8: dither_line(buffer, ptr, line, owidth); ptr += owidth; return ptr; case 15: case 16: for (x = 0; x < owidth; x++) { ptr2[x] = lut_red[buffer[x*3]] | lut_green[buffer[x*3+1]] | lut_blue[buffer[x*3+2]]; } ptr2 += owidth; return (char*)ptr2; case 24: for (x = 0; x < owidth; x++) { ptr[3*x+2] = buffer[3*x+0]; ptr[3*x+1] = buffer[3*x+1]; ptr[3*x+0] = buffer[3*x+2]; } ptr += owidth * 3; return ptr; case 32: for (x = 0; x < owidth; x++) { ptr4[x] = lut_red[buffer[x*3]] | lut_green[buffer[x*3+1]] | lut_blue[buffer[x*3+2]]; } ptr4 += owidth; return (char*)ptr4; default: /* keep compiler happy */ return NULL; }}/* ---------------------------------------------------------------------- */static void init_one(int32_t *lut, int bits, int shift){ int i; if (bits > 8) for (i = 0; i < 256; i++) lut[i] = (i << (bits + shift - 8)); else for (i = 0; i < 256; i++) lut[i] = (i >> (8 - bits)) << shift;}static voidlut_init(int depth){ if (fb_var.red.length && fb_var.green.length && fb_var.blue.length) { /* fb_var.{red|green|blue} looks sane, use it */ init_one(lut_red, fb_var.red.length, fb_var.red.offset); init_one(lut_green, fb_var.green.length, fb_var.green.offset); init_one(lut_blue, fb_var.blue.length, fb_var.blue.offset); } else { /* fallback */ int i; switch (depth) { case 15: for (i = 0; i < 256; i++) { lut_red[i] = (i & 0xf8) << 7; /* bits -rrrrr-- -------- */ lut_green[i] = (i & 0xf8) << 2; /* bits ------gg ggg----- */ lut_blue[i] = (i & 0xf8) >> 3; /* bits -------- ---bbbbb */ } break; case 16: for (i = 0; i < 256; i++) { lut_red[i] = (i & 0xf8) << 8; /* bits rrrrr--- -------- */ lut_green[i] = (i & 0xfc) << 3; /* bits -----ggg ggg----- */ lut_blue[i] = (i & 0xf8) >> 3; /* bits -------- ---bbbbb */ } break; case 24: for (i = 0; i < 256; i++) { lut_red[i] = i << 16; /* byte -r-- */ lut_green[i] = i << 8; /* byte --g- */ lut_blue[i] = i; /* byte ---b */ } break; } }}static unsigned short calc_gamma(int n, int max){ int ret =65535.0 * pow((float)n/(max), 1 / fbgamma); if (ret > 65535) ret = 65535; if (ret < 0) ret = 0; return ret;}static voidlinear_palette(int bit){ int i, size = 256 >> (8 - bit); for (i = 0; i < size; i++) red[i] = green[i] = blue[i] = calc_gamma(i,size);}static voidsvga_dither_palette(int r, int g, int b){ int rs, gs, bs, i; rs = 256 / (r - 1); gs = 256 / (g - 1); bs = 256 / (b - 1); for (i = 0; i < 256; i++) { red[i] = calc_gamma(rs * ((i / (g * b)) % r), 255); green[i] = calc_gamma(gs * ((i / b) % g), 255); blue[i] = calc_gamma(bs * ((i) % b), 255); }}static voidsvga_display_image(struct ida_image *img, int xoff, int yoff){ unsigned int dwidth = MIN(img->i.width, fb_var.xres); unsigned int dheight = MIN(img->i.height, fb_var.yres); unsigned int data, video, bank, offset, bytes, y; if (!visible) return; bytes = (fb_var.bits_per_pixel+7)/8; /* offset for image data (image > screen, select visible area) */ offset = (yoff * img->i.width + xoff) * 3; /* offset for video memory (image < screen, center image) */ video = 0, bank = 0; if (img->i.width < fb_var.xres) video += bytes * ((fb_var.xres - img->i.width) / 2); if (img->i.height < fb_var.yres) video += fb_fix.line_length * ((fb_var.yres - img->i.height) / 2); /* go ! */ for (data = 0, y = 0; data < img->i.width * img->i.height * 3 && data / img->i.width / 3 < dheight; data += img->i.width * 3, video += fb_fix.line_length) { convert_line(fb_var.bits_per_pixel, y++, dwidth, fb_mem+video, img->data + data + offset); }}static intsvga_show(struct ida_image *img, int timeout, char *desc, char *info, int *nr){ static int paused = 0; int exif = 0, help = 0; int rc; char key[11]; fd_set set; struct timeval limit; char linebuffer[80]; int fdmax; *nr = 0; if (NULL == img) return KEY_SPACE; /* skip */ if (new_image) { /* start with centered image, if larger than screen */ if (img->i.width > fb_var.xres) left = (img->i.width - fb_var.xres) / 2; if (img->i.height > fb_var.yres && !textreading) top = (img->i.height - fb_var.yres) / 2; new_image = 0; } redraw = 1; for (;;) { if (redraw) { redraw = 0; if (img->i.height <= fb_var.yres) { top = 0; } else { if (top < 0) top = 0; if (top + fb_var.yres > img->i.height) top = img->i.height - fb_var.yres; } if (img->i.width <= fb_var.xres) { left = 0; } else { if (left < 0) left = 0; if (left + fb_var.xres > img->i.width) left = img->i.width - fb_var.xres; } svga_display_image(img, left, top); status(desc, info); } if (switch_last != fb_switch_state) { console_switch(0); continue; } FD_SET(0, &set); fdmax = 1;#ifdef HAVE_LIBLIRC if (-1 != lirc) { FD_SET(lirc,&set); fdmax = lirc+1; }#endif limit.tv_sec = timeout; limit.tv_usec = 0; rc = select(fdmax, &set, NULL, NULL, (-1 != timeout && !paused) ? &limit : NULL); if (switch_last != fb_switch_state) { console_switch(0); continue; } if (0 == rc) return KEY_TIMEOUT; if (FD_ISSET(0,&set)) { /* stdin, i.e. keyboard */ rc = read(0, key, sizeof(key)-1); if (rc < 1) { /* EOF */ return KEY_EOF; } key[rc] = 0; }#ifdef HAVE_LIBLIRC if (lirc != -1 && FD_ISSET(lirc,&set)) { /* lirc input */ if (-1 == lirc_fbi_havedata(&rc,key)) { fprintf(stderr,"lirc: connection lost\n"); close(lirc); lirc = -1; } key[rc] = 0; }#endif if (rc == 1 && (*key == 'q' || *key == 'Q' || *key == 'e' || *key == 'E' || *key == '\x1b' || *key == '\n')) { if (*key == '\n') return KEY_TAGFILE; if (*key == '\x1b') return KEY_ESC; return KEY_Q; } else if (0 == strcmp(key, " ")) { if (textreading && top < (int)(img->i.height - fb_var.yres)) { redraw = 1; top += (fb_var.yres-100); } else { return KEY_SPACE; } } else if (0 == strcmp(key, "\x1b[A") && img->i.height > fb_var.yres) { redraw = 1; top -= steps; } else if (0 == strcmp(key, "\x1b[B") && img->i.height > fb_var.yres) { redraw = 1; top += steps; } else if (0 == strcmp(key, "\x1b[1~") && img->i.height > fb_var.yres) { redraw = 1; top = 0; } else if (0 == strcmp(key, "\x1b[4~")) { redraw = 1; top = img->i.height - fb_var.yres; } else if (0 == strcmp(key, "\x1b[D") && img->i.width > fb_var.xres) { redraw = 1; left -= steps; } else if (0 == strcmp(key, "\x1b[C") && img->i.width > fb_var.xres) { redraw = 1; left += steps; } else if (0 == strcmp(key, "\x1b[5~")) { return KEY_PGUP; } else if (0 == strcmp(key, "\x1b[6~") || 0 == strcmp(key, "n") || 0 == strcmp(key, "N")) { return KEY_PGDN; } else if (0 == strcmp(key, "+")) { return KEY_PLUS; } else if (0 == strcmp(key, "-")) { return KEY_MINUS; } else if (0 == strcmp(key, "a") || 0 == strcmp(key, "A")) { return KEY_ASCALE; } else if (0 == strcmp(key, "p") || 0 == strcmp(key, "P")) { if (-1 != timeout) { paused = !paused; status(paused ? "pause on " : "pause off", NULL); } } else if (0 == strcmp(key, "D")) { return KEY_DELETE; } else if (0 == strcmp(key, "r") || 0 == strcmp(key, "R")) { return KEY_ROT_CW; } else if (0 == strcmp(key, "l") || 0 == strcmp(key, "L")) { return KEY_ROT_CCW; } else if (0 == strcmp(key, "h") || 0 == strcmp(key, "H")) { if (!help) { show_help(); help = 1; } else { redraw = 1; help = 0; } exif = 0; } else if (0 == strcmp(key, "i") || 0 == strcmp(key, "I")) { if (!exif) { show_exif(fcurrent); exif = 1; } else { redraw = 1; exif = 0; } help = 0; } else if (0 == strcmp(key, "v") || 0 == strcmp(key, "V")) { return KEY_VERBOSE; } else if (0 == strcmp(key, "t") || 0 == strcmp(key, "T")) { return KEY_DESC; } else if (rc == 1 && (*key == 'g' || *key == 'G')) { return KEY_GOTO; } else if (rc == 1 && (*key == 's' || *key == 'S')) { return KEY_SCALE; } else if (rc == 1 && *key >= '0' && *key <= '9') { *nr = *nr * 10 + (*key - '0'); sprintf(linebuffer, "> %d",*nr); status(linebuffer, NULL); } else { *nr = 0;#if 0 debug_key(key);#endif } }}static void scale_fix_top_left(float old, float new, struct ida_image *img){ unsigned int width, height; float cx,cy; cx = (float)(left + fb_var.xres/2) / (img->i.width * old); cy = (float)(top + fb_var.yres/2) / (img->i.height * old); width = img->i.width * new; height = img->i.height * new; left = cx * width - fb_var.xres/2; top = cy * height - fb_var.yres/2;}/* ---------------------------------------------------------------------- */static int read_comment(char *filename, char *dest, int len){ int fh,rc,i; if (-1 == (fh = open(filename, O_RDONLY))) goto err; rc = read(fh,dest,len); if (rc <= 0) goto err; close(fh); for (i = 0; i < rc; i++) if ('\n' == dest[i] || '\0' == dest[i]) break; dest[i] = 0; return i; err: if (-1 != fh) close(fh); return -1;}static void write_comment(char *filename, char *dest, int len)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -