⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fbi.c

📁 linux下开源图片codec
💻 C
📖 第 1 页 / 共 3 页
字号:
	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 + -