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

📄 drawutil.c

📁 傅立叶变换和小波变换是图像压缩的重要工具。该代大戏是利用小波变换进行图像压缩。
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "DrawUtil.h"
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

void MakeHueRGBTable(void);
static void MakeNoise1d(void);
static void MakeNoise2d(void);
static void MakeNoise3d(void);

//-------------------------------------------------------

static ulong lastRandomNumber = 0xA2A9; // that's a prime

void DrawUtil_Randomize( void )
{
ulong cnt;
	cnt = clock();
	cnt &= 0xFF;
	while(cnt--)
	{
		lastRandomNumber = lastRandomNumber*65539+3;
		lastRandomNumber = lastRandomNumber*1009 +7;
	}
}

ulong REGCALL DrawUtil_Rand( ulong max )
{
ulong a;

	lastRandomNumber = a = lastRandomNumber*65539+3;

return (a>>16)%max;
}

//-------------------------------------------------------

float DrawUtil_SinTable[TABLE_SIZE];
float DrawUtil_CosTable[TABLE_SIZE];

ubyte DrawUtil_ByteSinTable[256];
ubyte DrawUtil_ByteCosTable[256];

static bool DidUtilInit = false;

void DrawUtil_Init(void)
{
int i;
double radVal;
	
	if ( DidUtilInit )
		return;

	float_SinglePrecision();
	float_RoundToZero();	

	for (i = 0; i < TABLE_SIZE; i ++)
	{
		radVal = i * (TWOPI / TABLE_SIZE );
		
		DrawUtil_SinTable[i] = fSin(radVal);
		DrawUtil_CosTable[i] = fCos(radVal);
	}

	for (i = 0; i < 256; i ++)
	{
		radVal = i * (TWOPI / 256.0);
		
		DrawUtil_ByteSinTable[i] = (int) (127.5 * (sin(radVal) + 1.0));
		DrawUtil_ByteCosTable[i] = (int) (127.5 * (cos(radVal) + 1.0));
	}

	MakeHueRGBTable();

	MakeNoise1d();
	MakeNoise2d();
	MakeNoise3d();
	
	DidUtilInit = true;
}

//-------------------------------------------------------

ubyte HueRGBTable[768];

void MakeHueRGBTable(void)
{
int hue;
		
	for(hue=0;hue<256;hue++)
	{
	int h,H,r,g,b;
		H = (hue * 360)>>8;
		h = 180 - (H % 60)*3;

		switch( (H % 360)/60 )
		{
			case 0: r = 180;	g = 180 - h;b = 0; break;
			case 1: r = h; 		g = 180;	b = 0; break;
			case 2: r = 0; 		g = 180;	b = 180 - h; break;
			case 3: r = 0; 		g = h;		b = 180; break;
			case 4: r = 180 - h;g = 0;		b = 180; break;
			case 5: r = 180;	g = 0;		b = h; break;
		}
		HueRGBTable[hue*3  ] = r;
		HueRGBTable[hue*3+1] = g;
		HueRGBTable[hue*3+2] = b;
	}
}

void DrawUtil_HueRGBFast(int H,uword *r,uword *g,uword *b)
{
	H = (H & 0xFF) * 3;
	*r = HueRGBTable[H  ];
	*g = HueRGBTable[H+1];
	*b = HueRGBTable[H+2];
}

void DrawUtil_HueRGBSlow(int H,uword *pr,uword *pg,uword *pb)
{
int h;
	h = 255 - (H & 0xFF);

	switch( (H % (256*6))>>8 )
	{
		case 0: *pr = 255;		*pg = 255 - h;*pb = 0; break;
		case 1: *pr = h; 		*pg = 255;	*pb = 0; break;
		case 2: *pr = 0; 		*pg = 255;	*pb = 255 - h; break;
		case 3: *pr = 0; 		*pg = h;	*pb = 255; break;
		case 4: *pr = 255 - h;	*pg = 0;	*pb = 255; break;
		case 5: *pr = 255;		*pg = 0;	*pb = h; break;
	}
}

//------------------------------------------------------------------------

uword DrawUtil_MakePixel(int Mode,uword r,uword g,uword b)
{
	switch(Mode)
	{
		case DRIVER_MODE_555:
			return ((r>>3)<<10) | ((g>>3)<<5) | ((b>>3));
		case DRIVER_MODE_565:
			return ((r>>3)<<11) | ((g>>2)<<5) | ((b>>3));
		default:
			return 0;
	}
}

void DrawUtil_DrawLine(Driver_Window * W,int x1,int y1,int x2,int y2,uword pixel)
{
int dx,dy,m16;
uword * pBuf;
uint Stride;
	
	if ( ! DrawUtil_ClipSegI(W,&x1,&y1,&x2,&y2) )
		return; //totally clipped away

	assert( min(x1,x2) >= 0 );
	assert( max(x1,x2) <  (int)W->Width );
	assert( min(y1,y2) >= 0 );
	assert( max(y1,y2) <  (int)W->Height );

	pBuf = (uword *)W->Buffer;
	Stride = W->Stride >>1;

	if ( x2 < x1 )
	{
		swapints(x1,x2);
		swapints(y1,y2);
	}

	dx = x2 - x1;
	dy = y2 - y1;

	if ( ABS(dx) > ABS(dy) )
	{
	int x,y16;
		assert( dx > 0 );
		m16 = (dy << 16)/dx;
		y16 = (y1 << 16);
		for(x=x1;x<=x2;x++)
		{
			pBuf[ x + (y16>>16)*Stride ] = pixel;
			y16 += m16;
		}
	}
	else
	{
	int y,x16;
		assert( dy > 0 );
		m16 = (dx << 16)/dy;
		x16 = (x1 << 16);
		for(y=y1;y<=y2;y++)
		{
			pBuf[ (x16>>16) + y*Stride ] = pixel;
			x16 += m16;
		}
	}
}

/*
	or = ((*ptr)>>10)<<3;
	og = (((*ptr)>>5)&0x1F)<<3;
	ob = ((*ptr)&0x1F)<<3;
	r = (a16 * r + (65536 - a16) * or)>>16;
	g = (a16 * g + (65536 - a16) * og)>>16;
	b = (a16 * b + (65536 - a16) * ob)>>16;
	assert( r <= 255 && g <= 255 && b <= 255 );
	*ptr = ((r>>3)<<10) | ((g>>3)<<5) | ((b>>3));
*/

void INLINE blendpel555(uword *ptr,uint a16,uword r,uword g,uword b)
{
uword or,og,ob;

	or = (*ptr)>>10;
	og = ((*ptr)>>5)&0x1F;
	ob = (*ptr)&0x1F;
	r = (a16 * r + (65536 - a16) * or)>>16;
	g = (a16 * g + (65536 - a16) * og)>>16;
	b = (a16 * b + (65536 - a16) * ob)>>16;
	assert( r <= 31 && g <= 31 && b <= 31 );
	*ptr = (r<<10) | (g<<5) | b;
}

void INLINE blendpel565(uword *ptr,uint a16,uword r,uword g,uword b)
{
uword or,og,ob;

	or = (*ptr)>>11;
	og = ((*ptr)>>5)&0x3F;
	ob = (*ptr)&0x1F;
	r = (a16 * r + (65536 - a16) * or)>>16;
	g = (a16 * g + (65536 - a16) * og)>>16;
	b = (a16 * b + (65536 - a16) * ob)>>16;
	assert( r <= 31 && g <= 63 && b <= 31 );
	*ptr = (r<<11) | (g<<5) | b;
}

void shiftdowncolors(Driver_Window * W,uword *r,uword *g,uword *b)
{
	switch(W->Mode)
	{
		case DRIVER_MODE_555:
			*r >>= 3;
			*g >>= 3;
			*b >>= 3;
			break;
		case DRIVER_MODE_565:
			*r >>= 3;
			*g >>= 2;
			*b >>= 3;
			break;
	}

}

