当前位置: 首页 > 知识库问答 >
问题:

我如何实现这个“色差”算法?

夏新翰
2023-03-14

作为这个问题的后续:(如何在位图上绘制清晰的文本(Winforms)?),我通过计算文本下面的“平均”颜色,并为文本选择适当的对比色,在位图上绘制清晰但很小的文本。

我从https://stackoverflow.com/A/6185448/3784949偷了Till的代码,用于计算“平均”bmp颜色。现在我来看看http://www.w3.org/tr/aert#color-carrist建议的“色差”算法。

颜色亮度由以下公式确定:

((红色值x299)+(绿色值x587)+(蓝色值x114))/1000

色差由以下公式确定:

编辑:具体来说,我的困惑就在这里:

>

  • 看起来我需要添加三个单独的值(R,G,B)来实现两个不同的目标(新的RGB加起来是原始的加125,新的RGB加起来是原始的加500

    看起来我可能需要“加权”我增加的亮度值,以增加G比R比B更多。

    private Color GetContrastingFontColor(Color AverageColorOfBitmap,
                                          List<Color> FavoriteColors)
    {
        IEnumerable<Color> AcceptableColors =
            (IEnumerable<Color>)FavoriteColors.Where(clr =>
            (GetColorDifferenceAboveTarget(AverageColorOfBitmap, clr, (float)200) > 0)
            && (GetBrightnessAboveTarget(AverageColorOfBitmap, clr, (float).125) > 0))
            .OrderBy(clr => GetColorDifferenceAboveTarget(
                                AverageColorOfBitmap, clr, (float)200));
        return AcceptableColors.DefaultIfEmpty(Color.Aqua).First();
    }
    

    这是一个很好的框架,但我需要努力从名单中选择“最好”的候选人。现在它只是返回“符合亮度标准的最大色差的合格颜色”。然而,这允许我修改浮动值(W3的“500色差要求”完全是废话,零知道颜色合格)和实验。

    支持代码:

    private float GetBrightnessAboveTarget(Color AverageColorOfBitmap, 
                                           Color proposed, float desiredDifference)
    {
        float result = proposed.GetBrightness() - AverageColorOfBitmap.GetBrightness();
        return result - desiredDifference;
    }
    
    private float GetColorDifferenceAboveTarget(Color avg, Color proposed,
                                                float desiredDifference)
    {
        float r1 = Convert.ToSingle(MaxByte(Color.Red, avg, proposed));
        float r2 = Convert.ToSingle(MinByte(Color.Red, avg, proposed));
        float r3 = Convert.ToSingle(MaxByte(Color.Green, avg, proposed));
        float r4 = Convert.ToSingle(MinByte(Color.Green, avg, proposed));
        float r5 = Convert.ToSingle(MaxByte(Color.Blue, avg, proposed));
        float r6 = Convert.ToSingle(MinByte(Color.Blue, avg, proposed));
    
        float result = (r1 - r2) + (r3 - r4) + (r5 - r6);
        return result - desiredDifference;
    }
    
    private byte MaxByte(Color rgb, Color x, Color y)
    {
        if (rgb == Color.Red) return (x.R >= y.R) ? x.R : y.R;
        if (rgb == Color.Green) return (x.G >= y.G) ? x.G : y.G;
        if (rgb == Color.Blue) return (x.B >= y.B) ? x.B : y.B;
        return byte.MinValue;
    }
    
    private byte MinByte(Color rgb, Color x, Color y)
    {
        if (rgb == Color.Red) return (x.R <= y.R) ? x.R : y.R;
        if (rgb == Color.Green) return (x.G <= y.G) ? x.G : y.G;
        if (rgb == Color.Blue) return (x.B <= y.B) ? x.B : y.B;
        return byte.MinValue;
    }
    
  • 共有1个答案

    白信鸿
    2023-03-14

    这更多的是对原问题的回答。我称之为自制大纲。

    使用透明度加上你能得到的最大和最小亮度(白色和黑色),它创造了很好的对比度,至少在我的屏幕上看起来很好。

    它是阴影和透明的混合体。我已经从红色成分中减去了一点,得到了你想要的水剂…

    此外,您可能应该在黑色阴影上的白色和白色高光上的黑色之间切换,这取决于您打印的斑点的亮度。但是有了这个自制的轮廓,它真的可以在黑暗和明亮的背景下工作,只是在明亮的背景下看起来不那么优雅。

    using (Graphics G = Graphics.FromImage(pictureBox1.Image) )
    {
      Font F = new Font("Arial", 8);
      SolidBrush brush0 = new SolidBrush(Color.FromArgb(150, 0, 0, 0))
      SolidBrush brush1 = new SolidBrush(Color.FromArgb(200, 255, 255, 222))
    
      G.DrawString(textBox1.Text, F, brush0 , new Point(x-1, y-1));
      G.DrawString(textBox1.Text, F, brush0 , new Point(x+1, y+1));
      G.DrawString(textBox1.Text, F, brush1, new Point(x, y));
    }
    

    编辑:这是从按钮单击调用的,但实际上应该在油漆事件中。在这里,Graphics对象及其使用块G将被E.Graphics事件参数替换。

    我注意到您使用“透明”标签来显示数据,以避免graphics.DrawString和Paint事件的细节。

    string theText ="123 - The quick brown fox..";
    Label L1, L2, L3;
    
    pictureBox1.Controls.Add(new trLabel());
    L1 = (trLabel)pictureBox1.Controls[pictureBox1.Controls.Count - 1];
    L1.Text = theText;
    L1.ForeColor = Color.FromArgb(150, 0, 0, 0);
    L1.Location = new Point(231, 31);  // <- position in the image, change!
    
    L1.Controls.Add(new trLabel());
    L2 = (trLabel)L1.Controls[pictureBox1.Controls.Count - 1];
    L2.Text = theText;
    L2.ForeColor = Color.FromArgb(150, 0, 0, 0);
    L2.Location = new Point(2, 2);  // do not change relative postion in the 1st label!
    
    L2.Controls.Add(new trLabel());
    L3 = (trLabel)L2.Controls[pictureBox1.Controls.Count - 1];
    L3.Text = theText;
    L3.ForeColor = Color.FromArgb(200, 255, 255, 234);
    L3.Location = new Point(-1,-1);  // do not change relative postion in the 2nd label!
    
    public partial class trLabel : Label
    {
        public trLabel()
        {
            SetStyle(ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
            BackColor = Color.Transparent;
            Visible = true;
            AutoSize = true;
        }
    }
    

    所以抽绳的解决方案并不复杂。它还允许您扭曲Graphics对象的几个属性,如Smoothingmode、TextContrant或InterpolationMode

     类似资料:
    • 我在Gradle控制台得到这个错误 错误:配置根项目“QuakeReport”时出现问题。 无法解析配置“:classpath”的所有文件。找不到com.android.tools.build:gradle:3.0.0。在以下位置搜索:文件:/applications/Android Studio.app/contents/gradle/m2repository/com/android/tools

    • 我想创建一个食谱网站,在那里你可以添加/修改/删除食谱,每个模型都应该有一个配料的列表,与所需的量的那个配料。 我试图使用这样的dict:,但结果是EF Core并不真正喜欢dicts的思想,所以我试图创建一个“映射器”模型,如下所示: 问题是,它仍然没有真正起作用。我不能添加菜谱,也不能删除,因为它进入了一个永远循环。 你将如何实施它? 谢谢

    • 要求是这样的(目前的话换行单选多选判断换行展示已经处理完了): 但是现在有个问题就是选项的个数问题,选项最多是9个(也就是从A~I),最少是3~4个(判断的选项就是两个,但是若遇到判断就换行了,倒是不用太操心),选项个数不固定每题的宽度就不固定,宽度不固定列数就不固定,列数有影响到了行数,但又要求每列得对齐。 大致就是: 1.选项个数不固定 2.支持横排、竖排的切换 3.每列得对齐 所以想问问各位

    • 本文向大家介绍oralce 计算时间差的实现,包括了oralce 计算时间差的实现的使用技巧和注意事项,需要的朋友参考一下 oralce 计算时间差的实现 查询系统时间和给定时间相差的毫秒数 将account表中第一条数据的dcur_state_start_date(timestamp类型)字段值的相差豪秒数算出来 备注 *24(小时) *60(分) *60(秒) *1000(毫秒) 感谢阅读,希

    • 在我的MergeSort程序的这一部分中,我递归地划分一个名为“arr”的未排序数组。为此,我创建了两个子数组,“leftArr”和“rightArr”,然后我分别用“arr”的前半部分和“arr”的后半部分填充“leftArr”和和“right arr”。然后,我将使用递归来划分/排序leftArr和rightArr。 只是想澄清一下:中=长度; 要初始化rightArr,我执行以下操作: 当我

    • 如图所示,可以用纯css3来实现吗