CRI Radio

May 10, 2007

CCS source--imgEffect.c

/*----------------------------------------------------------
Define : Type for Effect Library
-----------------------------------------------------------*/
#define DISPLAY_HEIGHT 220
#define DISPLAY_WIDTH 176

#define PEG2RGB(peg) ((((DWORD)peg>>11)<<3)&0xF8)|(((DWORD)peg<<5)&0xFC00)|(((DWORD)peg<<19)&0xF80000);
#define GetRValue(rgb) ((BYTE)(rgb))
#define GetGValue(rgb) ((BYTE)(((WORD)(rgb)) >> 8))
#define GetBValue(rgb) ((BYTE)((rgb)>>16))
#define PEG(r,g,b) ((WORD) (((r) >> 3) <<>> 2) <<>> 3))

typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef struct tagRGBQUAD
{
BYTE rgbReserved;
BYTE rgbRed;
BYTE rgbGreen;
BYTE rgbBlue;
}
RGBQUAD;

#ifdef _DEBUG
#define IMGDATA
IMGDATA WORD display[220][176];
IMGDATA int waitState=6;
#include "ccsView.c"
#else
#define IMGDATA static
extern WORD display[220][176];
#endif

#if defined(DEMO_IMGE_PPM)||defined(__NegaRGB)||defined(__Gray)||defined(__Sepia)||defined(__Emboss)||defined(__Sketch)||defined(__Smooth)||defined(__FlipH)||defined(__FlipV)

IMGDATA RGBQUAD rgb[DISPLAY_HEIGHT][DISPLAY_WIDTH];
void RGB5652RGB(BYTE* pPegBuf,WORD width, WORD height)
{
WORD h,w;
WORD *pPEG;
WORD color;
DWORD dcolor;

if(!pPegBuf)
{

return;///pointer is null,error!
}

//Step1. Read one pixel from internal SRAM.
pPEG = (WORD*)pPegBuf;
for(h = 0;h < height; h++)
{
for(w = 0;w < width; w++)
{
color=(WORD)(*pPEG++);
dcolor=PEG2RGB(color);
//Step2. Converts 16bit data to 24bit data.
rgb[h][w].rgbRed=GetRValue(dcolor);
rgb[h][w].rgbGreen=GetGValue(dcolor);
rgb[h][w].rgbBlue=GetBValue(dcolor);
}
}
}

void RGB2RGB565(BYTE* dstAddr,WORD width, WORD height)
{
WORD h,w;
WORD *pDst;

pDst = (WORD*)dstAddr;
for(h = 0; h < height; h++)
{
for(w = 0; w < width; w++)
{
*pDst++ = PEG(rgb[h][w].rgbRed,rgb[h][w].rgbGreen,rgb[h][w].rgbBlue);
}
}
}
/*-----------------------------------------------------------------------
Function name : RGB2YUV()
Prototype : void RGB2YUV(BYTE r, BYTE g, BYTE b,
BYTE *retY, BYTE *retU, BYTE *retV);
Return : Nothing
Argument : r, g, b, *retY, *retU, *retV
Comments : This function converts RGB 16bit data to YUV data.
-----------------------------------------------------------------------*/
void RGB2YUV(BYTE r, BYTE g, BYTE b, BYTE *retY, BYTE *retU, BYTE *retV)
{
int y, u, v;

/*
y = (0.299 * r + 0.587 * g + 0.114 * b);
u = (0.5 * b - 0.1687 * r - 0.3313 * g) + 128;
v = (0.5 * r - 0.419 * g - 0.081 * b) + 128;
*/

y = (19595 * r + 38470 * g + 7471 * b);
u = (32768 * b - 11056 * r - 21712 * g) + 8388608;
v = (32768 * r - 27460 * g - 5308 * b) + 8388608;

*retY = (y <> 16711680) ? 255 : (y >> 16);
*retU = (u <> 16711680) ? 255 : (u >> 16);
*retV = (v <> 16711680) ? 255 : (v >> 16);
}

