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

📄 img.c

📁 ELinks is an advanced and well-established feature-rich text mode web (HTTP/FTP/..) browser. ELinks
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifdef DEBUG	if (cimg->state!=12&&cimg->state!=14){		fprintf(stderr,"cimg->state=%d\n",cimg->state);		internal("invalid state in buffer_to_16");	}#endif /* #ifdef DEBUG */	switch (cimg->buffer_bytes_per_pixel){		case 3:			if (cimg->gamma_table){				apply_gamma_exponent_24_to_48_table(tmp, buffer,					cimg->width*height					,cimg->gamma_table);			}			else{				apply_gamma_exponent_24_to_48(tmp,buffer,cimg->width					*height					,user_gamma/cimg->red_gamma					,user_gamma/cimg->green_gamma					,user_gamma/cimg->blue_gamma);			}		break;		case 3*sizeof(unsigned short):			if (cimg->gamma_table){				apply_gamma_exponent_48_to_48_table(tmp					,(unsigned short *)buffer					,cimg->width*height, cimg->gamma_table);			}else{				apply_gamma_exponent_48_to_48(tmp,(unsigned short *)buffer					,cimg->width*height,					user_gamma/cimg->red_gamma,					user_gamma/cimg->green_gamma,					user_gamma/cimg->blue_gamma);			}		break;		/* Alpha's: */		case 4: 		{			round_color_sRGB_to_48(&red,&green,&blue,cimg->background_color);			if (cimg->gamma_table){				apply_gamma_exponent_and_undercolor_32_to_48_table(						tmp, buffer, cimg->width *height,						cimg->gamma_table, red, green, blue);			}else{								apply_gamma_exponent_and_undercolor_32_to_48(tmp,buffer					,cimg->width*height,					user_gamma/cimg->red_gamma,					user_gamma/cimg->green_gamma,					user_gamma/cimg->blue_gamma,					red, green, blue);			}		}		break;		case 4*sizeof(unsigned short):		{			round_color_sRGB_to_48(&red, &green, &blue,				cimg->background_color);			if (cimg->gamma_table){				apply_gamma_exponent_and_undercolor_64_to_48_table					(tmp, (unsigned short *)buffer, cimg->width*height					,cimg->gamma_table, red, green, blue);			}else{				apply_gamma_exponent_and_undercolor_64_to_48(tmp					,(unsigned short*)buffer,cimg->width*height,					user_gamma/cimg->red_gamma,					user_gamma/cimg->green_gamma,					user_gamma/cimg->blue_gamma,					red,green,blue);			}		}		break;		#ifdef DEBUG		default:		internal("buffer_to_16: unknown mem organization");#endif /* #ifdef DEBUG */	}	return tmp;}/* Returns allocated buffer with the resulting data and does not free the input * buffer. May be called only in states 12 and 14 of cimg * use_strip: 1 if the image is already registered and prepare_strip and * commit_strip is to be used * 0: if the image is not yet registered and instead one big register_bitmap * will be used eventually * dregs must be externally allocated and contain required value or must be * NULL. * if !dregs then rounding is performed instead of dithering. * dregs are not freed.  * bottom dregs are placed back into dregs. * Before return the bitmap will be in registered state and changes will be * commited. * height must be >=1 !!! */void buffer_to_bitmap_incremental(struct cached_image *cimg	,unsigned char *buffer, int height, int yoff, int *dregs, int use_strip){#define max_height 16/* max_height must be at least 1 */	unsigned short *tmp;	struct bitmap tmpbmp;	int add1=0, add2;#ifdef DEBUG	if (cimg->state!=12&&cimg->state!=14){		fprintf(stderr,"cimg->state=%d\n",cimg->state);		internal("Invalid state in buffer_to_bitmap_incremental\n");	}	if (height<1){		fprintf(stderr,"height=%d\n",height);		internal("Invalid height in buffer_to_bitmap_incremental\n");	}	if (cimg->width<1||cimg->height<1){		fprintf(stderr,"cimg->width=%d, cimg->height=%d\n",cimg->width,				cimg->height);		internal("Invalid cimg->width x cimg->height in\buffer_to_bitmap_incremental");	}#endif /* #ifdef DEBUG */	if ((unsigned)cimg->width > MAXINT / max_height / 3 / sizeof(*tmp)) overalloc();	tmp=mem_alloc(cimg->width*(height<max_height?height:max_height)*3*sizeof(*tmp));	/* Prepare a fake bitmap for dithering */	tmpbmp.x=cimg->width;	if (!use_strip){	       tmpbmp.data=(unsigned char *)cimg->bmp.data+cimg->bmp.skip*yoff;	       add1=cimg->bmp.skip*max_height;	}	add2=cimg->buffer_bytes_per_pixel*cimg->width*max_height;not_enough:	tmpbmp.y=height<max_height?height:max_height;	if (use_strip) tmpbmp.data=drv->prepare_strip(&(cimg->bmp),yoff,tmpbmp.y);	tmpbmp.skip=cimg->bmp.skip;	buffer_to_16(tmp, cimg, buffer, tmpbmp.y);	if (dregs){	       	dither_restart(tmp, &tmpbmp, dregs);	}	else {				(*round_fn)(tmp, &tmpbmp);	}	if (use_strip) drv->commit_strip(&(cimg->bmp),yoff,tmpbmp.y);	height-=tmpbmp.y;	if (!height) goto end;	buffer+=add2;	yoff+=tmpbmp.y;	tmpbmp.data=(unsigned char *)tmpbmp.data+add1; 	/* This has no effect if use_strip but it's faster	 * to add to bogus value than to play with	 * conditional jumps.	 */	goto not_enough;end:	mem_free(tmp);	if (!use_strip) drv->register_bitmap(&(cimg->bmp));}/* Takes the buffer and resamples the data into the bitmap. Automatically * destroys the previous bitmap. Must be called only when cimg->buffer is valid. * Sets bmp->user to non-NULL * If gamma_table is used, it must be still allocated here (take care if you * want to destroy gamma table and call buffer_to_bitmap, first call buffer_to_bitmap * and then destroy gamma_table). */void buffer_to_bitmap(struct cached_image *cimg){	unsigned short *tmp, *tmp1;	int ix, iy, ox, oy, gonna_be_smart;	int *dregs;#ifdef DEBUG	if(cimg->state!=12&&cimg->state!=14){		fprintf(stderr,"cimg->state=%d\n",cimg->state);		internal("buffer_to_bitmap called in invalid state");	}	if (cimg->strip_optimized) internal("strip_optimized in buffer_to_bitmap");	if (cimg->width<1||cimg->height<1){		fprintf(stderr,"cimg->width=%d, cimg->height=%d\n",cimg->width,				cimg->height);		internal("Invalid cimg->width x cimg->height in\buffer_to_bitmap");	}#endif /* #ifdef DEBUG */	if (!cimg->rows_added) return;	/* Here of course width and height must be already filled */	cimg->rows_added=0;	ix=cimg->width;	iy=cimg->height;	ox=cimg->xww;	oy=cimg->yww;	if (ix==ox&&iy==oy) gonna_be_smart=1;	else{		gonna_be_smart=0;		if (ix && (unsigned)ix * (unsigned)iy / (unsigned)ix != (unsigned)iy) overalloc();		if ((unsigned)ix * (unsigned)iy > MAXINT / sizeof(*tmp) / 3) overalloc();		tmp=mem_alloc(ix*iy*3*sizeof(*tmp));		buffer_to_16(tmp,cimg,cimg->buffer,iy);		if (!cimg->decoder){			mem_free(cimg->buffer);			cimg->buffer=NULL;		}			/* Scale the image to said size */#ifdef DEBUG		if (ox<=0||oy<=0){			internal("ox or oy <=0 before resampling image");		}#endif /* #ifdef DEBUG */		if (ix!=ox||iy!=oy){			/* We must really scale */			tmp1=tmp;			scale_color(tmp1,ix,iy,&tmp,ox,oy);		}	}	if (cimg->bmp.user) drv->unregister_bitmap(&cimg->bmp);	cimg->bmp.x=ox;	cimg->bmp.y=oy;	drv->get_empty_bitmap(&(cimg->bmp));	if (gonna_be_smart){		if (dither_images) {			if ((unsigned)cimg->width > MAXINT / 3 / sizeof(*dregs)) overalloc();			dregs = mem_calloc(sizeof(*dregs)*3*cimg->width);		} else {			dregs = 0;		}		buffer_to_bitmap_incremental(cimg, cimg->buffer, cimg->height,			0, dregs, 0);		if (dregs) mem_free(dregs);	}else{		if (dither_images)			dither(tmp,&(cimg->bmp));		else			(*round_fn)(tmp,&(cimg->bmp));		mem_free(tmp);		drv->register_bitmap(&(cimg->bmp));	}	cimg->bmp.user=(void *)&end_callback_hit;	/* Indicate that the bitmap is valid. The value is just any	   nonzero value */	cimg->rows_added=0;	/* Indicate the bitmap is up-to-date */}/* Performs state transition for end of stream or error in image or * end of image */void img_end(struct cached_image *cimg){	switch(cimg->state){		case 12:		case 14:		if (cimg->strip_optimized){		       if (cimg->dregs)	mem_free(cimg->dregs);		}		else{			buffer_to_bitmap(cimg);			mem_free(cimg->buffer);		}		if (cimg->gamma_table) mem_free(cimg->gamma_table);		case 8:		case 10:		destroy_decoder(cimg);		case 0:		case 1:		case 2:			case 3:		case 9:		case 11:		case 13:		case 15:		break;	#ifdef DEBUG		default:		fprintf(stderr,"state=%d\n",cimg->state);		internal("Invalid state encountered in end");#endif /* #ifdef DEBUG */	}	cimg->state|=1;}void r3l0ad(struct cached_image *cimg, struct g_object_image *goi){	cimg->eof_hit=0;	cimg->last_count=goi->af->rq->ce->count;	cimg->last_count2=goi->af->rq->ce->count2;	cimg->gamma_stamp=gamma_stamp;	switch(cimg->state){		case 8:		case 10:		destroy_decoder(cimg);		case 1:		case 3:		case 9:		case 11:		case 0:		case 2:		break;		case 12:		if (cimg->gamma_table) mem_free(cimg->gamma_table);		destroy_decoder(cimg);		if (cimg->strip_optimized){			if (cimg->dregs) mem_free(cimg->dregs);		}else{			mem_free(cimg->buffer);		}		if (cimg->bmp.user){			case 13:			drv->unregister_bitmap(&cimg->bmp);		}                cimg->xww=img_scale_h(cimg->scale, cimg->wanted_xw<0?32:cimg->wanted_xw);                cimg->yww=img_scale_v(cimg->scale, cimg->wanted_yw<0?32:cimg->wanted_yw);		break;		case 14:		if (cimg->gamma_table) mem_free(cimg->gamma_table);		destroy_decoder(cimg);		if (cimg->strip_optimized){			if (cimg->dregs) mem_free(cimg->dregs);		}else{			mem_free(cimg->buffer);		}		if (cimg->bmp.user){			case 15:			drv->unregister_bitmap(&cimg->bmp);		}		break;#ifdef DEBUG		default:		fprintf(stderr,"cimg->state=%d\n",cimg->state);		internal("Invalid state in r3l0ad()");#endif /* #ifdef DEBUG */	}	cimg->state&=2;}/* Returns 1 if match. If returns 1 then test is mem_free'd. * If doesn't return 1 then returns 0 * dtest - Destructive TEST */static inline int dtest(unsigned char *template, unsigned char *test){	if (strcasecmp(template,test)) return 0;	else{		mem_free(test);		return 1;	}}/* content_type will be mem_free'd before return from this function. * This may be called only in state 0 or 2 */void type(struct cached_image *cimg, unsigned char *content_type){#ifdef DEBUG	if (cimg->state!=0&&cimg->state!=2){		fprintf(stderr,"cimg->state=%d\n",cimg->state);		internal("Invalid state encountered in type()");	}#endif /* #ifdef DEBUG */#ifdef HAVE_JPEG	if (dtest("image/jpeg",content_type)){		cimg->image_type=IM_JPG;		jpeg_start(cimg);	}else if (dtest("image/jpg",content_type)){		cimg->image_type=IM_JPG;		jpeg_start(cimg);	}else if (dtest("image/jpe",content_type)){		cimg->image_type=IM_JPG;		jpeg_start(cimg);	}else if (dtest("image/pjpe",content_type)){		cimg->image_type=IM_JPG;		jpeg_start(cimg);	}else if (dtest("image/pjpeg",content_type)){		cimg->image_type=IM_JPG;		jpeg_start(cimg);	}else if (dtest("image/pjpg",content_type)){		cimg->image_type=IM_JPG;		jpeg_start(cimg);	}else #endif /* #ifdef HAVE_JPEG */		if (dtest("image/png",content_type)){		cimg->image_type=IM_PNG;		png_start(cimg);	}else if (dtest("image/x-png",content_type)){		cimg->image_type=IM_PNG;		png_start(cimg);	}else if (dtest("image/gif",content_type)){		cimg->image_type=IM_GIF;		gif_start(cimg);	}else if (dtest("image/x-xbitmap",content_type)){		cimg->image_type=IM_XBM;		xbm_start(cimg);#ifdef HAVE_TIFF	}else if (dtest("image/tiff",content_type)){		cimg->image_type=IM_TIFF;		tiff_start(cimg);	}else if (dtest("image/tif",content_type)){		cimg->image_type=IM_TIFF;		tiff_start(cimg);#endif /* #ifdef HAVE_TIFF */	}else{		/* Error */		mem_free(content_type);		img_end(cimg);		return;	}	cimg->state|=8; /* Advance the state according to the table in			   links-doc.html */	cimg->last_length=0;}/* Doesn't print anything. Downloads more data if available. * Sets up cimg->reparse and cimg->xww and cimg->yww accordingly to * the state of the decoder. When changing xww and yww also changes xw and yw * in g_object_image. *      return value 1 means the data were chopped and the caller shall not redraw *      	(because it would be too slow and because we are probably choked *      	up with the data) */int img_process_download(struct g_object_image *goi, struct f_data_c *fdatac){	unsigned char *data, *dataend, *ctype;	int length;	struct cached_image *cimg = goi->cimg;	int chopped=0;#ifdef DEBUG	if (!goi->af) internal("NULL goi->af in process_download\n");	if (cimg->state>=16){ /* Negative don't occur becaus it's unsigned char */		fprintf(stderr,"cimg->state=%d\n",cimg->state);		internal("Invalid cimg->state in img_process_download\n");	}#endif /* #ifdef DEBUG */	if (!goi->af->rq) return 0;	if (!goi->af->rq->ce) goto end;	if (goi->af->rq->ce->count2!=cimg->last_count2||		(goi->af->rq->ce->count!=cimg->last_count && cimg->eof_hit) ||		(cimg->state>=12&&gamma_stamp!=cimg->gamma_stamp)){		/* Reload */		r3l0ad(cimg,goi);	}	/*if (!goi->af->rq->ce->head) goto end;*/ /* Mikulas: head muze byt NULL*/ /* Mikulas: tak se to zpracuje a nebude se skakat na konec, kdyz je to NULL */	if (cimg->state==0||cimg->state==2){		/* Type still unknown */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -