Javascript 为什么canvas.toDataURL()不能为图像生成与Ruby中相同的base64?

Javascript 为什么canvas.toDataURL()不能为图像生成与Ruby中相同的base64?,javascript,image,canvas,md5,Javascript,Image,Canvas,Md5,我试图用JavaScript和Ruby为图像文件生成相同的base64数据。不幸的是,两者都输出两个非常不同的值 在Ruby中,我这样做: Base64.encode64(File.binread('test.png')); 然后在JavaScript中: var image = new Image(); image.src = 'http://localhost:8000/test.png'; $(image).load(function() { var canvas, conte

我试图用JavaScript和Ruby为图像文件生成相同的base64数据。不幸的是,两者都输出两个非常不同的值

在Ruby中,我这样做:

Base64.encode64(File.binread('test.png'));
然后在JavaScript中:

var image = new Image();
image.src = 'http://localhost:8000/test.png';

$(image).load(function() {
    var canvas, context, base64ImageData;

    canvas = document.createElement('canvas');
    context = canvas.getContext('2d');
    canvas.width = this.width;
    canvas.height = this.height;
    context.drawImage(this, 0, 0);
    imageData = canvas.toDataURL('image/png').replace(/data:image\/[a-z]+;base64,/, '');

    console.log(imageData);
});

知道这些输出为何不同吗?

保存画布时,浏览器正在重新编码图像


它不会生成与您渲染的文件相同的编码。

在Ruby中加载图像时,未经任何修改的二进制文件将直接编码到base-64

在浏览器中加载图像时,它将对图像应用一些处理,然后才能将其与画布一起使用:

  • 将应用ICC配置文件(如果图像文件包含该配置文件)
  • 伽马校正(如有支持)
当您将图像绘制到画布时,位图值已经更改,并且不一定与加载为图像之前编码的位图相同(如果文件中有alpha通道,这可能会影响绘制到画布时的颜色值-此时画布有点奇怪..)

当颜色值改变时,画布中的结果字符串自然也会不同,甚至在重新编码位图之前(由于PNG的损耗较小,编码/压缩应相当相同,但也可能存在影响因素,具体取决于浏览器实现。要进行测试,请将黑色未处理画布另存为PNG,并与应用程序中的类似图像进行比较-所有值应为0,包括alpha,当然大小相同)

避免这种情况的唯一方法是直接处理二进制数据。这当然有点过分(至少在一般情况下)而且在浏览器中是一个相对缓慢的过程


在某些情况下,一个可行的解决方案是从图像文件中删除任何ICC配置文件。要从Photoshop中保存图像而不使用ICC,请选择“文件”菜单中的“为web保存…”。

所以我最终解决了这个问题

幸运的是,我正在使用imgcache.js使用文件系统API在本地文件系统中缓存图像。我的解决方案是使用此API(imgcache.js使其更容易)从文件的实际缓存副本中获取base64数据。代码如下所示:

var imageUrl = 'http://localhost:8000/test.png';

ImgCache.init(function() {
    ImgCache.cacheFile(imageUrl, function() {
        ImgCache.getCachedFile(imageUrl, function(url, fileEntry) {
            fileEntry.file(function(file) {
                var reader = new FileReader();
                reader.onloadend = function(e) {
                    console.log($.md5(this.result.replace(/data:image\/[a-z]+;base64,/, '')));
                };
                reader.readAsDataURL(file);
            });
        });
    });
});
而且,非常重要的是,我必须在Ruby中删除base64中的换行符:

Base64.encode64(File.binread('test.png')).gsub("\n", '');

图像在查看时看起来是一样的吗?是的,如果我用Ruby解码base64并将原始数据保存到PNG文件中,它看起来是一样的。有没有办法以某种方式获得相同的base64?对该URL发出AJAX请求,而不使用canvas。你知道哪里可能有这样的例子吗?@ChadJohnson:什么例子?如何制作AJAX请求?不,这是一个通过AJAX请求对图像进行哈希处理的示例,考虑到图像是二进制格式的。我发现了,但它不起作用,因为“单词”是空的。无论如何,我找到了一个替代解决方案。您根本不需要文件系统;您可以从AJAX响应中读取它。请参阅将此标记为答案,因为它回答了我的“为什么”问题;不过,我在这里的另一个答案中发布了一个解决方案。