void DrawUtil_DrawLineV(Driver_Window * W,const Vec2d *cv1,const Vec2d *cv2,uword r,uword g,uword b)
{
int m16;
uword * pBuf;
uint Stride;
Vec2d v1,v2;

	v1 = *cv1;
	v2 = *cv2;
	if ( ! DrawUtil_ClipSegV(W,&v1,&v2) )
		return; //totally clipped away
	
	assert( min(v1.x,v2.x) >= 0 );
	assert( max(v1.x,v2.x) <  (int)W->Width );
	assert( min(v1.y,v2.y) >= 0 );
	assert( max(v1.y,v2.y) <  (int)W->Height );

	pBuf = (uword *)W->Buffer;
	Stride = W->Stride >>1;

	shiftdowncolors(W,&r,&g,&b);

	// @@ could do horizontal anti-aliasing at the start & finish too

	if ( ABS(v2.x - v1.x) > ABS(v2.y - v1.y) ) // mostly horizontal
	{
	int x,y16;
	int ix1,ix2;
		
		if ( v2.x < v1.x )
		{
			swapf(v1.x,v2.x);
			swapf(v1.y,v2.y);
		}

		if ( v1.y >= (W->Height-1) ) v1.y--;
		if ( v2.y >= (W->Height-1) ) v2.y--;

		y16 = ftoi(v1.y * 65536.0f);
		ix1 = ftoi(v1.x);
		ix2 = ftoi(v2.x);
		if ( ix1 == ix2 ) m16 = 0;
		else m16 = ftoi(((v2.y - v1.y) * 65536.0f))/(ix2 - ix1);

		switch(W->Mode)
		{
		case DRIVER_MODE_555:
			for(x=ix1;x<=ix2;x++)
			{
			uint frac;
			uword *ptr;
				frac = y16 & 0xFFFF;
				ptr = pBuf + x + (y16>>16)*Stride;
				blendpel555(ptr,0xFFFF - frac,r,g,b);
				blendpel555(ptr+Stride,  frac,r,g,b);
				y16 += m16;
			}
			break;
		case DRIVER_MODE_565:
			for(x=ix1;x<=ix2;x++)
			{
			uint frac;
			uword *ptr;
				frac = y16 & 0xFFFF;
				ptr = pBuf + x + (y16>>16)*Stride;
				blendpel565(ptr,0xFFFF - frac,r,g,b);
				blendpel565(ptr+Stride,  frac,r,g,b);
				y16 += m16;
			}
			break;
		}
	}
	else // mostly vertical
	{
	int y,x16;
	int iy1,iy2;
		
		if ( v2.y < v1.y )
		{
			swapf(v1.y,v2.y);
			swapf(v1.x,v2.x);
		}

		if ( v1.x >= (W->Width-1) ) v1.x--;
		if ( v2.x >= (W->Width-1) ) v2.x--;

		x16 = ftoi(v1.x * 65536.0f);
		iy1 = ftoi(v1.y);
		iy2 = ftoi(v2.y);
		if ( iy1 == iy2 ) m16 = 0;
		else m16 = ftoi(((v2.x - v1.x) * 65536.0f))/(iy2 - iy1);

		switch(W->Mode)
		{
		case DRIVER_MODE_555:
			for(y=iy1;y<=iy2;y++)
			{
			uint frac;
			uword *ptr;
				frac = x16 & 0xFFFF;
				ptr = pBuf + y*Stride + (x16>>16);
				blendpel555(ptr  ,0xFFFF - frac,r,g,b);
				blendpel555(ptr+1,         frac,r,g,b);
				x16 += m16;
			}
			break;
		case DRIVER_MODE_565:
			for(y=iy1;y<=iy2;y++)
			{
			uint frac;
			uword *ptr;
				frac = x16 & 0xFFFF;
				ptr = pBuf + y*Stride + (x16>>16);
				blendpel565(ptr  ,0xFFFF - frac,r,g,b);
				blendpel565(ptr+1,         frac,r,g,b);
				x16 += m16;
			}
			break;
		}
	}
}

