📄 dip.c
字号:
/* dip.c * Digital Image Processing routines * (c) 2000-2002 Karel 'Clock' Kulhavy * This file is a part of the Links program, released under GPL. * This does various utilities for digital image processing including font * rendering. */#include "cfg.h"#ifdef G#include "links.h"#ifdef HAVE_MATH_H#include <math.h>#endif /* HAVE_MATH_H */#endifint dither_letters=1;double user_gamma=1.0; /* 1.0 for 64 lx. This is the number user directly changes in the menu */ double display_red_gamma=2.2; /* Red gamma exponent of the display */double display_green_gamma=2.2; /* Green gamma exponent of the display */double display_blue_gamma=2.2; /* Blue gamma exponent of the display */#ifdef G/* #define this if you want to report missing letters to stderr. * Leave it commented up for normal operation and releases! *//* #define REPORT_UNKNOWN 1 */double sRGB_gamma=0.45455; /* For HTML, which runs * according to sRGB standard. Number * in HTML tag is linear to photons raised * to this power. */unsigned long aspect=65536; /* aspect=65536 for 320x240 * aspect=157286 for 640x200 (tall pixels) * Defines aspect ratio of screen pixels. * aspect=(196608*xsize+ysize<<1)/(ysize<<1); * Default is 65536 because we assume square pixel * when not specified otherwise. Aspect is ratio of * the pixel height (in milimeters) to pixel width, * multiplied by 65536. */unsigned long aspect_native=65536; /* Like aspect, but not influenced by * user, just determined by graphics driver. *//* Limitation: No input image's dimension may exceed 2^(32-1-8) pixels. *//* Each input byte represents 1 byte (gray). The question whether 0 is * black or 255 is black doesn't matter. *//* These constants represent contrast-enhancement and sharpen filter (which is one filter * together) that is applied onto the letters to enhance their appearance at low height. * They were determined by experiment for several values, interpolated, checked and tuned. * If you change them, don't wonder if the letters start to look strange. * The numers in the comments denote which height the line applies for. */float fancy_constants[64]={ 0,3, /* 1 */ .1,3, /* 2 */ .2,3, /* 3 */ .3,2.9, /* 4 */ .4,2.7, /* 5 */ .4,2.5, /* 6 */ .4,2, /* 7 */ .5,2, /* 8 */ .4,2, /* 9 */ .38,1.9, /* 10 */ .36,1.8, /* 11 */ .33,1.7, /* 12 */ .30,1.6, /* 13 */ .25,1.5, /* 14 */ .20,1.5, /* 15 */ .15,1.5, /* 16 */ .14,1.5, /* 17 */ .13,1.5, /* 18 */ .12,1.5, /* 19 */ .12,1.5, /* 20 */ .12,1.5, /* 21 */ .12,1.5, /* 22 */ .11,1.5, /* 23 */ .10,1.4, /* 24 */ .09,1.3, /* 25 */ .08,1.3, /* 26 */ .04,1.2, /* 27 */ .04,1.2, /* 28 */ .02,1.1, /* 29 */ .02,1.1, /* 30 */ .01,1, /* 31 */ .01,1 /* 32 */};/* prototypes */void decimate_3(unsigned short **, int, int);struct letter *find_stored_letter(int *, int);void read_stored_data(png_structp, png_bytep, png_uint_32);void my_png_warning(png_structp, png_const_charp);void my_png_error(png_structp, png_const_charp);struct font_cache_entry *supply_color_cache_entry (struct graphics_driver *, struct style *, struct letter *);void get_underline_pos(int, int *, int *);int compare_font_entries(void *, void *);void init_font_cache(int);void recode_font_name(unsigned char **);int compare_family(unsigned char *, unsigned char *);int fill_style_table(int *, unsigned char *);/* This shall be hopefully reasonably fast and portable * We assume ix is <65536. If not, the letters will be smaller in * horizontal dimension (because of overflow) but this will not cause * a segfault. 65536 pixels wide bitmaps are not normal and will anyway * exhaust the memory. */static inline int compute_width (int ix, int iy, int required_height){ int width; unsigned long reg; reg=(unsigned long)aspect*(unsigned long)required_height; if (reg>=0x1000000UL){ /* It's big */ reg=(reg+32768)>>16; width=(reg*ix+(iy>>1))/iy; }else{ /* It's small */ reg=(reg+128)>>8; iy<<=8; width=(reg*ix+(iy>>1))/iy; } if (width<1) width=1; return width;}struct lru font_cache; /* This is a cache for screen-ready colored bitmaps * of lettrs and/or alpha channels for these (are the * same size, only one byte per pixel and are used * for letters with an image under them ) *//* Each input byte represents 1 byte (gray). The question whether 0 is * black or 255 is black doesn't matter. */inline static void add_col_gray(unsigned *col_buf, unsigned char *ptr, int line_skip, int n, unsigned weight){ for (;n;n--){ *col_buf+=weight*(*ptr); ptr+=line_skip; col_buf++; }}/* line_skip is in pixels. The column contains the whole pixels (R G B) * We assume unsigned short holds at least 16 bits. */inline static void add_col_color(unsigned *col_buf, unsigned short *ptr , int line_skip, int n, unsigned weight){ for (;n;n--){ *col_buf+=weight*(*ptr); col_buf[1]+=weight*ptr[1]; col_buf[2]+=weight*ptr[2]; ptr+=line_skip; col_buf+=3; }} /* We assume unsigned short holds at least 16 bits. */inline static void add_row_gray(unsigned *row_buf, unsigned char *ptr, int n, unsigned weight){ for (;n;n--){ *row_buf+=weight**ptr; ptr++; row_buf++; }}/* n is in pixels. pixel is 3 unsigned shorts in series */ /* We assume unsigned short holds at least 16 bits. */inline static void add_row_color(unsigned *row_buf, unsigned short *ptr, int n, unsigned weight){ for (;n;n--){ *row_buf+=weight**ptr; row_buf[1]+=weight*ptr[1]; row_buf[2]+=weight*ptr[2]; ptr+=3; row_buf+=3; }}/* We assume unsigned holds at least 32 bits */inline static void emit_and_bias_col_gray(unsigned *col_buf, unsigned char *out, int line_skip, int n, unsigned weight){ unsigned half=weight>>1; for (;n;n--){ *out=*col_buf/weight; out+=line_skip; *col_buf++=half; }}/* We assume unsigned holds at least 32 bits */static inline void bias_buf_gray(unsigned *col_buf, int n, unsigned half){ for (;n;n--) *col_buf++=half;}/* We assume unsigned holds at least 32 bits */inline static void bias_buf_color(unsigned *col_buf, int n, unsigned half){ for (;n;n--){ *col_buf=half; col_buf[1]=half; col_buf[2]=half; col_buf+=3; } /* System activated */} /* line skip is in pixels. Pixel is 3*unsigned short *//* We assume unsigned holds at least 32 bits *//* We assume unsigned short holds at least 16 bits. */inline static void emit_and_bias_col_color(unsigned *col_buf , unsigned short *out, int line_skip, int n, unsigned weight){ unsigned half=weight>>1; for (;n;n--){ *out=(*col_buf)/weight; *col_buf=half; out[1]=col_buf[1]/weight; col_buf[1]=half; /* The following line is an enemy of the State and will be * prosecuted according to the Constitution of The United States * Cap. 20/3 ix. Sel. Bill 12/1920 * Moses 12/20 Erizea farizea 2:2:1:14 */ out[2]=col_buf[2]/weight; col_buf[2]=half; out+=line_skip; col_buf+=3; }} /* We assume unsigned holds at least 32 bits */inline static void emit_and_bias_row_gray(unsigned *row_buf, unsigned char *out, int n ,unsigned weight){ unsigned half=weight>>1; for (;n;n--){ *out++=*row_buf/weight; *row_buf++=half; }}/* n is in pixels. pixel is 3 unsigned shorts in series. *//* We assume unsigned holds at least 32 bits *//* We assume unsigned short holds at least 16 bits. */inline static void emit_and_bias_row_color(unsigned *row_buf, unsigned short *out, int n, unsigned weight){ unsigned half=weight>>1; for (;n;n--){ *out=*row_buf/weight; *row_buf=half; out[1]=row_buf[1]/weight; row_buf[1]=half; out[2]=row_buf[2]/weight; row_buf[2]=half; out+=3; row_buf+=3; }} /* For enlargement only -- does linear filtering. * Allocates output and frees input. * We assume unsigned holds at least 32 bits */inline static void enlarge_gray_horizontal(unsigned char *in, int ix, int y ,unsigned char ** out, int ox){ unsigned *col_buf; int total; int out_pos,in_pos,in_begin,in_end; unsigned half=(ox-1)>>1; unsigned char *outptr; unsigned char *inptr; if (ox && (unsigned)ox * (unsigned)y / (unsigned)ox != (unsigned)y) overalloc(); if ((unsigned)ox * (unsigned)y > MAXINT) overalloc(); outptr=mem_alloc(ox*y); inptr=in; *out=outptr; if (ix==1){ /* Dull copying */ for (;y;y--){ memset(outptr,*inptr,ox); outptr+=ox; inptr++; } mem_free(in); }else{ total=(ix-1)*(ox-1); if ((unsigned)y > MAXINT / sizeof(*col_buf)) overalloc(); col_buf=mem_alloc(y*sizeof(*col_buf)); bias_buf_gray(col_buf, y, half); out_pos=0; in_pos=0; again: in_begin=in_pos; in_end=in_pos+ox-1; add_col_gray(col_buf,inptr, ix, y, in_end-out_pos); add_col_gray(col_buf,inptr+1, ix, y, out_pos-in_begin); emit_and_bias_col_gray(col_buf,outptr,ox,y,ox-1); outptr++; out_pos+=ix-1; if (out_pos>in_end){ in_pos=in_end; inptr++; } if (out_pos>total){ mem_free(in); mem_free(col_buf); return; } goto again; } /* Rohan, oh Rohan... */ /* ztracena zeme :) */}/* For enlargement only -- does linear filtering * Frees input and allocates output. * We assume unsigned holds at least 32 bits */static inline void enlarge_color_horizontal(unsigned short *ina, int ix, int y, unsigned short ** outa, int ox){ unsigned *col_buf; int total,a,out_pos,in_pos,in_begin,in_end; unsigned half=(ox-1)>>1; unsigned skip=3*ix; unsigned oskip=3*ox; unsigned short *out, *in; if (ix==ox){ *outa=ina; return; } if (ox && (unsigned)ox * (unsigned)y / (unsigned)ox != (unsigned)y) overalloc(); if ((unsigned)ox * (unsigned)y > MAXINT / 3 / sizeof(*out)) overalloc(); out=mem_alloc(sizeof(*out)*3*ox*y); *outa=out; in=ina; if (ix==1){ for (;y;y--,in+=3) for (a=ox;a;a--,out+=3){ *out=*in; out[1]=in[1]; out[2]=in[2]; } mem_free(ina); return; } total=(ix-1)*(ox-1); if ((unsigned)y > MAXINT / 3 / sizeof(*col_buf)) overalloc(); col_buf=mem_alloc(y*3*sizeof(*col_buf)); bias_buf_color(col_buf,y,half); out_pos=0; in_pos=0; again: in_begin=in_pos; in_end=in_pos+ox-1; add_col_color(col_buf,in,skip,y ,in_end-out_pos); add_col_color(col_buf,in+3,skip,y ,out_pos-in_begin); emit_and_bias_col_color(col_buf,out,oskip,y,ox-1); out+=3; out_pos+=ix-1; if (out_pos>in_end){ in_pos=in_end; in+=3; } if (out_pos>total){ mem_free(col_buf); mem_free(ina); return; } goto again;}/* Works for both enlarging and diminishing. Linear resample, no low pass. * Automatically mem_frees the "in" and allocates "out". *//* We assume unsigned holds at least 32 bits */inline static void scale_gray_horizontal(unsigned char *in, int ix, int y ,unsigned char ** out, int ox){ unsigned *col_buf; int total=ix*ox; int out_pos,in_pos,in_begin,in_end,out_end; unsigned char *outptr; unsigned char *inptr; if (ix<ox){ enlarge_gray_horizontal(in,ix,y,out,ox); return; }else if (ix==ox){ *out=in; return; } if (ox && (unsigned)ox * (unsigned)y / (unsigned)ox != (unsigned)y) overalloc(); if ((unsigned)ox * (unsigned)y > MAXINT) overalloc(); outptr=mem_alloc(ox*y); inptr=in; *out=outptr; if ((unsigned)y > MAXINT / sizeof(*col_buf)) overalloc(); col_buf=mem_alloc(y*sizeof(*col_buf)); bias_buf_gray(col_buf, y, ix>>1); out_pos=0; in_pos=0; again: in_begin=in_pos; in_end=in_pos+ox; out_end=out_pos+ix; if (in_begin<out_pos)in_begin=out_pos; if (in_end>out_end)in_end=out_end; add_col_gray(col_buf,inptr,ix,y,in_end-in_begin); in_end=in_pos+ox; if (out_end>=in_end){ in_pos=in_end; inptr++; } if (out_end<=in_end){ emit_and_bias_col_gray(col_buf,outptr,ox,y,ix); out_pos=out_pos+ix; outptr++; } if (out_pos==total) { mem_free(in); mem_free(col_buf); return; } goto again;}/* Works for both enlarging and diminishing. Linear resample, no low pass. * Does only one color component. * Frees ina and allocates outa. * If ox*3<=ix, and display_optimize, performs optimization for LCD. */inline static void scale_color_horizontal(unsigned short *ina, int ix, int y, unsigned short **outa, int ox){ unsigned *col_buf; int total=ix*ox; int out_pos,in_pos,in_begin,in_end,out_end; unsigned skip=3*ix; unsigned oskip=3*ox; unsigned short *in, *out; if (ix==ox){ *outa=ina; return; } if (ix<ox){ enlarge_color_horizontal(ina,ix,y,outa,ox); return; }else if (ix==ox){ *outa=ina; return; } if (ox && (unsigned)ox * (unsigned)y / (unsigned)ox != (unsigned)y) overalloc(); if ((unsigned)ox * (unsigned)y > MAXINT / 3 / sizeof(*out)) overalloc(); out=mem_alloc(sizeof(*out)*3*ox*y); *outa=out; in=ina; if ((unsigned)y > MAXINT / 3 / sizeof(*col_buf)) overalloc(); col_buf=mem_alloc(y*3*sizeof(*col_buf)); bias_buf_color(col_buf,y,ix>>1); out_pos=0; in_pos=0; again: in_begin=in_pos; in_end=in_pos+ox; out_end=out_pos+ix; if (in_begin<out_pos)in_begin=out_pos; if (in_end>out_end)in_end=out_end; add_col_color(col_buf,in,skip,y,in_end-in_begin); in_end=in_pos+ox; if (out_end>=in_end){ in_pos=in_end; in+=3; } if (out_end<=in_end){ emit_and_bias_col_color(col_buf,out,oskip,y,ix); out_pos=out_pos+ix; out+=3; } if (out_pos==total) { mem_free(ina); mem_free(col_buf); return; } goto again;}/* For magnification only. Does linear filtering. *//* We assume unsigned holds at least 32 bits */inline static void enlarge_gray_vertical(unsigned char *in, int x, int iy, unsigned char ** out ,int oy){ unsigned *row_buf; int total; int out_pos,in_pos,in_begin,in_end; int half=(oy-1)>>1; unsigned char *outptr; unsigned char *inptr; if (iy==1){ if (x && (unsigned)x * (unsigned)oy / (unsigned)x != (unsigned)oy) overalloc(); if ((unsigned)x * (unsigned)oy > MAXINT) overalloc(); outptr=mem_alloc(oy*x); *out=outptr; for(;oy;oy--,outptr+=x) memcpy(outptr,in,x); mem_free(in); } else if (iy==oy){ *out=in;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -