Example #1
0
File: png.c Project: Gingar/port
void png_info_callback(png_structp png_ptr, png_infop info_ptr)
{
	int bit_depth, color_type, intent;
	double gamma;
	int bytes_per_pixel=3;
	struct cached_image *cimg;

	cimg=global_cimg;

	bit_depth=png_get_bit_depth(png_ptr, info_ptr);
	color_type=png_get_color_type(png_ptr, info_ptr);
	if (color_type == PNG_COLOR_TYPE_PALETTE)
        	png_set_expand(png_ptr);
    	if (color_type == PNG_COLOR_TYPE_GRAY &&
        	bit_depth < 8) png_set_expand(png_ptr);
	if (png_get_valid(png_ptr, info_ptr,
        	PNG_INFO_tRNS)){
		png_set_expand(png_ptr); /* Legacy version of
		png_set_tRNS_to_alpha(png_ptr); */
		bytes_per_pixel++;
	}
	if (color_type == PNG_COLOR_TYPE_GRAY ||
		color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png_ptr);
	if (bit_depth==16){
#ifndef REPACK_16
#ifdef C_LITTLE_ENDIAN
		/* We use native endianity only if unsigned short is 2-byte
		 * because otherwise we have to reassemble the buffer so we
		 * will leave in the libpng-native big endian.
		 */
		png_set_swap(png_ptr);
#endif /* #ifdef C_LITTLE_ENDIAN */
#endif /* #ifndef REPACK_16 */
		bytes_per_pixel*=sizeof(unsigned short);
	}
	png_set_interlace_handling(png_ptr);
	if (color_type==PNG_COLOR_TYPE_RGB_ALPHA
		||color_type==PNG_COLOR_TYPE_GRAY_ALPHA){
		if (bytes_per_pixel==3
			||bytes_per_pixel==3*sizeof(unsigned short))
			bytes_per_pixel=4*bytes_per_pixel/3;
	}
	cimg->width=png_get_image_width(png_ptr,info_ptr);
	cimg->height=png_get_image_height(png_ptr,info_ptr);
	cimg->buffer_bytes_per_pixel=bytes_per_pixel;
	if (png_get_sRGB(png_ptr, info_ptr, &intent)){
		gamma=sRGB_gamma;
	}
	else
 	{              
  		if (!png_get_gAMA(png_ptr, info_ptr, &gamma)){
			gamma=sRGB_gamma;
		}
	}
	cimg->red_gamma=gamma;
	cimg->green_gamma=gamma;
	cimg->blue_gamma=gamma;
	png_read_update_info(png_ptr,info_ptr);                 
	cimg->strip_optimized=0;
	header_dimensions_known(cimg);
}
/* length is always !=NULL */
static int xbm_decode(struct cached_image *cimg, unsigned char *data, int length)
{
    struct xbm_decoder *deco=(struct xbm_decoder *)cimg->decoder;
    /* okurky v decu ;-) */
    int a;
    int must_return=0;

restart_again:
    if (must_return&&!length)return 0;
    must_return=0;
    a=min(length,XBM_BUFFER_LEN-deco->buffer_pos);
    memcpy(deco->buffer+deco->buffer_pos,data,a);
    length-=a;
    deco->buffer_pos+=a;
    if (!deco->buffer_pos)return 0; 	/* z toho nic plodnyho nevznikne */
    data+=a;
    if (!deco->in_data_block&&deco->partnum)
    {
        unsigned char *p;
        int a;
        int b,d;
        p=deco->buffer;
        a=deco->buffer_pos;
        *(deco->numdest)=xbm_read_num(&p,&a,&(deco->partnum),&d,&b);
        /* p i a ukazuje na 1. neciselnej znak (at uz za mezerama bylo cislo nebo nebylo) */
        memmove(deco->buffer,p,a);
        deco->buffer_pos=a;
        if (deco->partnum) {
            must_return=1;    /* zase konec bufferu */
            goto restart_again;
        }
    }
    if (deco->width<0||deco->height<0)	/* decoding header */
    {
        unsigned char *p,*q;
        int *d;
        int a;
        int base, digits;

        p=my_memmem(deco->buffer,deco->buffer_pos,cast_uchar "width",5);
        q=my_memmem(deco->buffer,deco->buffer_pos,cast_uchar "height",6);

        if (!p&&!q)	/* sezereme zacatek */
        {
            int a=deco->buffer_pos>5?deco->buffer_pos:0;	/* nesmime ukrast kus width/height */
            memmove(deco->buffer,deco->buffer+deco->buffer_pos-a,deco->buffer_pos-a);	/* sezereme to pred width/height */
            deco->buffer_pos-=a;
            must_return=1;
            goto restart_again;
        }

        p=p&&q?min(p,q):max(p,q);	/* bereme vetsi, protoze ten 2. je NULL */
        memmove(deco->buffer,p,(deco->buffer_pos)+(deco->buffer)-p);	/* sezereme to pred width/height */
        deco->buffer_pos-=p-deco->buffer;
        /* deco->buffer zacina height/width */
        if (deco->buffer[0]=='w') {
            p=deco->buffer+5;
            d=&(deco->width);
        }
        else {
            p=deco->buffer+6;
            d=&(deco->height);
        }

        a=deco->buffer_pos+deco->buffer-p;
        xbm_skip_space_tab(&p,&a);
        if (!a) {
            must_return=1;    /* v bufferu je: width/height, whitespace, konec */
            goto restart_again;
        }
        *d=xbm_read_num(&p,&a,&(deco->partnum),&digits, &base);
        if (deco->partnum)deco->numdest=d,must_return=1;
        /* p i a ukazuje na 1. neciselnej znak (at uz za mezerama bylo cislo nebo nebylo) */
        memmove(deco->buffer,p,a);
        deco->buffer_pos=a;
        goto restart_again;
    }
    else	/* decoding data */
    {
        unsigned char *p;
        int a;
        int d=0,b=10;
        if (!deco->in_data_block)
        {
            p=memchr(deco->buffer,'{',deco->buffer_pos);
            if (!p) {
                deco->buffer_pos=0;    /* sezerem celej blok a cekame na zavorku */
                must_return=1;
                goto restart_again;
            }

            cimg->width=deco->width;
            cimg->height=deco->height;
            cimg->buffer_bytes_per_pixel=3;
            cimg->red_gamma=display_red_gamma;
            cimg->green_gamma=display_green_gamma;
            cimg->blue_gamma=display_blue_gamma;
            cimg->strip_optimized=0;
            if (header_dimensions_known(cimg)) {
                img_end(cimg);
                return 1;
            }

            deco->in_data_block=1;
            p++;
            memmove(deco->buffer,p,deco->buffer_pos+deco->buffer-p);	/* sezereme to pred width/height */
            deco->buffer_pos-=p-deco->buffer;
            deco->image_pos=0;
            deco->pixels=deco->width*deco->height;
            deco->line_pos=0;
        }
        p=deco->buffer;
        a=deco->buffer_pos;
        if (!deco->partnum) xbm_skip_whitespace(&p,&a);
        if (!a) {
            must_return=1;
            goto restart_again;
        }
        deco->actual_eight=xbm_read_num(&p,&a,&(deco->partnum),&d,&b);
        memmove(deco->buffer,p,a);
        deco->buffer_pos=a;
        if (deco->partnum)must_return=1;
        else put_eight(cimg,(b==16&&d>2)||(b==10&&deco->actual_eight>255)?16:8);
        if (deco->image_pos>=deco->pixels) {
            img_end(cimg);
            return 1;
        }
        goto restart_again;

    }
}
Example #3
0
void jpeg_restart(struct cached_image *cimg, unsigned char *data, int length)
{
	struct jpg_decoder *deco;

	deco=(struct jpg_decoder *)(cimg->decoder);
#ifdef DEBUG
	if (!deco) internal("NULL decoder in jpeg_restart");
#endif /* #ifdef DEBUG */
	global_cinfo=((struct jpg_decoder *)(cimg->decoder))->cinfo;
	global_jerr=((struct jpg_decoder *)(cimg->decoder))->jerr;
	/* These global variables are here so that we don't have to pass lots
	 * of structure pointers into each function. The jpeg decoder is never
	 * running twice at the same time so it doesn't matter.
	 */

	/* If the decoder wants us to skip bytes it's not interested in */
	if (deco->skip_bytes>=length){
		/* If the decoder wants to skip as much as or more bytes than
		 * the chunk that has just arrived */
		deco->skip_bytes-=length;
		return;
	}else{
		/* If the decoder wants to skip less bytes than the chunk
		 * that has just arrived */
		data+=deco->skip_bytes;
		length-=deco->skip_bytes;
		deco->skip_bytes=0;
	}

	/* Add the arrived data chunk into the decoder buffer. Sometimes the
	 * chunks are so small the decoder can't move on on a single chunk
	 * so it has to accumulate more chunks together. This is why the buffer
	 * is there. */
	if ((unsigned)global_cinfo->src->bytes_in_buffer + (unsigned)length > MAXINT) overalloc();
	if ((unsigned)global_cinfo->src->bytes_in_buffer + (unsigned)length < (unsigned)length) overalloc();
	if (deco->jdata){
		/* If there is already some decoder buffer, we have to
		 * allocate more space */
		memmove(deco->jdata,global_cinfo->src->next_input_byte,
			global_cinfo->src->bytes_in_buffer);
		deco->jdata=mem_realloc(
			deco->jdata, global_cinfo->src->bytes_in_buffer+length);
	}else{
		/* If there is no decoder buffer we'll have to allocate
		 * space for a new buffer */
		deco->jdata=mem_alloc(global_cinfo->src->bytes_in_buffer+length);
	}

	/* Copy the data iself into the decoder buffer */
	memcpy(deco->jdata+global_cinfo->src->bytes_in_buffer
		,data,length);

	/* Update the next input byte pointer for the decoder to continue at
	 * the right position */
	global_cinfo->src->next_input_byte=deco->jdata;

	/* ...:::...:..:.:::.:.::::.::.:.:.:.::..::::.::::.:...: */
	/* Update the length of data in the decoder buffer */
	global_cinfo->src->bytes_in_buffer+=length;

	if (setjmp(global_jerr->setjmp_buffer)) goto decoder_ended;
	switch(deco->state){
		case 0:
		/* jpeg_read_header */
	   	if (JPEG_SUSPENDED==jpeg_read_header(global_cinfo,TRUE))
			break;
		global_cinfo->buffered_image=TRUE;
		deco->state=1;

		case 1:
		/* If the scaling is sufficiently brutal we can leave out
		 * some DCT coefficients...: */
		/* jpeg_start_decompress */
		if (jpeg_start_decompress(global_cinfo)==FALSE)
			break;

		cimg->width=global_cinfo->output_width;
		cimg->height=global_cinfo->output_height;

		switch(cimg->buffer_bytes_per_pixel=
			global_cinfo->output_components)
		{
			case 1:
				/* We'll do the conversion ourselves
				 * because libjpeg seems to be buggy */
				cimg->buffer_bytes_per_pixel=3;
				break;


			case 3: /* RGB or YCrCb. We will ask libjpeg to
				 * possibly convert from YCrCb to RGB. */

				global_cinfo->out_color_space=JCS_RGB;
				break;

			case 4:
				/* CMYK or YCCK. We need to enable conversion
				 * to CMYK and then convert CMYK data to RGBA
				 * with dummy A ourselves.
				 * We will ask libjpeg to possibly convert from
				 * YCCK to CMYK. */
				global_cinfo->out_color_space=JCS_CMYK;
				break;

			default:
			/* Let's make a decompression fatal error here */

			if (!mesg_unsup_emitted){
				fprintf(stderr,
			"Unsupported JPEG output components number: %d.\n",
			cimg->buffer_bytes_per_pixel);
				mesg_unsup_emitted=1;
			}
			longjmp(global_jerr->setjmp_buffer,2);

			/* longjmp()  and  siglongjmp() make programs hard to
			 * understand and maintain.  If possible an alternative
			 * should be used. Hahaha :) ;-)
			 */
			/* Free will makes people hard to understand 
			 * and maintain. If possible an alternative should be 
			 * used.
			 */
			/* With our new LongJump(TM) your jumps will be longer
			 * than with ordinary commercially available jumps.
			 */
		}
		cimg->red_gamma=sRGB_gamma;
		cimg->green_gamma=sRGB_gamma;
		cimg->blue_gamma=sRGB_gamma;
		/* This is defined in the JPEG standard somehow that sRGB
		 * color space is used. */

		cimg->strip_optimized=0;
		/* Strip optimization yet waits to be written. This will
		 * allow huge jpegs to be processed without consuming
		 * Links memory and consuming Xserver memory instead ;-)
		 * However strip optimization is already written for PNG's.
		 */

		header_dimensions_known(cimg);
new_scan:
		deco->state=2;

		case 2:
		/* jpeg_start_output */
		if (FALSE==jpeg_start_output(global_cinfo,global_cinfo->input_scan_number)){
susp0:
			/* Suspended */
			break;
		}
		deco->state=3;

		case 3:
		/* jpeg_read_scanlines */
			/* color */
        	while (global_cinfo->output_scanline
			<global_cinfo->output_height){
			int a, lines;

			for (a=0;a<16;a++){
				deco->scanlines[a]=cimg->buffer
				+(global_cinfo
				->output_scanline+a)
				*global_cinfo->output_width*cimg->
					buffer_bytes_per_pixel;
			}
		
         		if ((lines=
				jpeg_read_scanlines(
				global_cinfo,deco->scanlines,1))){
				/* Some lines were written into cimg buffer */
				cimg->rows_added=1;
				
				fix_data(deco, lines);
			}else{
				/* No lines have been written into cimg
				 * buffer */
                	 	/* We are suspended and we want more data */
         	 		goto susp0; /* Break the outer 
					     * switch statement */
			}
		}
		deco->state=4;

		case 4:
		/* jpeg_finish_output */
		if (FALSE==jpeg_finish_output(global_cinfo))
		{
			/* Suspended */
			break;
		}
		if (!jpeg_input_complete(global_cinfo))
		{
			/* Some more scans awaited... */
			goto new_scan;
		}
		deco->state=5;

		case 5:
		/* jpeg_finish_decompress */
		if (FALSE==jpeg_finish_decompress(global_cinfo))
			break;
decoder_ended:
		img_end(cimg);
	}
}