Hi everyone,<div><br></div><div>I'm using cairo and pixman to composite images.</div><div>I tested image scaling performance with bilinear filtering.</div><div>But it's a little bit slower than I expected.</div><div>
<br></div><div>Test was performed with cairo 1.8.8 & pixman 0.21.2 on ubuntu 10.04 with intel quad core CPU @2.66GHz.</div><div>I used cairo image surface for both source and destination.</div><div><br></div><div><br>
</div><div>Test codes are something like this...</div><div><br></div><div>#define SCALE_X 2.0</div><div>#define SCALE_Y 2.0</div><div><br></div><div><div>cairo_scale(cr, SCALE_X, SCALE_Y);</div><div>cairo_set_source_surface(cr, srcSurface, 0, 0);</div>
<div>cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BILINEAR);</div><div>cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);</div><div><br></div><div>startTime = rdtsc();</div><div>cairo_paint(ctx);</div><div>endTime = rdtsc();</div>
</div><div><br></div><div><br></div><div>What I understand about image scaling procedure is as follows</div><div><br></div><div>1. Allocate(or acquire statically allocated buffer) horizontal source scanline buffer to store interpolated pixels.</div>
<div>2. Fetch a scanline from source image to source scanline buffer with bilinear interpolation.</div><div>3. Composite source scanline and destination scanline with operator SRC.</div><div>4. Go to next scanline.</div><div>
5. Free(or release) source scanline buffer.</div><div><br></div><div><br></div><div>My optimization point is</div><div><br></div><div>1. It seems possible to avoid fetching by directly combining bilinear interpolated result with destination.</div>
<div>2. Bilinear interpolation can be optimized using double-blend trick with a little bit of precision loss.</div><div><br></div><div>Optimization 1 can reduce one memory write and one memory read operation.</div><div>I think it will not affect the performance significantly.</div>
<div>However, it can be helpful on some machines with limited cache.</div><div><br></div><div>Optimization 2 is more critical for image scaling with bilinear filtering.</div><div>I wrote some codes for bilinear_interpolation@pixman-bits-image.c</div>
<div><br></div><div>// Optimization 2</div><div><div>static force_inline uint32_t bilinear_interpolation (uint32_t tl, uint32_t tr, uint32_t bl, uint32_t br, int distx, int disty)</div></div><div>{</div><div><div> <meta http-equiv="content-type" content="text/html; charset=utf-8">int distxy, distxiy, distixy, distixiy;</div>
<meta http-equiv="content-type" content="text/html; charset=utf-8"><div> uint32_t rb, ga;</div><div><br></div><meta http-equiv="content-type" content="text/html; charset=utf-8"><div> distxy = distx * disty;</div><meta http-equiv="content-type" content="text/html; charset=utf-8"><div>
distxiy = (disty << 8) - <meta http-equiv="content-type" content="text/html; charset=utf-8">distxy;</div><meta http-equiv="content-type" content="text/html; charset=utf-8"><div> distixy = (distx << 8) - <meta http-equiv="content-type" content="text/html; charset=utf-8">distxy;</div>
<meta http-equiv="content-type" content="text/html; charset=utf-8"><div> distixiy = 256*256 - (disty << 8) - (distx << 8) + <meta http-equiv="content-type" content="text/html; charset=utf-8">distxy;</div><div>
<br></div><meta http-equiv="content-type" content="text/html; charset=utf-8"><div> <meta http-equiv="content-type" content="text/html; charset=utf-8">distxy = <meta http-equiv="content-type" content="text/html; charset=utf-8">distxy >> 8;</div>
<meta http-equiv="content-type" content="text/html; charset=utf-8"><div> <meta http-equiv="content-type" content="text/html; charset=utf-8">distxiy = <meta http-equiv="content-type" content="text/html; charset=utf-8">distxiy >> 8;</div>
<meta http-equiv="content-type" content="text/html; charset=utf-8"><div> <meta http-equiv="content-type" content="text/html; charset=utf-8">distixy = <meta http-equiv="content-type" content="text/html; charset=utf-8">distixy >> 8;</div>
<meta http-equiv="content-type" content="text/html; charset=utf-8"><div> <meta http-equiv="content-type" content="text/html; charset=utf-8">distixiy = <meta http-equiv="content-type" content="text/html; charset=utf-8">distixiy >> 8;</div>
<div><br></div><div> /* Red and Blue */</div><meta http-equiv="content-type" content="text/html; charset=utf-8"><div> rb = (0x00FF00FF & tl)*<meta http-equiv="content-type" content="text/html; charset=utf-8">distixiy + (0x00FF00FF & tr)*<meta http-equiv="content-type" content="text/html; charset=utf-8">distixy + (0x00FF00FF & bl)*<meta http-equiv="content-type" content="text/html; charset=utf-8">distxiy + (0x00FF00FF & br)*<meta http-equiv="content-type" content="text/html; charset=utf-8">distxy;</div>
<meta http-equiv="content-type" content="text/html; charset=utf-8"><div> rb = (rb >> 8) & 0x00FF00FF;</div><div><br></div><div> /* Green and Alpha */</div><meta http-equiv="content-type" content="text/html; charset=utf-8"><div>
ga = (0x00FF00FF & (tl >> 8))*<meta http-equiv="content-type" content="text/html; charset=utf-8">distixiy + (0x00FF00FF & (tr >> 8))*<meta http-equiv="content-type" content="text/html; charset=utf-8">distixy + (0x00FF00FF & (bl >> 8))*<meta http-equiv="content-type" content="text/html; charset=utf-8">distxiy + (0x00FF00FF & (br >> 8))*<meta http-equiv="content-type" content="text/html; charset=utf-8">distxy;</div>
<meta http-equiv="content-type" content="text/html; charset=utf-8"><div> ga = ga & 0xFF00FF00;</div><div><br></div><meta http-equiv="content-type" content="text/html; charset=utf-8"><div> return rb | ga;</div></div>
<div>}</div><div><br></div><div>Optimization 2 increased the performance by more than twice.</div><div>But it does not always produce the same result as the original code, which is also an approximation of bilinear interpolation.</div>
<div>So it can cause pixel correctness issues on some test cases.</div><div>I've done some numerical analysis and it appears that at most you would have a difference of 1 for each RGBA value as the original code. </div>
<div><br></div><div>Let me know if you need for information / explanation. </div><div><br></div><div>It's my great pleasure if this can be useful for your project.</div><div>Thank you.</div>