构建GrayScaleBrushes类

时间:2011-01-10 19:27:14

标签: c# .net gdi+

最近,我发现了基于色调和亮度值的.NET颜色表。让我震惊的是疯狂的灰度图表。例如,DarkGray实际上比Gray更轻?另外,我在rgb值的渐变中看不到任何逻辑,它从0到105到128?

0   : Black
105 : DimGray 
128 : Gray
169 : DarkGray!
192 : Silver
211 : LightGray 
220 : Gainsboro
245 : Ghostwhite
255 : White

http://sites.google.com/site/cdeveloperresources/

color chart - see link above

我想要的是一个GrayScaleBrushes类,其行为与Brushes类完全相同,但使用我的自定义方案,如:

GrayScaleBrushes.Pct05
GrayScaleBrushes.Pct10
GrayScaleBrushes.Pct15
..all the way to.Pct95
...
ie: e.FillRectangle( GrayScaleBrushes.Pct05, exampleRect );

如何做到这一点,确保刷子能够正确处理?

编辑:.NET Brushes类如下所示(使用反射器进行反汇编)。

public sealed class Brushes
{
    // Fields
    private static readonly object AliceBlueKey = new object();

    // Methods
    private Brushes()
    {
    }

    // Properties
    public static Brush AliceBlue
    {
        get
        {
            Brush brush = (Brush) SafeNativeMethods.Gdip.ThreadData[AliceBlueKey];
            if (brush == null)
            {
                brush = new SolidBrush(Color.AliceBlue);
                SafeNativeMethods.Gdip.ThreadData[AliceBlueKey] = brush;
            }
            return brush;
        }
    }
}

SafeNativeMethods对我来说似乎无法访问。假设我刚刚在静态方法中返回了一个SolidBrush,是否会使所有内容都正确处理? (以及如何测试?)

public sealed class GrayScaleBrushes
{
    private static SolidBrush pct05 = null;

    public static SolidBrush Pct05
    {
        get
        {
            if (pct05 == null)
            {
                int rgbVal = GetRgbValFromPct( 5 );
                pct05 = new SolidBrush(Color.FromArgb(rgbVal, rgbVal, rgbVal));
            }
            return pct05;
        }
    }

    private static int GetRgbValFromPct(int pct)
    {
        return 255 - (int)(((float)pct / 100f) * 255f);
    }
}

3 个答案:

答案 0 :(得分:1)

Brushes类是静态的只能泄漏与定义的颜色数相对应的少量资源,所以只需在应用程序退出时清除这些资源。相反,我们要确保除非引用它们,否则确保不会实际创建画笔。这将加速启动并确保未使用的颜色不会消耗资源。

答案 1 :(得分:1)

在这种情况下,SafeNativeMethods只是一个包含画笔副本的简单缓存。因此,对属性getter的第二次调用将不会创建新实例。相反,它将始终返回相同的画笔。

要完成此任务,您可以重写您的功能,如下所示:

public static class GrayScaleBrushes
{
    private static SolidBrush _Pct05;

    public static SolidBrush Pct05
    {
        get
        {
            if (_Pct05 == null)
            {
                var value = GetRgbValFromPct(5);
                _Pct05 = new SolidBrush(Color.FromArgb(value, value, value));
            }

            return _Pct05;
        }
    }

    private static int GetRgbValFromPct(int pct)
    {
        // no need to convert to float and back to int again
        return 255 - ((pct * 255) / 100);
    }
}

此解决方案将根据需要创建灰度,但每次调用时都会检查null的成本。您可以通过采用以下方法再次更改内存问题来完成此速度问题

public static class GrayScaleBrushes
{
    public static readonly SolidBrush Pct05;

    static GrayScaleBrushes()
    {
        var value = GetRgbValFromPct(5);
        Pct05 = new SolidBrush(Color.FromArgb(value, value, value));
    }
}

但我认为在这种情况下,它只是一种品味,原因,速度和记忆都不会成为两个案例中的真正问题。

答案 2 :(得分:1)

我会推荐以下内容:

创建一个静态类GrayScaleBrushes

创建一个以强度百分比(int)为键的静态字典

创建一个静态的索引属性“Pct”,你可以像GrayScaleBrushes.Pct [10]一样使用它来返回字典条目。

现在你可以像Oliver所说的那样做,并在调用时动态创建字典条目,或者你可以使用静态构造函数循环遍历20个条目并将它们添加到字典中。

这种方法可以让您免于创建和维护20多个属性。欢呼声。