/*-----------------------------------------------------------------------
Function name : YUV2RGB()
Prototype : void YUV2RGB(BYTE y, BYTE u, BYTE v,
BYTE *retR, BYTE *retG, BYTE *retB)
Return : Nothing
Argument : y, u, v, *retR, *retG, *retB
Comments : This function converts YUV data to RGB 16bit data.
-----------------------------------------------------------------------*/
void YUV2RGB(BYTE y, BYTE u, BYTE v, BYTE *retR, BYTE *retG, BYTE *retB)
{
int r, g, b;

/*
r = y + (int)(1.402 * (float)(v - 128) );
g = y - (int)(0.34414 * (float)(u - 128) + 0.71414 * (float)(v - 128));
b = y + (int)(1.772 * (float)(u - 128));
*/

r = (y << 16) + (91881 * (v - 128));
g = (y << 16) - (22554 * (u - 128) + 46802 * (v - 128));
b = (y << 16) + (116130 * (u - 128));

*retR = (r <> 16711680) ? 255 : (r >> 16);
*retG = (g <> 16711680) ? 255 : (g >> 16);
*retB = (b <> 16711680) ? 255 : (b >> 16);
}
#endif

#if defined(__NegaRGB)
/*
反色有时是很有用的,比如,图中黑色区域占绝大多数,这样打印起来很费墨,
我们可以先进行反色处理后再打印。
反色的实际含义是将R、G、B值反转。若颜色的量化级别是256,则新图的R、G、
B值为255减去原图的R、G、B值。这里针对的是所有图,包括真彩图、带调色板
的彩色图(又称为伪彩色图)、和灰度图。针对不同种类有不同的处理。
先看看真彩图。我们知道真彩图不带调色板,每个象素用3个字节,表示R、G、
B三个分量。所以处理很简单,把反转后的R、G、B值写入新图即可。
再来看看带调色板的彩色图,我们知道位图中的数据只是对应调色板中的一个
索引值,我们只需要将调色板中的颜色反转,形成新调色板,而位图数据不用
动,就能够实现反转。
灰度图是一种特殊的伪彩色图,只不过调色板中的R、G、B值 都是一样的而已。
所以反转的处理和上面讲的一样。
这里,我想澄清一个概念。过去我们讲二值图时,一直都说成黑白图。二值位
图一定是黑白的吗?答案是不一定。我们安装Windows95时看到的那幅setup.bmp
是由蓝色和黑色组成的,但它实际上是二值图。原来,它的调色板中的两种颜色
是黑与蓝,而不是黑与白。所以说二值图也可以是彩色的,只不过一般情况下是
黑白图而已。
*/
/*-----------------------------------------------------------------------
Function name : NegaRGB()
Prototype : void NegaRGB(WORD srcAddr, WORD dstAddr,
WORD width, WORD height);
Return : Nothing
Argument : srcAddr, dstAddr, width, height
Comments : This function inverts RGB color.
-----------------------------------------------------------------------*/
void NegaRGB(BYTE *srcAddr, BYTE *dstAddr, WORD width, WORD height)
{
#if 0
BYTE r, g, b;
BYTE y, u, v;
#endif
WORD w,h;
WORD *pDst;

RGB5652RGB(srcAddr,width,height);
pDst=(WORD *)dstAddr;
for(h = 0; h < height; h++)
{
for(w = 0; w < width; w++)
{
#if 0
r = rgb[h][w].rgbRed;
g = rgb[h][w].rgbGreen;
b = rgb[h][w].rgbBlue;

//Step3. Converts RGB 24bit data to YUV data.
RGB2YUV(r, g, b, &y, &u, &v);

//Step4. Suctract YUV data from original value.
y = 255 - y;
u = 255 - u;
v = 255 - v;

//Step5. Converts YUV data to RGB 24bit data.
YUV2RGB(y, u, v, &r, &g, &b);

//Step6. Converts RGB 24bit data to RGB 16bit data.
//Step7. Display through LCD driver.
*pDst++ = PEG(r,g,b);
#else
*pDst++ = PEG(255-rgb[h][w].rgbRed,255-rgb[h][w].rgbGreen,255-rgb[h][w].rgbBlue);
#endif
}
}
}
#endif
#if defined(__Gray)
/*
彩色图像到灰度图像的变换
Gray(i,j)=0.11*R(i,j)+0.59*G(i,j)+0.39*B(i,j);
我们利用上式,根据R、G、B的值求出Y值后,将R、G、B值都赋值成Y,就能表示出
灰度图来,这就是彩色图转灰度图的原理?
先看看真彩图。我们知道真彩图不带调色板,每个象素用3个字节,表示R、G、B三
个分量。所以处理很简单,根据R、G、B的值求出Y值后,将R、G、B值都赋值成Y,
写入新图即可。
再来看看带调色板的彩色图,我们知道位图中的数据只是对应调色板中的一个索引
值,我们只需要将调色板中的彩色变成灰度,形成新调色板,而位图数据不用动,
就可以了。
*/
/*-----------------------------------------------------------------------
Function name : Grey()
Prototype : void Grey(WORD srcAddr, WORD dstAddr,
WORD width, WORD height);
Return : Nothing
Argument : srcAddr, dstAddr, width, height
Comments : This function make gray effect to image.
-----------------------------------------------------------------------*/
void Gray(BYTE *srcAddr, BYTE *dstAddr, WORD width, WORD height)
{
BYTE r, g, b;
BYTE y, u, v;
WORD w,h;
WORD *pDst;

RGB5652RGB(srcAddr,width,height);
pDst=(WORD *)dstAddr;
for(h = 0; h < height; h++)
{
for(w = 0; w < width; w++)
{
r = rgb[h][w].rgbRed;
g = rgb[h][w].rgbGreen;
b = rgb[h][w].rgbBlue;

//Step3. Converts RGB 24bit data to YUV data.
RGB2YUV(r, g, b, &y, &u, &v);

//Step4. Set Y(luminance) vlaue to RGB value.
r = g = b = y;

//Step6. Converts RGB 24bit data to RGB 16bit data.
//Step7. Display through LCD driver.
*pDst++ = PEG(r,g,b);
}
}
}
#endif
#if defined(__Sepia)
/*-----------------------------------------------------------------------
Function name : Sepia()
Prototype : void Sepia(WORD srcAddr, WORD dstAddr,
WORD width, WORD height);
Return : Nothing
Argument : srcAddr, dstAddr, width, height
Comments : This function make sepia effect to image.
-----------------------------------------------------------------------*/
void Sepia(BYTE *srcAddr, BYTE *dstAddr, WORD width, WORD height)
{
BYTE r, g, b;
BYTE y, u, v;
WORD w,h;
WORD *pDst;

RGB5652RGB(srcAddr,width,height);
pDst=(WORD *)dstAddr;
for(h = 0; h < height; h++)
{
for(w = 0; w < width; w++)
{
r = rgb[h][w].rgbRed;
g = rgb[h][w].rgbGreen;
b = rgb[h][w].rgbBlue;

//Step3. Converts RGB 24bit data to YUV data.
RGB2YUV(r, g, b, &y, &u, &v);

//Step4. Set a fixed value for u,v.
u = 100;
v = 140;

//Step5. Converts YUV data to RGB 24bit data.
YUV2RGB(y, u, v, &r, &g, &b);

//Step6. Converts RGB 24bit data to RGB 16bit data.
//Step7. Display through LCD driver.
*pDst++ = PEG(r,g,b);
}
}
}
#endif
#if defined(__Emboss)
/*-----------------------------------------------------------------------
Function name : Emboss()
Prototype : void Emboss(WORD srcAddr, WORD dstAddr,
WORD width, WORD height, WORD level);
Return : Nothing
Argument : srcAddr, dstAddr, width, height, level
Comments : This function make emboss effect to image.
-----------------------------------------------------------------------*/
void Emboss(BYTE *srcAddr, BYTE *dstAddr, WORD width, WORD height)
{
BYTE r, g, b;
BYTE y, u, v;
WORD w,h;
WORD *pDst;
BYTE r2, g2, b2;
BYTE yy;
int tmp, y2;
WORD level=2;
WORD wt;


RGB5652RGB(srcAddr,width,height);
pDst=(WORD *)dstAddr;
for(h = 0; h < height; h++)
{
for(w = 0; w < width; w++)
{
r = rgb[h][w].rgbRed;
g = rgb[h][w].rgbGreen;
b = rgb[h][w].rgbBlue;

//Step3. Converts RGB 24bit data to YUV data.
RGB2YUV(r, g, b, &y, &u, &v);

//Step4. Set a fixed value for u,v.
u = 128;
v = 128;
//Step5. For emboss effect, read RGB data by keeping a fixed interval.
wt=w;
if ((w) < (width - level))
{
wt=w+level;
}
if ( (w >= (width - level)) && (w < width) )
{
wt=w+width-1;
}

//Step6. Calculate emboss effect Y(luminance) value.
r2 = rgb[h][wt].rgbRed;
g2 = rgb[h][wt].rgbGreen;
b2 = rgb[h][wt].rgbBlue;

y2 = (19595 * r2 + 38470 * g2 + 7471 * b2);

yy = (y2 <> 16711680) ? 255 : (y2 >> 16);


tmp = 128 + y - yy;
y = tmp > 255 ? 255 : tmp < 0 ? 0 : tmp;

//Step5. Converts YUV data to RGB 24bit data.
YUV2RGB(y, u, v, &r, &g, &b);

//Step6. Converts RGB 24bit data to RGB 16bit data.
//Step7. Display through LCD driver.
*pDst++ = PEG(r,g,b);
}
}
}
#endif
#if defined(__Sketch)
/*-----------------------------------------------------------------------
Function name : Sketch()
Prototype : void Sketch(WORD srcAddr, WORD dstAddr,
WORD width, WORD height, WORD level);
Return : Nothing
Argument : srcAddr, dstAddr, width, height, level
Comments : This function make sketch effect to image.
-----------------------------------------------------------------------*/
void Sketch(BYTE *srcAddr, BYTE *dstAddr, WORD width, WORD height)
{
BYTE r, g, b;
BYTE y, u, v;
WORD w,h;
WORD *pDst;
BYTE r2, g2, b2;
BYTE yy;
int tmp, y2;
WORD level=2;
WORD wt;


RGB5652RGB(srcAddr,width,height);
pDst=(WORD *)dstAddr;
for(h = 0; h < height; h++)
{
for(w = 0; w < width; w++)
{
r = rgb[h][w].rgbRed;
g = rgb[h][w].rgbGreen;
b = rgb[h][w].rgbBlue;

//Step3. Converts RGB 24bit data to YUV data.
RGB2YUV(r, g, b, &y, &u, &v);

//Step4. Set a fixed value for u,v.
u = 128;
v = 128;
//Step5. For emboss effect, read RGB data by keeping a fixed interval.
wt=w;
if ((w) < (width - level))
{
wt=w+level;
}
if ( (w >= (width - level)) && (w < width) )
{
wt=w+width-1;
}

//Step6. Calculate sketch effect Y(luminance) value.
r2 = rgb[h][wt].rgbRed;
g2 = rgb[h][wt].rgbGreen;
b2 = rgb[h][wt].rgbBlue;

y2 = (19595 * r2 + 38470 * g2 + 7471 * b2);

yy = (y2 <> 16711680) ? 255 : (y2 >> 16);

tmp = y - yy;
tmp = tmp < 0 ? -tmp : tmp;
tmp = tmp > 75 ? 150 : (tmp << 1);
y = 255 - tmp;//?128:255;//255:Y[i*width+j];

//Step5. Converts YUV data to RGB 24bit data.
YUV2RGB(y, u, v, &r, &g, &b);

//Step6. Converts RGB 24bit data to RGB 16bit data.
//Step7. Display through LCD driver.
*pDst++ = PEG(r,g,b);
}
}
}
#endif
#if defined(__Smooth)
/*-----------------------------------------------------------------------
Function name : Smooth()
Prototype : void Smooth(WORD srcAddr, WORD dstAddr,
WORD width, WORD height);
Return : Nothing
Argument : srcAddr, dstAddr, width, height
Comments : This function inverts RGB color.
-----------------------------------------------------------------------*/
void Smooth(BYTE *srcAddr, BYTE *dstAddr, WORD width, WORD height)
{
BYTE r, g, b;
BYTE y, u, v;
WORD w,h;
WORD *pDst;
WORD level=4;
WORD rr, gg, bb;

RGB5652RGB(srcAddr,width,height);
pDst=(WORD *)dstAddr;
for(h = 0; h < height; h++)
{
for(w = 0; w < width; w++)
{
if((h==0)|(h==height-1))
{
*pDst++=PEG(rgb[h][w].rgbRed,rgb[h][w].rgbGreen,rgb[h][w].rgbBlue);
}else if((w==0)|(w==width-1))
{
*pDst++=PEG(rgb[h][w].rgbRed,rgb[h][w].rgbGreen,rgb[h][w].rgbBlue);
}
else if((w%level==0)||(h%level==0))
{
*pDst++=PEG(128,128,128);
}
else
{
rr=(WORD)rgb[h-1][w-1].rgbRed+(WORD)rgb[h][w-1].rgbRed+(WORD)rgb[h+1][w-1].rgbRed+
(WORD)rgb[h-1][w].rgbRed+(WORD)rgb[h][w].rgbRed+(WORD)rgb[h+1][w].rgbRed+
(WORD)rgb[h-1][w+1].rgbRed+(WORD)rgb[h][w+1].rgbRed+(WORD)rgb[h+1][w+1].rgbRed;
gg=(WORD)rgb[h-1][w-1].rgbGreen+(WORD)rgb[h][w-1].rgbGreen+(WORD)rgb[h+1][w-1].rgbGreen+
(WORD)rgb[h-1][w].rgbGreen+(WORD)rgb[h][w].rgbGreen+(WORD)rgb[h+1][w].rgbGreen+
(WORD)rgb[h-1][w+1].rgbGreen+(WORD)rgb[h][w+1].rgbGreen+(WORD)rgb[h+1][w+1].rgbGreen;
bb=(WORD)rgb[h-1][w-1].rgbBlue+(WORD)rgb[h][w-1].rgbBlue+(WORD)rgb[h+1][w-1].rgbBlue+
(WORD)rgb[h-1][w].rgbBlue+(WORD)rgb[h][w].rgbBlue+(WORD)rgb[h+1][w].rgbBlue+
(WORD)rgb[h-1][w+1].rgbBlue+(WORD)rgb[h][w+1].rgbBlue+(WORD)rgb[h+1][w+1].rgbBlue;
r=(BYTE)(rr/9);
g=(BYTE)(gg/9);
b=(BYTE)(bb/9);
//Step3. Converts RGB 24bit data to YUV data.
if(rr>0x7FF)
r=227;
if(gg>0x7FF)
g=227;
if(bb>0x7FF)
b=227;
RGB2YUV(r, g, b, &y, &u, &v);

//Step4. Suctract YUV data from original value.
y = y+20;
//Step5. Converts YUV data to RGB 24bit data.
YUV2RGB(y, u, v, &r, &g, &b);

//Step6. Converts RGB 24bit data to RGB 16bit data.
//Step7. Display through LCD driver.
*pDst++ = PEG(r,g,b);
}
}
}
}
#endif
#if defined(__FlipH)
/*-----------------------------------------------------------------------
Function name : FlipH()
Prototype : void FlipH(WORD srcAddr, WORD dstAddr,
WORD width, WORD height);
Return : Nothing
Argument : srcAddr, dstAddr, width, height
Comments : This function inverts RGB color.
-----------------------------------------------------------------------*/
void FlipH(BYTE *srcAddr, BYTE *dstAddr, WORD width, WORD height)
{
WORD w,h;
WORD *pDst;

RGB5652RGB(srcAddr,width,height);
pDst=(WORD *)dstAddr;
for(h = 0; h < height; h++)
{
for(w = width; w > 0; w--)
{
*pDst++ = PEG(rgb[h][w-1].rgbRed,rgb[h][w-1].rgbGreen,rgb[h][w-1].rgbBlue);
}
}
}
#endif
#if defined(__FlipV)
/*-----------------------------------------------------------------------
Function name : FlipV()
Prototype : void FlipV(WORD srcAddr, WORD dstAddr,
WORD width, WORD height);
Return : Nothing
Argument : srcAddr, dstAddr, width, height
Comments : This function inverts RGB color.
-----------------------------------------------------------------------*/
void FlipV(BYTE *srcAddr, BYTE *dstAddr, WORD width, WORD height)
{
WORD w,h;
WORD *pDst;

RGB5652RGB(srcAddr,width,height);
pDst=(WORD *)dstAddr;
for(h = height; h > 0; h--)
{
for(w = 0; w < width; w++)
{
*pDst++ = PEG(rgb[h-1][w].rgbRed,rgb[h-1][w].rgbGreen,rgb[h-1][w].rgbBlue);
}
}
}
#endif
/*
真彩图转256色图
我们知道,真彩图中包含最多达224种颜色,怎样从中选出256种颜色,又要使颜色的
失真比较小,这是一个比较复杂的问题。一种简单的做法是将R:G:B以3:3:2表示,
即取R,G的高3位,B的高两位,组成一个字节,这样就可以表示256种颜色了,但不难
想象,这种方法的失真肯定很严重。
我们下面介绍的算法能够比较好地实现真彩图到256色图的转换。它的思想是:准备一
个长度为4096的数组,代表4096种颜色。对图中的每一个象素,取R、G、B的最高四位,
拼成一个12位的整数,对应的数组元素加1。全部统计完后,就得到了这4096种颜色的
使用频率。其中,可能有一些颜色一次也没用到,即对应的数组元素为零(假设不为零
的数组元素共有PalCounts个)。将这些为零的数组元素清除出去,使得前PalCounts个
元素都不为零。将这PalCounts个数按从大到小的顺序排列(这里我们使用起泡排序)。
这样,前256种颜色就是用的最多的颜色,它们将作为调色板上的256种颜色。对于剩
下的PalCounts-256种颜色并不是简单地丢弃,而是用前256种颜色中的一种来代替,
代替的原则是找有最小平方误差的那个。再次对图中的每一个象素,取R、G、B的最高
四位,拼成一个12位的整数,如果对应值在前256种颜色中,则直接将该索引值填入位
图数据中,如果是在后PalCounts-256种颜色中,则用代替色的索引值填入位图数据中。
*/
/*
对比度扩展
假设有一幅图,由于成象时光照不足,使得整幅图偏暗(例如,灰度范围从0到63);或
者成象时光照过强,使得整幅图偏亮(例如,灰度范围从200到255),我们称这些情况
为低对比度,即灰度都挤在一起,没有拉开。灰度扩展的意思就是把你所感兴趣的灰度
范围拉开,使得该范围内的象素,亮的越亮,暗的越暗,从而达到了增强对比度的目的。
*/