Esempio n. 1
0
File: img.c Progetto: Gingar/port
/* updates cimg state when header dimensions are know. Only allowed to be called
 * in state 8 and 10.
 * Allocates right amount of memory into buffer, formats it (with background or
 * zeroes, depens on buffer_bytes_per_pixel). Updates dimensions (xww and yww)
 * according to newly known header dimensions. Fills in gamma_stamp, bmp.user
 * (NULL because we not bother with generating bitmap here)
 * and rows_added.
 * Resets strip_optimized if image will be scaled or 
 * Allocates dregs if on exit strip_optimized is nonzero.
 * Allocates and computes gamma_table, otherwise
 * 	sets gamma_table to NULL. Also doesn't make gamma table if image contains less
 * 	than 1024 pixels (it would be probably a waste of time).
 * Output state is always 12 (from input state 8) or 14 (from input state 10).
 *
 * The caller must have set the following elements of cimg:
 *	width
 *	height
 *	buffer_bytes_per_pixel
 *	red_gamma
 *	green_gamma
 *	blue_gamma
 *	strip_optimized
 */
void header_dimensions_known(struct cached_image *cimg)
{
	unsigned short red, green, blue;

#ifdef DEBUG
	if ((cimg->state^8)&13){
		fprintf(stderr,"cimg->state=%d\n",cimg->state);
		internal("Invalid state in header_dimensions_known");
	}
	if (cimg->width<1||cimg->height<1){
		fprintf(stderr,"width=%d height=%d\n",cimg->width, cimg->height);
		internal("Zero dimensions in header_dimensions_known");
	}
#endif /* #ifdef DEBUG */
	if (cimg->wanted_xw<0){
		/* Unspecified width */
		if (cimg->wanted_yw<0){
			/* Unspecified width and height */
			cimg->xww=img_scale_h(cimg->scale, cimg->width);
			cimg->yww=img_scale_v(cimg->scale, cimg->height);
		}else{
			/* Unspecified width specified height */
			cimg->xww=(cimg->yww
				*cimg->width+(cimg->height>>1))
				/cimg->height;
			if (cimg->xww<=0) cimg->xww=1;
			
		}
	}else{
		if (cimg->wanted_yw<0){
/* updates cimg state when header dimensions are know. Only allowed to be called
 * in state 8 and 10.
 * Allocates right amount of memory into buffer, formats it (with background or
 * zeroes, depens on buffer_bytes_per_pixel). Updates dimensions (xww and yww)
 * according to newly known header dimensions. Fills in gamma_stamp, bmp.user
 * (NULL because we not bother with generating bitmap here)
 * and rows_added.
 * Resets strip_optimized if image will be scaled or 
 * Allocates dregs if on exit strip_optimized is nonzero.
 * Allocates and computes gamma_table, otherwise
 * 	sets gamma_table to NULL. Also doesn't make gamma table if image contains less
 * 	than 1024 pixels (it would be probably a waste of time).
 * Output state is always 12 (from input state 8) or 14 (from input state 10).
 *
 * The caller must have set the following elements of cimg:
 *	width
 *	height
 *	buffer_bytes_per_pixel
 *	red_gamma
 *	green_gamma
 *	blue_gamma
 *	strip_optimized
 */
int header_dimensions_known(struct cached_image *cimg)
{
	unsigned short red, green, blue;

#ifdef DEBUG
	if ((cimg->state^8)&13){
		fprintf(stderr,"cimg->state=%d\n",cimg->state);
		internal("Invalid state in header_dimensions_known");
	}
#endif /* #ifdef DEBUG */
	if (cimg->width<1||cimg->height<1){
		/*fprintf(stderr,"width=%d height=%d\n",cimg->width, cimg->height);*/
		return 1;
	}
	if (!is_image_size_sane(cimg->width, cimg->height)) {
		return 1;
	}
	if (cimg->wanted_xw<0){
		/* Unspecified width */
		if (cimg->wanted_yw<0){
			/* Unspecified neither width nor height */
			cimg->xww=img_scale_h(cimg->scale, cimg->width);
			cimg->yww=img_scale_v(cimg->scale, cimg->height);
		}else{
			/* Unspecified width specified height */
			cimg->xww=height2width(cimg->yww,
					cimg->width, cimg->height);
			if (cimg->xww<=0) cimg->xww=1;
			
		}
	}else{
		/* Specified width */
		if (cimg->wanted_yw<0){
			/* Unspecified height, specified width */
			cimg->yww=width2height(cimg->xww,
					cimg->width, cimg->height);
			if (cimg->yww<=0) cimg->yww=1;
		}else if (cimg->wanted_xyw_meaning==MEANING_AUTOSCALE){
			/* Specified height and width and autoscale meant */
			/* Try first to nail the height */
			cimg->yww=cimg->wanted_yw;
			cimg->xww=height2width(cimg->yww,
					cimg->width, cimg->height);
			if (cimg->xww>cimg->wanted_xw)
			{
				/* Width too much, we nail the width */
				cimg->xww=cimg->wanted_xw;
				cimg->yww=width2height(cimg->xww,
						cimg->width, cimg->height);
			}
			
			/* Some sanity checks */
			if (cimg->xww<=0) cimg->xww=1;
			if (cimg->yww<=0) cimg->yww=1;
		}
	}
	if (!is_image_size_sane(cimg->xww, cimg->yww)) {
		cimg->xww = cimg->width;
		cimg->yww = cimg->height;
	}
	if (cimg->width!=cimg->xww||cimg->height!=cimg->yww) cimg->strip_optimized=0;
	cimg->gamma_stamp=gamma_stamp;
	if (cimg->strip_optimized){
		struct bitmap tmpbmp;
		unsigned short *buf_16;
		int i;

		tmpbmp.x=cimg->width;
		tmpbmp.y=1;
		/* No buffer, bitmap is valid from the very beginning */
		cimg->bmp.x=cimg->width;
		cimg->bmp.y=cimg->height;
		if (drv->get_empty_bitmap(&(cimg->bmp))) {
			cimg->dregs = NULL;
			goto skip_img;
		}
		if ((unsigned)cimg->width > MAXINT / sizeof(*buf_16) / 3) overalloc();
		buf_16=mem_alloc(sizeof(*buf_16)*3*cimg->width);
		round_color_sRGB_to_48(&red, &green, &blue
			, cimg->background_color);
		mix_one_color_48(buf_16,cimg->width, red, green, blue);
#ifdef DEBUG
		if (cimg->height<=0){
			fprintf(stderr,"cimg->height=%d\n",cimg->height);
			internal("Invalid cimg->height in strip_optimized section of\
 header_dimensions_known");
		}
#endif /* #ifdef DEBUG */
		/* The skip is uninitialized here and is read by dither_start
		 * but is not used in any malicious way so it doesn't matter
		 */
		tmpbmp.data=cimg->bmp.data;
		cimg->dregs=dither_images?dither_start(buf_16,&tmpbmp):NULL;
		tmpbmp.data=(unsigned char *)tmpbmp.data+cimg->bmp.skip;
		if (cimg->dregs)
			for (i=cimg->height-1;i;i--){
				dither_restart(buf_16,&tmpbmp,cimg->dregs);
				tmpbmp.data=(unsigned char *)tmpbmp.data+cimg->bmp.skip;
			}
		else
			for (i=cimg->height-1;i;i--){
				(*round_fn)(buf_16,&tmpbmp);
				tmpbmp.data=(unsigned char *)tmpbmp.data+cimg->bmp.skip;
			}
		mem_free(buf_16);
		skip_img:
		drv->register_bitmap(&(cimg->bmp));
		if(cimg->dregs) memset(cimg->dregs,0,cimg->width*sizeof(*cimg->dregs)*3);
		cimg->bmp.user=(void *)&end_callback_hit; /* Nonzero value */
		/* This ensures the dregs are none and because strip
		 * optimization is unusable in interlaced pictures,
		 * this saves the zeroing out at the beginning of the
		 * decoder itself.
		 */
	}else {