8

我想以编程方式在图像上创建光泽效果,有点像 Web 在更新到 2.0 Beta 时采用的受 Apple 启发的设计。

本质上是这样的:

示例图标 http://nhc.hcmuns.googlepages.com/web2_icons.jpg

现在,我在这里看到了两种方法:我创建了一个具有光泽效果的 Alpha 通道的图像,然后我将输入和光泽 Alpha 图标组合起来创建它。

第二种方法:在代码中创建 Alpha Gloss Image,然后将其与输入图形合并。

我更喜欢第二种解决方案,但我不是一个图形人,我不知道创建这种效果的算法是什么。有人可以给我一些指示*我实际上在这里寻找什么吗?有没有名字的“光泽算法”?甚至已经实现了.net?

*不,不是那些类型的指针。

4

3 回答 3

17

谢谢你,德文!这是我的 C# 代码,用于实现您的建议。它工作得很好。将其变成社区拥有的 Wiki 帖子,如果有人喜欢添加一些代码,请随时编辑。

例子

(示例使用的 Alpha 和曝光值与下面的代码不同)

Image img = Image.FromFile("rss-icon.jpg");
pictureBox1.Image = AddCircularGloss(img, 30,25,255,255,255);

public static Image AddCircularGloss(Image inputImage, int exposurePercentage, int transparency, int fillColorR, int fillColorG, int fillColorB)
{
    Bitmap outputImage = new Bitmap(inputImage);
    using (Graphics g = Graphics.FromImage(outputImage))
    {
        using (Pen p = new Pen(Color.FromArgb(transparency, fillColorR, fillColorG, fillColorB)))
        {
            // Looks jaggy otherwise
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.CompositingQuality = CompositingQuality.HighQuality;
            int x, y;

            // 3 * Height looks best
            int diameter = outputImage.Height * 3;
            double imgPercent = (double)outputImage.Height / 100;
            x = 0 - outputImage.Width;

            // How many percent of the image to expose
            y = (0 - diameter) + (int)(imgPercent * exposurePercentage);
            g.FillEllipse(p.Brush, x, y, diameter, diameter);
        }
    }
    return outputImage;
}

(根据 John 的建议进行了更改。但我无法处理 Bitmap,这必须由函数的调用者完成)

于 2008-09-21T00:19:14.930 回答
8

我可以用图形术语来解释这种效果。

  1. 创建一个大约 3* 图标大小的图像。

  2. 在此图像中,创建一个圆圈,其中(图标的高度)< 半径 < 2*(图标的高度)。

  3. 用 10% 的 alpha 混合/透明度(到白色)填充圆圈。

  4. 将该圆形图像裁剪为与您的图标大小相同的新图像,其中圆形的中心位于查看区域之外,但向上是较小图像高度的 1/2。

如果然后将此图像叠加到原始图标上,效果应该类似于上面的图标。如果您热衷于此,它应该可以使用 imagemagick,或者您可以根据要使用的语言选择其中一种图形 API。从上面的步骤来看,它应该很容易以编程方式进行。

于 2008-09-20T23:34:25.913 回答
3

响应 C# 代码……总的来说,在成像方面做得很好。过去,我不得不对我的一些应用程序做类似的事情。

但是,有一条建议:.NET 中的所有图形对象都基于 Windows GDI+ 原语。这意味着这些对象需要正确处理以清理它们的非内存资源,就像文件句柄或数据库连接一样。您需要稍微调整代码以正确支持它。

所有的 GDI+ 对象都实现了 IDisposable 接口,使它们在 using 语句中起作用。考虑重写您的代码,类似于以下内容:

// Experiment with this value
int exposurePercentage = 40;

using (Image img = Image.FromFile("rss-icon.jpg"))
{
    using (Graphics g = Graphics.FromImage(img))
    {    
        // First Number = Alpha, Experiment with this value.
        using (Pen p = new Pen(Color.FromArgb(75, 255, 255, 255)))
        {
            // Looks jaggy otherwise
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

            int x, y;

            // 3 * Height looks best
            int diameter = img.Height * 3;
            double imgPercent = (double)img.Height / 100;
            x = 0 - img.Width;

            // How many percent of the image to expose
            y = (0 - diameter) + (int)(imgPercent * exposurePercentage);

            g.FillEllipse(p.Brush, x, y, diameter, diameter);

            pictureBox1.Image = img;
        }
    }
}

(请记住,与我的大多数示例不同,我没有机会编译和测试它......这更多的是作为构建代码以确保没有资源泄漏的示例,而不是作为成品. 无论如何,可能有更好的方法来抽象/构造它。强烈考虑这样做——把它扔进一个图形库 DLL 中,你可以在将来需要这些功能的任何项目中引用它!)

于 2008-09-21T10:17:17.473 回答