匹配十六进制值与SQLite查询像JavaScript


Matching Hex Values with SQLite Query like JavaScript

我使用一个javascript,命名一个近似/确切的颜色取决于它给出的十六进制值。这工作得很好,我试图创建一个类似的东西,除了使用SQLite查询。

问题是SQLite查询的结果与我使用javascript得到的结果不同。我没有足够的javascript经验,不知道还有什么其他匹配发生,以获得正确的近似颜色。

例如我有颜色:

["000000", "Black"],
["000080", "Navy Blue"],
["0000C8", "Dark Blue"],
["0000FF", "Blue"],
["000741", "Stratos"],
["011635", "Midnight"],
["011D13", "Holly"],
["0FFFFF", "Aqua Blue"],
["1E1609", "Karaka"],
["1E1708", "El Paso"],
["1E385B", "Cello"],
["1E433C", "Te Papa Green"],
["1E90FF", "Dodger Blue"],
["27504B", "Plantation"],
["FFFFF0", "Ivory"],
["FFFFFF", "White"]

使用#09F7FF作为输入,我使用这个查询:

SELECT * FROM colors WHERE "Hex" >= '#0F97FF' ORDER BY "ROWID" COLLATE NOCASE ASC LIMIT 1

返回的颜色应该是#1E90FF, Dodger Blue像javascript一样,但我得到#1E1609 Karaka,这是不正确的。是否有人能够解释我需要做什么才能获得与javascript相同的结果?

var ntc = {
  init: function() {
    var color, rgb, hsl;
    for(var i = 0; i < ntc.names.length; i++)
    {
      color = "#" + ntc.names[i][0];
      rgb = ntc.rgb(color);
      hsl = ntc.hsl(color);
      ntc.names[i].push(rgb[0], rgb[1], rgb[2], hsl[0], hsl[1], hsl[2]);
    }
  },
  name: function(color) {
    color = color.toUpperCase();
    if(color.length < 3 || color.length > 7)
      return ["#000000", "Invalid Color: " + color, false];
    if(color.length % 3 == 0)
      color = "#" + color;
    if(color.length == 4)
      color = "#" + color.substr(1, 1) + color.substr(1, 1) + color.substr(2, 1) + color.substr(2, 1) + color.substr(3, 1) + color.substr(3, 1);
    var rgb = ntc.rgb(color);
    var r = rgb[0], g = rgb[1], b = rgb[2];
    var hsl = ntc.hsl(color);
    var h = hsl[0], s = hsl[1], l = hsl[2];
    var ndf1 = 0; ndf2 = 0; ndf = 0;
    var cl = -1, df = -1;
    for(var i = 0; i < ntc.names.length; i++)
    {
      if(color == "#" + ntc.names[i][0])
        return ["#" + ntc.names[i][0], ntc.names[i][1], true];
      ndf1 = Math.pow(r - ntc.names[i][2], 2) + Math.pow(g - ntc.names[i][3], 2) + Math.pow(b - ntc.names[i][4], 2);
      ndf2 = Math.pow(h - ntc.names[i][5], 2) + Math.pow(s - ntc.names[i][6], 2) + Math.pow(l - ntc.names[i][7], 2);
      ndf = ndf1 + ndf2 * 2;
      if(df < 0 || df > ndf)
      {
        df = ndf;
        cl = i;
      }
    }
    return (cl < 0 ? ["#000000", "Invalid Color: " + color, false] : ["#" + ntc.names[cl][0], ntc.names[cl][1], false]);
  },
  // adopted from: Farbtastic 1.2
  // http://acko.net/dev/farbtastic
  hsl: function (color) {
    var rgb = [parseInt('0x' + color.substring(1, 3)) / 255, parseInt('0x' + color.substring(3, 5)) / 255, parseInt('0x' + color.substring(5, 7)) / 255];
    var min, max, delta, h, s, l;
    var r = rgb[0], g = rgb[1], b = rgb[2];
    min = Math.min(r, Math.min(g, b));
    max = Math.max(r, Math.max(g, b));
    delta = max - min;
    l = (min + max) / 2;
    s = 0;
    if(l > 0 && l < 1)
      s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
    h = 0;
    if(delta > 0)
    {
      if (max == r && max != g) h += (g - b) / delta;
      if (max == g && max != b) h += (2 + (b - r) / delta);
      if (max == b && max != r) h += (4 + (r - g) / delta);
      h /= 6;
    }
    return [parseInt(h * 255), parseInt(s * 255), parseInt(l * 255)];
  },
  // adopted from: Farbtastic 1.2
  // http://acko.net/dev/farbtastic
  rgb: function(color) {
    return [parseInt('0x' + color.substring(1, 3)), parseInt('0x' + color.substring(3, 5)),  parseInt('0x' + color.substring(5, 7))];
  },
  names: [
["000000", "Black"],
["000080", "Navy Blue"],
["0000C8", "Dark Blue"],
["0000FF", "Blue"],
["000741", "Stratos"],
["011635", "Midnight"],
["011D13", "Holly"],
["0FFFFF", "Aqua Blue"],
["1E1609", "Karaka"],
["1E1708", "El Paso"],
["1E385B", "Cello"],
["1E433C", "Te Papa Green"],
["1E90FF", "Dodger Blue"],
["27504B", "Plantation"],
["FFFFF0", "Ivory"],
["FFFFFF", "White"]
]
}
ntc.init();
var n_match  = ntc.name("#0F97FF");
n_rgb        = n_match[0]; // RGB value of closest match
n_name       = n_match[1]; // Text string: Color name
n_exactmatch = n_match[2]; // True if exact color match
alert(n_match);

javascript来自:http://chir.ag/projects/name-that-color/#7996C8

我的SQLite代码可以在这里找到:http://sqlfiddle.com/#!5/9eb07/21

您正在使用TEXT作为十六进制值的数据类型,但正确的十六进制数据格式应该在sqlite中开始0x,而不是#和:

"包含十六进制整数格式文本的字符串变量在由于CAST表达式、列关联转换、执行数值操作之前或任何其他运行时转换而将字符串值强制转换为整数时不会被解释为十六进制整数。源

编辑您的sqlite示例以返回更多行,显示HEX字段的前导0字符被忽略(并且不显示)-因此Aqua Blue #0FFFFF显示为#FFFFF,这可能不是您想要的。Karaka是按ROWID升序排序时发现的第一个结果。

如果您的数据库包含相当多的冗余数据,则可以通过比较颜色的十进制值,轻松地使用Int字段来进行比较。

将查询更改为从颜色代码的十进制值开始工作,并按十进制值(不是十六进制)排序。对于这个查询,我已经将示例中给出的十六进制值手动转换为十进制。此解决方案将避免将HEX字段转换为sqlite-

所需的x'格式。
SELECT * FROM colors WHERE "Int" >= '1021951' ORDER BY "Int" COLLATE NOCASE ASC LIMIT 

如果你改变你的数据sqlite比较应该工作-只要你排序的颜色值(HEX或Int)而不是ROWID。

这个关于hex()函数及其相反的答案可能会有所帮助。

您确实应该考虑规范化数据库,因为这将大大减少错误的机会。HEX字段可以很容易地通过连接R、G和B字段来显示。本质上,你有5个可以表示为单个字段的字段。