【发布时间】:2014-09-01 11:21:09
【问题描述】:
在我正在编写的 WPF 用户控件中,我有 3 个滑块代表 RGB,其值从 0 到 255。标准的东西!还显示了一个色样
基类是
private class SwatchPixels
{
public Point P { get; set; }
public int X { get; set; }
public int Y { get; set; }
public int R { get; set; }
public int G { get; set; }
public int B { get; set; }
public int A { get; set; }
}
private List<SwatchPixels> _points = new List<SwatchPixels>();
现在我想做的是(我有一些工作但不够准确!)
使用色样中像素的所有 RGB 值加载列表,然后找到与所提供的一组 RGB 值最接近的像素颜色。然后我可以将一个椭圆移动到该像素的 x,y 位置。我想要这个的原因当然是色板通常不会包含所有 1600 万种颜色!
如果有人能提出更好的方法,我将不胜感激!
样本位于相同大小的画布对象中。
<Canvas Name="CanvasImage" Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" Width="150" Height="150"
HorizontalAlignment="Center" Background="Transparent" VerticalAlignment="Top" Margin="2"
MouseMove="CanvasImage_MouseMove" MouseDown="CanvasImage_MouseDown" MouseUp="CanvasImage_MouseUp">
<Ellipse Name="EllipsePixel" Width="8" Height="8" Stroke="Black" Fill="White"
Canvas.Left="0" Canvas.Top="0"/>
</Canvas>
加载所有像素值的方法
private List<SwatchPixels> FindAllPixelLocations()
{
// http://stackoverflow.com/questions/1176910/finding-specific-pixel-colors-of-a-bitmapimage
var img = new BitmapImage(new Uri(@"Resources/Cws.png", UriKind.RelativeOrAbsolute));
Image Ti = new Image();
Ti.Source = img;
ImageSource ims = Ti.Source;
BitmapImage bitmapImage = (BitmapImage)ims;
try
{
int stride = bitmapImage.PixelWidth * 4;
int size = bitmapImage.PixelHeight * stride; // stride
pixels = new byte[size];
bitmapImage.CopyPixels(pixels, stride, 0);
for (int y = 0; y < bitmapImage.PixelHeight; y++)
{
for (int x = 0; x < bitmapImage.PixelWidth; x++)
{
int index = y * stride + 4 * x;
byte red = pixels[index];
byte green = pixels[index + 1];
byte blue = pixels[index + 2];
byte alpha = pixels[index + 3];
var swatchPixels = new SwatchPixels
{
X = x,
Y = y,
P = new Point(x, y),
R = red,
G = green,
B = blue,
A = alpha
};
_points.Add(swatchPixels);
}
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
return _points;
}
接下来是找点方法(我不满意的一点!)
private const int initVariance = 40;
private const int dropPercent = 5;
private SwatchPixels FindXy(string a, string r, string g, string b)
{
var iR = 0;
var iG = 0;
var iB = 0;
if (RgbDec.IsChecked == true)
{
iR = Convert.ToByte(r);
iG = Convert.ToByte(g);
iB = Convert.ToByte(b);
}
else
{
// Number in hex format so convert to dec first
iR = Convert.ToByte(int.Parse(r, NumberStyles.HexNumber));
iG = Convert.ToByte(int.Parse(g, NumberStyles.HexNumber));
iB = Convert.ToByte(int.Parse(b, NumberStyles.HexNumber));
}
List<SwatchPixels> closepoints = new List<SwatchPixels>();
List<SwatchPixels> prevCp = new List<SwatchPixels>(closepoints);
var v = Convert.ToInt32(initVariance);
foreach (var p in _points)
{
if ((iR >= p.R - v && iR <= p.R + v) &&
(iG >= p.G - v && iG <= p.G + v) &&
(iB >= p.B - v && iB <= p.B + v))
{
closepoints.Add(p);
}
}
var c = closepoints.Count;
while (c > 10)
{
v = v - (v * dropPercent / 100);
closepoints = LoopAgain(closepoints, v, iR, iG, iB);
c = closepoints.Count;
//Variance.Text += c.ToString() + Environment.NewLine;
if (c == 0)
{
closepoints = new List<SwatchPixels>(prevCp);
break;
}
else
{
prevCp = new List<SwatchPixels>(closepoints);
}
}
if (c > 1)
return closepoints[0];
return null;
}
private List<SwatchPixels> LoopAgain(IEnumerable<SwatchPixels> cpoints, int v, int iR, int iG, int iB)
{
var closepoints = new List<SwatchPixels>();
foreach (var p in cpoints)
{
if ((iR >= p.R - v && iR <= p.R + v) &&
(iG >= p.G - v && iG <= p.G + v) &&
(iB >= p.B - v && iB <= p.B + v))
{
closepoints.Add(p);
}
}
return closepoints;
}
这是我修改后的 ColorCanvas。 更改包括用于 RGB 的单个颜色矩形、将差异应用于所选颜色以及使用不同的颜色模型进行输入。您也可以一键将十六进制内容复制到剪贴板。
【问题讨论】: