【问题标题】:How do you compare two images in javascript correctly?如何正确比较 javascript 中的两个图像?
【发布时间】:2018-12-10 04:25:28
【问题描述】:

我在 Tampermonkey(在 Google Chrome 中)中使用 javascript,如果它们相同/非常相似,我喜欢比较两个图像。

我认为我可以通过使用画布元素并比较生成的字符串来做到这一点,但无论我选择什么图像,我总是认为它们是相同的......:/

所以比较似乎不起作用,我不知道为什么?

修改 1:添加了一个计时器来等待图像加载 /

/ ==UserScript==
// @name         ImageCompare
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        *://*/*
// @match        www*
// @grant        none
// ==/UserScript==

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

function getBase64Image(img) {
    // Create an empty canvas element
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;

    // Copy the image contents to the canvas
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

    // Get the data-URL formatted image
    // Firefox supports PNG and JPEG. You could check img.src to
    // guess the original format, but be aware the using "image/jpg"
    // will re-encode the image.
    var dataURL = canvas.toDataURL("image/png");

    return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}

var x = new Image();
var y = new Image();
var url_x = "https://cdn0.tnwcdn.com/wp-content/blogs.dir/1/files/2010/03/google_logo.jpg";
var url_y = "https://nairobigarage.com/2017/wp-content/uploads/2015/02/6_logo_predesign.jpg";
x.src = 'chrome://favicon/' + url_x;
y.src = 'chrome://favicon/' + url_y;

var x_base64 = getBase64Image(x);
var y_base64 = getBase64Image(y);

sleep(5000).then(() => {
    if (x_base64 === y_base64)
    {
        alert("identical");
    }
    else
    {
       alert("not identical");
    }
});

【问题讨论】:

  • 您必须等待图片加载,您目前没有这样做
  • @PatrickEvans 我不确定我是否正确,但我现在添加了 5 秒的延迟,它仍然一直在说“相同”:(
  • 您延迟了比较,而不是等待图像加载。
  • 不要添加延迟。在每张图片上添加loadevent listener
  • @cnmesr 如果 页面 已加载,则不会;加载每个 image 后执行代码。提示:x.addEventListener("load", ); y.addEventListener("load", );,尽管您需要一种方法来确保两个都已加载。

标签: javascript image google-chrome url


【解决方案1】:

您需要等待图片加载完毕,您可以使用onload event在图片加载完毕时通知您

var img = new Image();
img.onload = ()=>{
  //do work
};

所以:

function getBase64Image(img) {
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;

    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

    var dataURL = canvas.toDataURL("image/png");
    return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}

var x = new Image();
var y = new Image();
var url_x = "https://cdn0.tnwcdn.com/wp-content/blogs.dir/1/files/2010/03/google_logo.jpg";
var url_y = "https://nairobigarage.com/2017/wp-content/uploads/2015/02/6_logo_predesign.jpg";
x.src = 'chrome://favicon/' + url_x;
y.src = 'chrome://favicon/' + url_y;

//make the load events into promises
var xPromise = new Promise((resolve)=>{
   x.onload = resolve;
});
var yPromise = new Promise((resolve)=>{
   y.onload = resolve;
});
Promise.all([xPromise,yPromise]).then(()=>{
  var x_base64 = getBase64Image(x);
  var y_base64 = getBase64Image(y);
  if(x_base64 == y_base64){
    //match
  } else {
    //no match
  }
});

请注意,虽然您尝试从chrome:// 协议加载资源,但由于安全限制,您实际上无法获取跨源资源的数据。从您的页面正在运行的同一域加载资源,或使用文件输入来获取图像。

【讨论】:

  • 非常感谢,这对我有用!我只有你最后提到的问题,我需要使用来自同一个域的资源,但我喜欢比较来自两个不同域的两个图像。 “使用文件输入获取图像”是什么意思?
  • @cnmesr 我的意思是<input type="file">,用户可以从他们自己的系统中选择一个文件。您也可以使用代理服务器,即向服务器上的某个脚本发出请求,然后该脚本将获取实际图像并返回该图像,但这不适用于chrome:// url。
猜你喜欢
  • 2011-08-29
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多