📄 gbench.c
字号:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
/*
* gbench is a small program used to benchmark a new algorithm
* performing gamma-corrected alpha-blending.
*
* EXPERIMENTAL: the numbers given here do not correspond to
* typical usage patterns yet, and the algorithm
* can still be tuned
*
*/
#ifdef UNIX
#include <sys/time.h>
#endif
#include "gbench.h"
#define xxCACHE
static int use_gamma = 0;
static unsigned char gamma_ramp[256];
static unsigned char gamma_ramp_inv[256];
#define ALGO_KEY_COUNT 256
#define ALGO_GRADE_BITS 5
#define ALGO_GRADE_COUNT (1 << ALGO_GRADE_BITS)
#define ALGO_GRADE_INDEX(x) ((x) >> (8-ALGO_GRADE_BITS))
typedef struct CKeyRec_
{
int background;
int foreground;
unsigned char* grades;
} CKeyRec, *CKey;
static CKeyRec ckeys [ ALGO_KEY_COUNT ];
static unsigned char cgrades[ ALGO_KEY_COUNT * ALGO_GRADE_COUNT * 3 ];
static chits = 0;
static cmiss1 = 0;
static cmiss2 = 0;
/* clear the cache
*/
static void
cclear( void )
{
int nn;
for ( nn = 0; nn < ALGO_KEY_COUNT; nn++ )
ckeys[nn].grades = NULL;
}
/* recompute the grade levels of a given key
*/
static void
ckey_reset( CKey key )
{
int back = key->background;
int fore = key->foreground;
unsigned char* gr = key->grades;
int nn;
int r1,g1,b1,r2,g2,b2;
r1 = (unsigned char)( back >> 16 );
g1 = (unsigned char)( back >> 8 );
b1 = (unsigned char)( back );
r2 = (unsigned char)( fore >> 16 );
g2 = (unsigned char)( fore >> 8 );
b2 = (unsigned char)( fore );
gr[0] = r1;
gr[1] = g1;
gr[2] = b1;
gr[3] = r2;
gr[4] = g2;
gr[5] = b2;
gr += 6;
if ( use_gamma )
{
r1 = gamma_ramp_inv[r1];
g1 = gamma_ramp_inv[g1];
b1 = gamma_ramp_inv[b1];
r2 = gamma_ramp_inv[r2];
g2 = gamma_ramp_inv[g2];
b2 = gamma_ramp_inv[b2];
}
for ( nn = 1; nn < ALGO_GRADE_COUNT-1; nn++ )
{
int r = r1 + ((r2-r1)*nn)/(ALGO_GRADE_COUNT-1);
int g = g1 + ((g2-g1)*nn)/(ALGO_GRADE_COUNT-1);
int b = b1 + ((b2-b1)*nn)/(ALGO_GRADE_COUNT-1);
if ( use_gamma )
{
r = gamma_ramp[r];
g = gamma_ramp[g];
b = gamma_ramp[b];
}
gr[0] = (unsigned char)r;
gr[1] = (unsigned char)g;
gr[2] = (unsigned char)b;
gr += 3;
}
cmiss2 ++;
}
/* lookup the grades of a given (background,foreground) couple
*/
static const unsigned char*
clookup( int background,
int foreground )
{
int index, index0;
CKey key;
cmiss1++;
index0 = ( background + foreground*7 ) % ALGO_KEY_COUNT;
index = index0;
do
{
key = ckeys + index;
if ( key->grades == NULL )
goto NewNode;
if ( key->background == background &&
key->foreground == foreground )
goto Exit;
index = (index+1) % ALGO_KEY_COUNT;
}
while ( index != index0 );
/* the cache is full, clear it completely
*/
cclear();
NewNode:
key->background = background;
key->foreground = foreground;
key->grades = cgrades + index0*(3*ALGO_GRADE_COUNT);
ckey_reset( key );
Exit:
return (const unsigned char*)key->grades;
}
void
ggamma_set( double gamma )
{
int ii;
double gamma_inv = 1.0f / gamma;
cclear();
for ( ii = 0; ii < 256; ii++ )
gamma_ramp[ii] = (unsigned char)( pow( (double)ii/255.0f, gamma )*255 );
for ( ii = 0; ii < 256; ii++ )
gamma_ramp_inv[ii] = (unsigned char)( pow( (double)ii/255.0f, gamma_inv ) * 255.0f );
use_gamma = (gamma != 1.0f);
}
static void
gblitter_blitrgb24_gray_direct( GBlitter blitter,
int color )
{
unsigned char r = (unsigned char)(color >> 16);
unsigned char g = (unsigned char)(color >> 8);
unsigned char b = (unsigned char)(color);
int h = blitter->height;
unsigned char* src_line = blitter->src_line;
unsigned char* dst_line = blitter->dst_line;
if ( use_gamma )
{
int r1 = gamma_ramp_inv[r];
int g1 = gamma_ramp_inv[g];
int b1 = gamma_ramp_inv[b];
do
{
unsigned char* src = src_line + (blitter->src_x);
unsigned char* dst = dst_line + (blitter->dst_x*3);
int w = blitter->width;
do
{
int a = src[0];
if ( a < 2 )
{
/* nothing */
}
else if ( a >= 254 )
{
dst[0] = r;
dst[1] = g;
dst[2] = b;
}
else
{
int r0 = dst[0];
int g0 = dst[1];
int b0 = dst[2];
r0 = gamma_ramp_inv[r0];
g0 = gamma_ramp_inv[g0];
b0 = gamma_ramp_inv[b0];
a = a + (a >> 7);
r0 += (r1 - r0)*a/256;
g0 += (g1 - g0)*a/256;
b0 += (b1 - b0)*a/256;
r0 = gamma_ramp[r0];
g0 = gamma_ramp[g0];
b0 = gamma_ramp[b0];
dst[0] = (unsigned char)r0;
dst[1] = (unsigned char)g0;
dst[2] = (unsigned char)b0;
}
src += 1;
dst += 3;
}
while (--w > 0);
src_line += blitter->src_incr;
dst_line += blitter->dst_incr;
}
while (--h > 0);
return;
}
do
{
unsigned char* src = src_line + (blitter->src_x);
unsigned char* dst = dst_line + (blitter->dst_x*3);
int w = blitter->width;
do
{
int a = src[0];
if ( a < 2 )
{
/* nothing */
}
else if ( a >= 254 )
{
dst[0] = r;
dst[1] = g;
dst[2] = b;
}
else
{
int r0 = dst[0];
int g0 = dst[1];
int b0 = dst[2];
a = a + (a >> 7);
r0 += (r - r0)*a/256;
g0 += (g - g0)*a/256;
b0 += (b - b0)*a/256;
dst[0] = (unsigned char)r0;
dst[1] = (unsigned char)g0;
dst[2] = (unsigned char)b0;
}
src += 1;
dst += 3;
}
while (--w > 0);
src_line += blitter->src_incr;
dst_line += blitter->dst_incr;
}
while (--h > 0);
}
static void
gblitter_blitrgb24_gray_cache( GBlitter blitter,
int color )
{
unsigned char r = (unsigned char)(color >> 16);
unsigned char g = (unsigned char)(color >> 8);
unsigned char b = (unsigned char)(color);
int back = -1;
const unsigned char* grades = NULL;
int h = blitter->height;
unsigned char* src_line = blitter->src_line;
unsigned char* dst_line = blitter->dst_line;
do
{
unsigned char* src = src_line + (blitter->src_x);
unsigned char* dst = dst_line + (blitter->dst_x*3);
int w = blitter->width;
do
{
int a = src[0];
if ( a < 2 )
{
/* nothing */
}
else if ( a >= 254 )
{
dst[0] = r;
dst[1] = g;
dst[2] = b;
}
else
{
int back0 = ((int)dst[0] << 16) | ((int)dst[1] << 8) | dst[2];
const unsigned char* g;
if ( back0 != back )
{
grades = clookup( back0, color );
back = back0;
}
else
chits++;
g = grades + ALGO_GRADE_INDEX(a)*3;
dst[0] = g[0];
dst[1] = g[1];
dst[2] = g[2];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -