📄 img.c
字号:
#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 + -