⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 details

📁 linux下电话本所依赖的一些图形库
💻
字号:
General ideas of Pixops======================= - Gain speed by special-casing the common case, and using   generic code to handle the uncommon case. - Most of the time in scaling an image is in the center;   however code that can handle edges properly is slow   because it needs to deal with the possibility of running   off the edge. So make the fast case code only handle   the centers, and use generic, slow, code for the edges,Structure of Pixops===================The code of pixops can roughly be grouped into four parts: - Filter computation functions - Functions for scaling or compositing lines and pixels   using precomputed filters - pixops process, the central driver that iterates through   the image calling pixel or line functions as necessary    - Wrapper functions (pixops_scale/composite/composite_color)   that compute the filter, chooses the line and pixel functions   and then call pixops_processs with the filter, line,   and pixel functions.pixops process is a pretty scary looking function:static voidpixops_process (guchar         *dest_buf,		int             render_x0,		int             render_y0,		int             render_x1,		int             render_y1,		int             dest_rowstride,		int             dest_channels,		gboolean        dest_has_alpha,		const guchar   *src_buf,		int             src_width,		int             src_height,		int             src_rowstride,		int             src_channels,		gboolean        src_has_alpha,		double          scale_x,		double          scale_y,		int             check_x,		int             check_y,		int             check_size,		guint32         color1,		guint32         color2,		PixopsFilter   *filter,		PixopsLineFunc  line_func,		PixopsPixelFunc pixel_func)(Some of the arguments should be moved into structures. It's basically"all the arguments to pixops_composite_color plus three more") Thearguments can be divided up into:Information about the destination buffer   guchar *dest_buf, int dest_rowstride, int dest_channels, gboolean dest_has_alpha,Information about the source buffer   guchar *src_buf,  int src_rowstride,  int src_channels,  gboolean src_has_alpha,   int src_width, int src_height,Information on how to scale the source buf and the region of the scaled sourceto render onto the destination buffer   int render_x0, int render_y0, int render_x1, int render_y1   double scale_x, double scale_yInformation about a constant color or check pattern onto which to to composite   int check_x,	int check_y, int check_size, guint32 color1, guint32 color2Information precomputed to use during the scale operation   PixopsFilter *filter, PixopsLineFunc line_func, OixopsPixelFunc pixel_funcFilter computation==================The PixopsFilter structure looks like:struct _PixopsFilter{  int *weights;  int n_x;  int n_y;  double x_offset;  double y_offset;}; 'weights' is an array of size: weights[SUBSAMPLE][SUBSAMPLE][n_x][n_y]SUBSAMPLE is a constant - currently 16 in pixops.c.In order to compute a scaled destination pixel we convolvean array of n_x by n_y source pixels with one ofthe SUBSAMPLE * SUBSAMPLE filter matrices storedin weights. The choice of filter matrix is determinedby the fractional part of the source location.To compute dest[i,j] we do the following: x = i * scale_x + x_offset; y = i * scale_x + y_offset; x_int = floor(x) y_int = floor(y) C = weights[SUBSAMPLE*(x - x_int)][SUBSAMPLE*(y - y_int)] total  = sum[l=0..n_x-1, j=0..n_y-1] (C[l,m] * src[x_int + l, x_int + m])The filter weights are integers scaled so that the total of theweights in the weights array is equal to 65536.When the source does not have alpha, we simply compute each channelas above, so total is in the range [0,255*65536] dest = src / 65536When the source does have alpha, then we need to compute using"pre-multiplied alpha": a_total = sum (C[l,m] * src_a[x_int + l, x_int + m]) c_total = sum (C[l,m] * src_a[x_int + l, x_int + m] * src_c[x_int + l, x_int + m]) This gives us a result for c_total in the range of [0,255*a_total]  c_dest = c_total / a_total Mathematical aside:The process of producing a destination filter consistsof: - Producing a continuous approximation to the source   image via interpolation.  - Sampling that continuous approximation with filter.This is representable as: S(x,y) = sum[i=-inf,inf; j=-inf,inf] A(frac(x),frac(y))[i,j] * S[floor(x)+i,floor(y)+j] D[i,j] = Integral(s=-inf,inf; t=-inf,inf) B(i+x,j+y) S((i+x)/scale_x,(i+y)/scale_y) By reordering the sums and integrals, you get something of the form: D[i,j] = sum[l=-inf,inf; m=-inf;inf] C[l,m] S[i+l,j+l]The arrays in weights are the C[l,m] above, and are thusdetermined by the interpolating algorithm in use and thesampling filter:                                       INTERPOLATE       SAMPLE ART_FILTER_NEAREST                nearest neighbour     point ART_FILTER_TILES                  nearest neighbour      box ART_FILTER_BILINEAR (scale < 1)   nearest neighbour      box   (scale < 1) ART_FILTER_BILINEAR (scale > 1)       bilinear           point  (scale > 1) ART_FILTER_HYPER                      bilinear           box Pixel Functions===============typedef void (*PixopsPixelFunc) (guchar *dest, int dest_x, int dest_channels, int dest_has_alpha,				 int src_has_alpha,                                  int check_size, guint32 color1, guint32 color2,				 int r, int g, int b, int a);The arguments here are: dest: location to store the output pixel dest_x: x coordinate of destination (for handling checks) dest_has_alpha, dest_channels: Information about the destination pixbuf src_has_alpha: Information about the source pixbuf check_size, color1, color2: Information for color background for composite_color variant  r,g,b,a - scaled red, green, blue and alphar,g,b are premultiplied alpha. a is in [0,65536*255] r is in [0,255*a] g is in [0,255*a] b is in [0,255*a]If src_has_alpha is false, then a will be 65536*255, allowing optimization.Line functions==============typedef guchar *(*PixopsLineFunc) (int *weights, int n_x, int n_y,				   guchar *dest, int dest_x, guchar *dest_end, int dest_channels, int dest_has_alpha,				   guchar **src, int src_channels, gboolean src_has_alpha,				   int x_init, int x_step, int src_width,				   int check_size, guint32 color1, guint32 color2);The argumets are: weights, n_x, n_y   Filter weights for this row - dimensions weights[SUBSAMPLE][n_x][n_y] dest, dest_x, dest_end, dest_channels, dest_has_alpha   The destination buffer, function will start writing into *dest and   increment by dest_channels, until dest == dest_end. Reading from   src for these pixels is guaranteed not to go outside of the    bufer bounds src, src_channels, src_has_alpha    src[n_y] - an array of pointers to the start of the source rows   for each filter coordinate. x_init, x_step   Information about x positions in source image. src_width - unused check_size, color1, color2: Information for color background for composite_color variant The total for the destination pixel at dest + i is given by   SUM (l=0..n_x - 1, m=0..n_y - 1)      src[m][(x_init + i * x_step)>> SCALE_SHIFT + l] * weights[m][l]Algorithms for compositing==========================Compositing alpha on non alpha: R = As * Rs + (1 - As) * Rd G = As * Gs + (1 - As) * Gd B = As * Bs + (1 - As) * BdThis can be regrouped as: Cd + Cs * (Cs - Rd)Compositing alpha on alpha: A = As + (1 - As) * Ad R = (As * Rs + (1 - As) * Rd * Ad)  / A G = (As * Gs + (1 - As) * Gd * Ad)  / A B = (As * Bs + (1 - As) * Bd * Ad)  / AThe way to think of this is in terms of the "area":The final pixel is composed of area As of the source pixeland (1 - As) * Ad of the target pixel. So the final pixelis a weighted average with those weights.Note that the weights do not add up to one - hence thenon-constant division.Integer tricks for compositing==============================MMX Code========Line functions are provided in MMX functionsfor a few special cases: n_x = n_y = 2   src_channels = 3 dest_channels = 3    op = scale   src_channels = 4 with alpha dest_channels = 4 no alpha  op = composite   src_channels = 4 with alpha dest_channels = 4 no alpha  op = composite_colorFor the case n_x = n_y = 2 - primarily hit when scaling up with bilinearscaling, we can take advantage of the fact that multiple destinationpixels will be composed from the same source pixels.That is a destination pixel is a linear combination of the sourcepixels around it:  S0                     S1       D  D' D'' ...  S2                     S3Each mmx register is 64 bits wide, so we can unpack a source pixelinto the low 8 bits of 4 16 bit words, and store it into a mmx register.For each destination pixel, we first make sure that we have pixels S0... S3 loaded into registers mm0 ...mm3. (This will often involve notdoing anything or moving mm1 and mm3 into mm0 and mm1 then reloadingmm1 and mm3 with new values).Then we load up the appropriate weights for the 4 corner pixelsbased on the offsets of the destination pixel within the sourcepixels.We have preexpanded the weights to 64 bits wide and truncated therange to 8 bits, so an original filter value of  0x5321 would be expanded to 0x0053005300530053For source buffers without alpha, we simply do a multiply-addof the weights, giving us a 16 bit quantity for the resultthat we shift left by 8 and store in the destination buffer.When the source buffer has alpha, then things become morecomplicated - when we load up mm0 and mm3, we premultiplythe alpha, so they contain: (a*ff >> 8) (r*a >> 8) (g*a >> 8) (b*a >> a)Then when we multiply by the weights, and add we end upwith premultiplied r,g,b,a in the range of 0 .. 0xff * 0ff,call them A,R,G,BWe then need to composite with the dest pixels - which we do by: r_dest = (R + ((0xff * 0xff - A) >> 8) * r_dest) >> 8(0xff * 0xff) 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -