📄 dip.c
字号:
*dest=rb; dest[1]=gb; dest[2]=bb; } } dest+=3; }}/* src is a block of four-bytes RGBA. All bytes are gamma corrected. length is * number of pixels. output is input powered to the given gamma, passed into * dest. src and dest may be identical and it will work. rb, gb, bb are 0-65535 * in linear monitor output photon space. alpha 255 means full image no background. * We assume unsigned short holds at least 16 bits. */void apply_gamma_exponent_and_undercolor_64_to_48_table(unsigned short *dest ,unsigned short *src, int lenght, unsigned short *gamma_table ,unsigned short rb, unsigned short gb, unsigned short bb){ unsigned alpha, calpha; unsigned short ri,gi,bi; for (;lenght;lenght--) { ri=gamma_table[*src]; gi=gamma_table[src[1]+65536]; bi=gamma_table[src[2]+131072]; alpha=src[3]; src+=4; if (((alpha+1)&0xffff)>=2){ calpha=65535-alpha; *dest=(ri*alpha+calpha*rb+32767)/65535; dest[1]=(gi*alpha+calpha*gb+32767)/65535; dest[2]=(bi*alpha+calpha*bb+32767)/65535; }else{ if (alpha){ *dest=ri; dest[1]=gi; dest[2]=bi; }else{ *dest=rb; dest[1]=gb; dest[2]=bb; } } dest+=3; }}/* src is a block of three-bytes. All bytes are gamma corrected. length is * number of triplets. output is input powered to the given gamma, passed into * dest. src and dest may be identical and it will work. * We assume unsigned short holds at least 16 bits. */void apply_gamma_exponent_48_to_48(unsigned short *dest, unsigned short *src, int lenght, float red_gamma ,float green_gamma, float blue_gamma){ float a, inv_65535=1/((float)65535); for (;lenght;lenght--,src+=3,dest+=3) { a=*src; a*=inv_65535; a=pow(a,red_gamma); *dest=(a*65535)+0.5;#if SIZEOF_UNSIGNED_SHORT > 2 if (*dest>=0x10000) *dest=0xffff;#endif /* #if SIZEOF_UNSIGNED_SHORT > 2 */ a=src[1]; a*=inv_65535; a=pow(a,green_gamma); dest[1]=(a*65535)+0.5;#if SIZEOF_UNSIGNED_SHORT > 2 if (dest[1]>=0x10000) dest[1]=0xffff;#endif /* #if SIZEOF_UNSIGNED_SHORT > 2 */ a=src[2]; a*=inv_65535; a=pow(a,blue_gamma); dest[2]=(a*65535)+0.5;#if SIZEOF_UNSIGNED_SHORT > 2 if (dest[2]>=0x10000) dest[2]=0xffff;#endif /* #if SIZEOF_UNSIGNED_SHORT > 2 */ }}/* src is a block of three-bytes. All bytes are gamma corrected. length is * number of triples. output is input powered to the given gamma, passed into * dest. src and dest may be identical and it will work. * We assume unsigned short holds at least 16 bits. */void apply_gamma_exponent_48_to_48_table(unsigned short *dest, unsigned short *src, int lenght, unsigned short *table){ for (;lenght;lenght--,src+=3,dest+=3) { *dest=table[*src]; dest[1]=table[src[1]+65536]; dest[2]=table[src[2]+131072]; }}/* src is a block of three-bytes. All bytes are gamma corrected. length is * number of triples. output is input powered to the given gamma, passed into * dest. src and dest may be identical and it will work. * We assume unsigned short holds at least 16 bits. */void apply_gamma_exponent_24_to_48(unsigned short *dest, unsigned char *src, int lenght, float red_gamma, float green_gamma, float blue_gamma){ float a; float inv_255=1/((float)255); for (;lenght;lenght--,src+=3,dest+=3) { a=*src; a*=inv_255; a=pow(a,red_gamma); *dest=(a*65535)+0.5;#if SIZEOF_UNSIGNED_SHORT > 2 if (*dest>=0x10000) *dest=0xffff;#endif /* #if SIZEOF_UNSIGNED_SHORT > 2 */ a=src[1]; a*=inv_255; a=pow(a,green_gamma); dest[1]=(a*65535)+0.5;#if SIZEOF_UNSIGNED_SHORT > 2 if (dest[1]>=0x10000) dest[1]=0xffff;#endif /* #if SIZEOF_UNSIGNED_SHORT > 2 */ a=src[2]; a*=inv_255; a=pow(a,blue_gamma); dest[2]=(a*65535)+0.5;#if SIZEOF_UNSIGNED_SHORT > 2 if (dest[2]>=0x10000) dest[2]=0xffff;#endif /* #if SIZEOF_UNSIGNED_SHORT > 2 */ }}/* Allocates new gamma_table and fills it with mapping 8 bits -> * power to user_gamma/cimg->*_gamma -> 16 bits * We assume unsigned short holds at least 16 bits. */void make_gamma_table(struct cached_image *cimg){ double rg=user_gamma/cimg->red_gamma; double gg=user_gamma/cimg->green_gamma; double bg=user_gamma/cimg->blue_gamma; double inv; int a; unsigned short *ptr_16; if (cimg->buffer_bytes_per_pixel<=4){ /* 8-bit */ inv=1/((double)255); ptr_16=mem_alloc(768*sizeof(*(cimg->gamma_table))); cimg->gamma_table=ptr_16; for (a=0;a<256;a++,ptr_16++){ *ptr_16=65535*pow(((double)a)*inv,rg)+0.5;#if SIZEOF_UNSIGNED_SHORT > 2 /* To test against crappy arithmetics */ if (*ptr_16>=0x10000) *ptr_16=0xffff;#endif /* #if SIZEOF_UNSIGNED_SHORT > 2 */ } for (a=0;a<256;a++,ptr_16++){ *ptr_16=65535*pow(((double)a)*inv,gg)+0.5;#if SIZEOF_UNSIGNED_SHORT > 2 if (*ptr_16>=0x10000) *ptr_16=0xffff;#endif /* #if SIZEOF_UNSIGNED_SHORT > 2 */ } for (a=0;a<256;a++,ptr_16++){ *ptr_16=65535*pow(((double)a)*inv,bg)+0.5;#if SIZEOF_UNSIGNED_SHORT > 2 if (*ptr_16>=0x10000) *ptr_16=0xffff;#endif /* #if SIZEOF_UNSIGNED_SHORT > 2 */ } }else{ /* 16-bit */ inv=1/((double)65535); ptr_16=mem_alloc(196608*sizeof(*(cimg->gamma_table))); cimg->gamma_table=ptr_16; for (a=0;a<0x10000;a++,ptr_16++){ *ptr_16=65535*pow(((double)a)*inv,rg)+0.5;#if SIZEOF_UNSIGNED_SHORT > 2 if (*ptr_16>=0x10000) *ptr_16=0xffff;#endif /* #if SIZEOF_UNSIGNED_SHORT > 2 */ } for (a=0;a<0x10000;a++,ptr_16++){ *ptr_16=65535*pow(((double)a)*inv,gg)+0.5;#if SIZEOF_UNSIGNED_SHORT > 2 if (*ptr_16>=0x10000) *ptr_16=0xffff;#endif /* #if SIZEOF_UNSIGNED_SHORT > 2 */ } for (a=0;a<0x10000;a++,ptr_16++){ *ptr_16=65535*pow(((double)a)*inv,bg)+0.5;#if SIZEOF_UNSIGNED_SHORT > 2 if (*ptr_16>=0x10000) *ptr_16=0xffff;#endif /* #if SIZEOF_UNSIGNED_SHORT > 2 */ } }}/* We assume unsigned short holds at least 16 bits. */void apply_gamma_exponent_24_to_48_table(unsigned short *dest, unsigned char *src, int lenght, unsigned short *table){ for (;lenght;lenght--,src+=3,dest+=3) { dest[0]=table[src[0]]; dest[1]=table[src[1]+256]; dest[2]=table[src[2]+512]; }}/* Input is 0-255 (8-bit). Output is 0-255 (8-bit)*/unsigned char apply_gamma_single_8_to_8(unsigned char input, float gamma){ return 255*pow(((float) input)/255,gamma)+0.5;}/* Input is 0-255 (8-bit). Output is 0-65535 (16-bit)*//* We assume unsigned short holds at least 16 bits. */unsigned short apply_gamma_single_8_to_16(unsigned char input, float gamma){ float a=input; unsigned short retval; a/=255; a=pow(a,gamma); a*=65535; retval = a+0.5;#if SIZEOF_UNSIGNED_SHORT > 2 if (retval>=0x10000) retval=0xffff;#endif /* #if SIZEOF_UNSIGNED_SHORT > 2 */ return retval;}/* Input is 0-65535 (16-bit). Output is 0-255 (8-bit)*//* We assume unsigned short holds at least 16 bits. */unsigned char apply_gamma_single_16_to_8(unsigned short input, float gamma){ return pow(((float)input)/65535,gamma)*255+0.5;}/* Input is 0-65535 (16-bit). Output is 0-255 (8-bit)*/unsigned short apply_gamma_single_16_to_16(unsigned short input, float gamma){ unsigned short retval; retval = 65535*pow(((float)input)/65535,gamma)+0.5;#if SIZEOF_UNSIGNED_SHORT > 2 if (retval>=0x10000) retval=0xffff;#endif /* #if SIZEOF_UNSIGNED_SHORT > 2 */ return retval;}/* Points to the next unread byte from png data block */extern unsigned char font_data[];extern struct letter letter_data[];extern struct font font_table[];extern int n_fonts; /* Number of fonts. font number 0 is system_font (it's * images are in system_font/ directory) and is used * for special purpose. *//* Returns a pointer to a structure describing the letter found or NULL * if the letter is not found. Tries all possibilities in the style table * before returning NULL. */struct letter *find_stored_letter(int *style_table, int letter_number){ int first, last, half, diff, font_index, font_number; for (font_index=n_fonts-1;font_index;font_index--) { font_number=*style_table++; first=font_table[font_number].begin; last=font_table[font_number].length+first-1; while(first<=last){ half=(first+last)>>1; diff=letter_data[half].code-letter_number; if (diff>=0){ if (diff==0){ return letter_data+half; }else{ /* Value in table is bigger */ last=half-1; } }else{ /* Value in the table is smaller */ first=half+1; } } } /* 0 is system font, 0 is blotch char. This must be present * or we segfault :) */#ifdef REPORT_UNKNOWN fprintf(stderr,"letter 0x%04x not found\n",letter_number);#endif /* #ifdef REPORT_UNKNOWN */ return letter_data+font_table[0].begin;}void read_stored_data(png_structp png_ptr, png_bytep data, png_uint_32 length){ struct read_work *work; work=png_get_io_ptr(png_ptr); if (length>(png_uint_32)work->length) png_error(png_ptr,"Ran out of input data"); memcpy(data,work->pointer,length); work->length-=length; work->pointer+=length;}void my_png_warning(png_structp a, png_const_charp b){}void my_png_error(png_structp a, png_const_charp error_string){ error("Error when loading compiled-in font: %s.",error_string);}/* Loads width and height of the PNG (nothing is scaled). Style table is * already incremented. */inline static void load_metric(int *x, int *y, int char_number, int *style_table){ struct letter *l; l=find_stored_letter(style_table,char_number); if (!l){ *x=0; *y=0; }else{ *x=l->xsize; *y=l->ysize; } return;}/* The data tha fall out of this function express this: 0 is paper. 255 is ink. 34 * is 34/255ink+(255-34)paper. No gamma is involved in this formula, as you can see. * The multiplications and additions take place in photon space. */static void load_char(unsigned char **dest, int *x, int *y, unsigned char *png_data, int png_length, struct style *style){ png_structp png_ptr; png_infop info_ptr; double gamma; int y1,number_of_passes; unsigned char **ptrs; struct read_work work; work.pointer = png_data; work.length = png_length; png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, my_png_error, my_png_warning); info_ptr=png_create_info_struct(png_ptr); png_set_read_fn(png_ptr,&work,(png_rw_ptr)&read_stored_data); png_read_info(png_ptr, info_ptr); *x=png_get_image_width(png_ptr,info_ptr); *y=png_get_image_height(png_ptr,info_ptr); if (png_get_gAMA(png_ptr,info_ptr, &gamma)) png_set_gamma(png_ptr, 1.0, gamma); else png_set_gamma(png_ptr, 1.0, sRGB_gamma); { int bit_depth; int color_type; color_type=png_get_color_type(png_ptr, info_ptr); bit_depth=png_get_bit_depth(png_ptr, info_ptr); if (color_type==PNG_COLOR_TYPE_GRAY){ if (bit_depth<8){ png_set_expand(png_ptr); } if (bit_depth==16){ png_set_strip_16(png_ptr); } } if (color_type==PNG_COLOR_TYPE_PALETTE){ png_set_expand(png_ptr);#ifdef HAVE_PNG_SET_RGB_TO_GRAY png_set_rgb_to_gray(png_ptr,1,54.0*256,183.0*256);#else goto end;#endif } if (color_type & PNG_COLOR_MASK_ALPHA){ png_set_strip_alpha(png_ptr); } if (color_type==PNG_COLOR_TYPE_RGB || color_type==PNG_COLOR_TYPE_RGB_ALPHA){#ifdef HAVE_PNG_SET_RGB_TO_GRAY png_set_rgb_to_gray(png_ptr, 1, 54.0*256, 183.0*256);#else goto end;#endif } } /* If the depth is different from 8 bits/gray, make the libpng expand * it to 8 bit gray. */ number_of_passes=png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr,info_ptr); if (*x && (unsigned)*x * (unsigned)*y / (unsigned)*x != (unsigned)*y) overalloc(); if ((unsigned)*x * (unsigned)*y > MAXINT) overalloc(); *dest=mem_alloc(*x*(*y)); if ((unsigned)*y > MAXINT / sizeof(*ptrs)) overalloc(); ptrs=mem_alloc(*y*sizeof(*ptrs)); for (y1=0;y1<*y;y1++) ptrs[y1]=*dest+*x*y1; for (;number_of_passes;number_of_passes--){ png_read_rows(png_ptr, ptrs, NULL, *y); } png_read_end(png_ptr, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); mem_free(ptrs); return;#ifndef HAVE_PNG_SET_RGB_TO_GRAY end: if (*x && (unsigned)*x * (unsigned)*y / (unsigned)*x != (unsigned)*y) overalloc(); if ((unsigned)*x * (unsigned)*y > MAXINT) overalloc(); *dest=mem_calloc(*x*(*y)); return;#endif}/* Like load_char, but we dictate the y. */static void load_scaled_char(void **dest, int *x, int y,unsigned char *png_data, int png_length, struct style *style){ unsigned char *interm; unsigned char *interm2; unsigned char *i2ptr,*dptr; int ix, iy, y0, x0, c; float conv0, conv1,sharpness,contrast; load_char(&interm, &ix,&iy,png_data, png_length,style); if (style->mono_space>=0) *x=compute_width(style->mono_space, style->mono_height, y); else *x=compute_width(ix,iy,y); if (display_optimize) *x*=3; scale_gray(interm, ix,iy, (unsigned char **)dest, *x, y); if (y>32||y<=0) return ; /* No convolution */ ix=*x+2; /* There is one-pixel border around */ iy=y+2; if (ix && (unsigned)ix * (unsigned)iy / (unsigned)ix != (unsigned)iy) overalloc(); if ((unsigned)ix * (unsigned)iy > MAXINT) overalloc(); interm2=mem_alloc(ix*iy); i2ptr=interm2+ix+1; dptr=*dest; memset(interm2,0,ix); memset(interm2+(iy-1)*ix,0,ix); for (y0=y;y0;y0--){ i2ptr[-1]=0; memcpy(i2ptr,dptr,*x); i2ptr[ix-1]=0; i2ptr+=ix; dptr+=*x; } i2ptr=interm2+ix+1; dptr=*dest; /* Determine the sharpness and contrast */ sharpness=fancy_constants[2*y-2]; contrast=fancy_constants[2*y-1]; /* Compute the matrix constants from contrast and sharpness */ conv0=(1+sharpness)*contrast; conv1=-sharpness*0.25*contrast; for (y0=y;y0;y0--){ for (x0=*x;x0;x0--){ /* Convolution */ c=((*i2ptr)*conv0)+i2ptr[-ix]*conv1+i2ptr[-1]*conv1+i2ptr[1]*conv1+i2ptr[ix]*conv1+0.5; if (((unsigned)c)>=256) c=c<0?0:255; *dptr=c; dptr++; i2ptr++; } i2ptr+=2; } mem_free(interm2);}/* Adds required entry into font_cache and returns pointer to the entry. * We assume the entry is FC_COLOR. */struct font_cache_entry *supply_color_cache_entry (struct graphics_driver*gd, struct style *style, struct letter *letter){ struct font_cache_entry *found, *new; unsigned short *primary_data; int do_free=0; struct font_cache_entry template; unsigned short red, green, blue; unsigned bytes_consumed; template.bitmap.y=style->height; template.type=FC_BW; /* The BW entries will be added only for background images which * are not yet implemented, but will be in the future. */ found=lru_lookup(&font_cache, &template, letter->bw_list); if (!found){ found=mem_alloc(sizeof(*found)); found->bitmap.y=style->height; load_scaled_char(&(found->bitmap.data),&(found->bitmap.x), found->bitmap.y, font_data+letter->begin, letter->length, style); do_free=1; } new=mem_alloc(sizeof(*new)); new->type=FC_COLOR; new->bitmap=found->bitmap; new->r0=style->r0; new->g0=style->g0; new->b0=style->b0; new->r1=style->r1; new->g1=style->g1; new->b1=style->b1; new->mono_space=style->mono_space; new->mono_height=style->mono_height; if (new->bitmap.x && (unsigned)new->bitmap.x * (unsigned)new->bitmap.y / (unsigned)new->bitmap.x != (unsigned)new->bitmap.y) overalloc(); if ((unsigned)new->bitmap.x * (unsigned)new->bitmap.y > MAXINT / 3 / sizeof(*primary_data)) overalloc(); primary_data=mem_alloc(3 *new->bitmap.x*new->bitmap.y*sizeof(*primary_data)); /* We assume the gamma of HTML styles is in sRGB space */ round_color_sRGB_to_48(&red, &green, &blue, ((style->r0)<<16)|((style->g0)<<8)|(style->b0)); mix_two_colors(primary_data, found->bitmap.data, found->bitmap.x*found->bitmap.y, red,green,blue,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -