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; } }
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); } }