很久没有问过问题了,问一下:如何做阴影?

yesry 2004-02-27 05:30:09
如何给Draw在Canvas中的任意BMP增加阴影效果?
...全文
99 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
yesry 2004-03-23
  • 打赏
  • 举报
回复
总结起来,BMP有两种内容,一种是图像,一种是图形。

前者,要寻找边缘不容易,老妖的方法就是用BMP的边界矩形作为边缘进行阴影化。画阴影的方法是右边、下面各有4个像素的逐渐变化。角落使用6个像素的逐渐变化。

后者比较容易找到边缘,在边缘上画阴影。画阴影的方法仿效矩形阴影,但是角落的计算不容易。大家多多想想办法,如果我想到了就在这里公布。
yesry 2004-03-22
  • 打赏
  • 举报
回复
不知道也要说一下啊。
xiaoshi0 2004-03-22
  • 打赏
  • 举报
回复
我想不用管是什么形状,只要知道想要阴影的大小和方向,然后生成一个和图形一样大小的Bitmap,然后把Pixels[i][j]不是白色的部分画到Bitmap上,颜色全是黑色,最后按方向错开一定的位置,再用CopyMode把两个图形连起来就可以了
gjgj3368 2004-03-22
  • 打赏
  • 举报
回复
老妖,久闻大名啊,无缘相见,可惜
ccrun.com 2004-03-22
  • 打赏
  • 举报
回复
是的。矩形算法。别人写的,我只是略改动了一下。
猛禽 2004-03-22
  • 打赏
  • 举报
回复
老妖那个是矩形的阴影画法
猛禽 2004-03-22
  • 打赏
  • 举报
回复
就是有前景和背景的区别

如果只是一幅BMP,分不出前景背景,那是没法做的,不要告诉我你还要写程序来识别图象.

另,上面提到的填充,羽化,Alpha-Channel等,一般有标准算法,数字图像处理方面的书里都有.
ccrun.com 2004-03-22
  • 打赏
  • 举报
回复
// 绘制阴影
void __fastcall DrawShadow(HDC pDC, TRect rect)
{
COLORREF clOldColor = RGB(255, 255, 255);
BYTE btNewRedValue, btNewGreenValue, btNewBlueValue;
BYTE btAlphaArray[] = {140, 170, 212, 240};
BYTE btAlphaArray2[] = {170, 205, 220, 240, 240, 250, 255};

// 底部的阴影 -----------------------------------------
for(int j=0; j<4; j++)
{
for(int i=6; i<=rect.right-5-rect.left; i++)
{
clOldColor = GetPixel(pDC, i + rect.left, rect.bottom - (4 - j));
btNewRedValue = GetRValue(clOldColor) * btAlphaArray[j] / 255;
btNewGreenValue = GetGValue(clOldColor) * btAlphaArray[j] / 255;
btNewBlueValue = GetBValue(clOldColor) * btAlphaArray[j] / 255;
SetPixel(pDC, i + rect.left, rect.bottom - (4 - j), RGB(btNewRedValue,
btNewGreenValue, btNewBlueValue));
}
}

// 右边的阴影 -----------------------------------------
for(int i = 0; i<4; i++)
{
for(int j = 6; j <= rect.bottom - 5 - rect.top; j++)
{
clOldColor = GetPixel(pDC, rect.right - (4 - i), j + rect.top);
btNewRedValue = GetRValue(clOldColor) * btAlphaArray[i] / 255;
btNewGreenValue = GetGValue(clOldColor) * btAlphaArray[i] / 255;
btNewBlueValue = GetBValue(clOldColor) * btAlphaArray[i] / 255;
SetPixel(pDC, rect.right - (4 - i), j + rect.top, RGB(btNewRedValue,
btNewGreenValue, btNewBlueValue));
}
}

// 角上的阴影 --------------------------------------
for(int i=0; i<6; i++)
{
for(int j=0; j<6; j++)
{
if((i+j) > 6)
break;

clOldColor = GetPixel(pDC, rect.right - 4 + i, rect.bottom - 4 + j);
btNewRedValue = GetRValue(clOldColor) * btAlphaArray2[i + j] / 255;
btNewGreenValue = GetGValue(clOldColor) * btAlphaArray2[i + j] / 255;
btNewBlueValue = GetBValue(clOldColor) * btAlphaArray2[i + j] / 255;
SetPixel(pDC, rect.right - 4 + i, rect.bottom - 4 + j,
RGB(btNewRedValue, btNewGreenValue, btNewBlueValue));

clOldColor = GetPixel(pDC,rect.right - 4 + i, rect.top + 5 - j);
btNewRedValue = GetRValue(clOldColor) * btAlphaArray2[i + j] / 255;
btNewGreenValue = GetGValue(clOldColor) * btAlphaArray2[i + j] / 255;
btNewBlueValue = GetBValue(clOldColor) * btAlphaArray2[i + j] / 255;
SetPixel(pDC, rect.right - 4 + i, rect.top + 5 - j,
RGB(btNewRedValue, btNewGreenValue, btNewBlueValue));

clOldColor = GetPixel(pDC, rect.left - i + 5, rect.bottom - 4 + j);
btNewRedValue = GetRValue(clOldColor) * btAlphaArray2[i + j] / 255;
btNewGreenValue = GetGValue(clOldColor) * btAlphaArray2[i + j] / 255;
btNewBlueValue = GetBValue(clOldColor) * btAlphaArray2[i + j] / 255;
SetPixel(pDC, rect.left - i + 5, rect.bottom - 4 + j,
RGB(btNewRedValue, btNewGreenValue, btNewBlueValue));
}
}
}
//---------------------------------------------------------------------------
// 调用举例
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TRect rect = Image1->BoundsRect;
rect.right += 4;
rect.bottom += 4;
DrawShadow(Canvas->Handle, rect);
}
猛禽 2004-03-22
  • 打赏
  • 举报
回复
任意BMP?

这个提法就是错误的

既然有阴影,就是前景和背景的区别

标准的做法是先在CANVAS上画一个背景,然后把前景图做黑色填充,再边缘羽化(其程度取决于投影的高度),然后用Alpha-Channel的方式,加上一定的位移(取决于投影的角度和高度)叠画到背景上,再把前景画上即可

13,825

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