GDI+ 的对角线阴影

Diagonal Shadow with GDI+

我正在尝试绘制对角线阴影。

首先我将所有像素设为黑色:

接下来用一个简单的for cicle就是结果

现在我想沿对角线拉伸此图像以模拟阴影。
我试过:

Bitmap b = new Bitmap(tImage.Width + 100, tImage.Height);
Graphics p = Graphics.FromImage(b);
p.RotateTransform(30f);
p.TranslateTransform(100f, -200f);
p.DrawImage(tImage, new Rectangle(0, -20, b.Width+20, b.Height));

但图像被旋转和平移。

请问有人能给我解决方案吗?

我需要它看起来像这样(在 Photoshop 中创建):

使用 Winforms 和 GDI+ 创建漂亮的阴影是一项相当艰巨的任务。

它既没有多边形缩放也没有模糊;让我们甚至不要考虑 3D..! - 但我们至少可以在不做太多工作的情况下做一些事情,并为许多图像获得不错的结果..

假设您已经有一张从背景中裁剪下来的图像。

下一步是将所有颜色变成黑色。

那么我们很可能想要添加一定程度的透明度,这样阴影落在的背景仍然会发光。

通过使用合适的 ColorMatrix.

这两项任务都非常有效地完成了

对于非常透明的版本,我们还可以通过使用偏移绘制图像来创建简单的模糊效果。为了获得最佳效果,我会使用 3 个不同的 weights/alpha 值将其绘制九次..

高质量模糊是一门艺术,您甚至可以通过 Adobe PhotoshopAffinity Photo[= 等专业软件中的滤镜和调整来了解这一点94=]。这是一组 nice 有趣的链接..

但是由于我们只处理 b/w 位图,所以简单的方法就足够了。我使用 5%、10% 和 20% 的 3 个 alpha 值用于第 4 个角、第 4 个边和1 个中心图纸。

最后一步是绘制带有一些 倾斜 的阴影。

这是解释here;但是,虽然这看起来很简单,但也有些不切实际。 DrawImage overlay 期望的三个点需要计算。

所以这里有一个方法可以做到这一点;请注意,这是一种高度简化的方法:

叠加取三点,即6浮点数。我们只使用 3 个数字:

  • 一个是偏斜量; 0.5表示顶部向右移动位图宽度的一半。
  • 另外两个是生成的边界框的缩放比例。 10.5表示宽度不变,高度缩小为50%

函数如下:

public Bitmap SkewBitmap(Bitmap inMap, float skewX, float ratioX, float ratioY )
{
    int nWidth = (int)(inMap.Width * (skewX + ratioX));
    int nHeight = (int)(Math.Max(inMap.Height, inMap.Height * ratioY));
    int yOffset = inMap.Height - nHeight;

    Bitmap outMap = new Bitmap(nWidth, nHeight);

    Point[] destinationPoints = {
        new Point((int)(inMap.Width * skewX), (int)(inMap.Height * ratioY) + yOffset),
        new Point((int)(inMap.Width * skewX + inMap.Width * ratioX),
                  (int)(inMap.Height * ratioY) + yOffset),
        new Point(0, inMap.Height + yOffset ) };

        using (Graphics g = Graphics.FromImage(outMap))
        g.DrawImage(inMap, destinationPoints);

    return outMap;
}

注意一些简化:

  • 如果要将阴影向左移动,您不仅需要将前两个点向左移动,还需要调整宽度的计算以及叠加方式阴影上方的对象。

  • 如果您研究 MSDN 示例,您会发现 DrawImage 叠加层还允许进行旋转。我没有将它添加到我们的函数中,因为计算起来要复杂得多,甚至只是写一个签名。

  • 如果你想知道这六个数字的信息在哪里,这里是完整的布局:

    • 3进入我们的参数
    • 1 是我们不做的旋转角度
    • 2 可以是旋转中心点或结果平移的点 (deltaX&Y)
  • 仔细看可以看到左脚的影子在脚下一点点。这是因为双脚不在同一水平面上,并且由于垂直压缩,基线会分开。要纠正这个问题,我们要么修改图像,要么添加一个微小的旋转。

  • 看你的例子很明显,你需要把它拆开,分开对待'house'和'tree'!

  • 签名保持简单;这始终是易用性和编码工作量之间的平衡。可能希望有一个参数 take angle 来控制倾斜。随意进行必要的计算..

请注意,在其他按钮后面添加功能将超出问题的范围。我只想说大多数只是一条线来做图,十几条线来设置颜色矩阵..

这是 'Skew' 按钮中的代码:

Bitmap bmp = SkewBitmap((Bitmap)pictureBox4.Image, 0.5f, 1f, 0.5f);

pictureBox5.Image = pictureBox1.Image;
pictureBox5.BackgroundImage = bmp;
pictureBox5.ClientSize = new Size(bmp.Width, bmp.Height);

我没有在阴影上绘制对象,而是使用 PictureBox 的额外图层。你当然会结合这两个 Bitmaps..