void DrawUtil_DrawLineAA(Driver_Window * W,int x1,int y1,int x2,int y2,uword r,uword g,uword b)
{
int dx,dy,m16;
uword * pBuf;
uint Stride;

	if ( ! DrawUtil_ClipSegI(W,&x1,&y1,&x2,&y2) )
		return; //totally clipped away
	
	assert( min(x1,x2) >= 0 );
	assert( max(x1,x2) <  (int)W->Width );
	assert( min(y1,y2) >= 0 );
	assert( max(y1,y2) <  (int)W->Height );

	pBuf = (uword *)W->Buffer;
	Stride = W->Stride >>1;

	dx = x2 - x1;
	dy = y2 - y1;

	shiftdowncolors(W,&r,&g,&b);

	if ( ABS(dx) > ABS(dy) ) // mostly horizontal
	{
	int x,y16;
		if ( dx == 0 ) return;
		
		if ( x2 < x1 )
		{
			swapints(x1,x2);
			swapints(y1,y2);
		}
		if ( y1 == (int)(W->Height-1) ) y1--;
		if ( y2 == (int)(W->Height-1) ) y2--;
		dx = x2 - x1;
		dy = y2 - y1;
		m16 = (dy<<16)/dx;
		y16 = (y1 << 16);

		switch(W->Mode)
		{
		case DRIVER_MODE_555:
			for(x=x1;x<=x2;x++)
			{
			uint frac;
			uword *ptr;
				frac = y16 & 0xFFFF;
				ptr = pBuf + x + (y16>>16)*Stride;
				blendpel555(ptr,0xFFFF - frac,r,g,b);
				blendpel555(ptr+Stride,  frac,r,g,b);
				y16 += m16;
			}
			break;
		case DRIVER_MODE_565:
			for(x=x1;x<=x2;x++)
			{
			uint frac;
			uword *ptr;
				frac = y16 & 0xFFFF;
				ptr = pBuf + x + (y16>>16)*Stride;
				blendpel565(ptr,0xFFFF - frac,r,g,b);
				blendpel565(ptr+Stride,  frac,r,g,b);
				y16 += m16;
			}
			break;
		}
	}
	else // mostly vertical
	{
	int y,x16;
		if ( dy == 0 ) return;
		
		if ( y2 < y1 )
		{
			swapints(x1,x2);
			swapints(y1,y2);
		}
		if ( x1 == (int)(W->Width-1) ) x1--;
		if ( x2 == (int)(W->Width-1) ) x2--;
		dx = x2 - x1;
		dy = y2 - y1;
		m16 = (dx<<16)/dy;
		x16 = (x1 << 16);

		switch(W->Mode)
		{
		case DRIVER_MODE_555:
			for(y=y1;y<=y2;y++)
			{
			uint frac;
			uword *ptr;
				frac = x16 & 0xFFFF;
				ptr = pBuf + y*Stride + (x16>>16);
				blendpel555(ptr  ,0xFFFF - frac,r,g,b);
				blendpel555(ptr+1,         frac,r,g,b);
				x16 += m16;
			}
			break;
		case DRIVER_MODE_565:
			for(y=y1;y<=y2;y++)
			{
			uint frac;
			uword *ptr;
				frac = x16 & 0xFFFF;
				ptr = pBuf + y*Stride + (x16>>16);
				blendpel565(ptr  ,0xFFFF - frac,r,g,b);
				blendpel565(ptr+1,         frac,r,g,b);
				x16 += m16;
			}
			break;
		}
	}
}


bool DrawUtil_ClipPoint(const Driver_Window * pWindow,float *px,float *py)
{
bool clipped = false;

	if ( *px < 1.0f )
	{
		*px = 0.5f;
		clipped = true;
	}
	else if ( *px > (pWindow->Width-2) )
	{
		*px = pWindow->Width-1.5f;
		clipped = true;
	}
	if ( *py < 1.0f )
	{
		*py = 0.5f;
		clipped = true;
	}
	else if ( *py > (pWindow->Height-2) )
	{
		*py = pWindow->Height-1.5f;
		clipped = true;
	}
return clipped;	
}

bool DrawUtil_ClipSegI(const Driver_Window * W,int *px1,int *py1,int *px2,int *py2)
{
float x1,y1,x2,y2,m;

	x1 = *px1; y1 = *py1;
	x2 = *px2; y2 = *py2;
	if ( x1 > x2 )
	{
		swapf(x1,x2);
		swapf(y1,y2);
	}

	m = (y2 - y1)/(x2 - x1);

	if ( x1 < 0.0f )
	{
		// clip against the left
		if ( x2 <= 0.0f )
			return false;

		y1 += m * ABS(x1);
		x1 = 0.0f;
	}
	if ( x2 >= W->Width-1 )
	{
		// clip right
		if ( x1 >= W->Width-1 )
			return false;
		y2 -= m * (x2 - (W->Width-1));
		x2 = W->Width-1;
	}

⌨️ 快捷键说明

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