JavaScript/NodeJS和Electron中的图像DPI?

JavaScript/NodeJS和Electron中的图像DPI?,javascript,node.js,image,electron,Javascript,Node.js,Image,Electron,我正在构建一个主要用于Mac OS X的应用程序。用户可以在页面上放置一个图像,该页面创建一个带有放置图像源路径的,用户可以看到该图像 问题 如果用户在视网膜显示器上截图,然后将图像放到页面上,图像显示的大小将是原来的两倍。我需要知道如何以自然尺寸的一半来显示这个图像 可能的解决方案 如果我检查图像的DPI,我相信我应该能够可靠地判断图像是否为视网膜。在Mac上的预览应用程序中,我可以看到图像是144 DPI。基本上,如果DPI是144或更大,那么它就是视网膜,对吗 在给定图像的情况下,是否有某

我正在构建一个主要用于Mac OS X的应用程序。用户可以在页面上放置一个图像,该页面创建一个带有放置图像源路径的
,用户可以看到该图像

问题 如果用户在视网膜显示器上截图,然后将图像放到页面上,图像显示的大小将是原来的两倍。我需要知道如何以自然尺寸的一半来显示这个图像

可能的解决方案 如果我检查图像的DPI,我相信我应该能够可靠地判断图像是否为视网膜。在Mac上的预览应用程序中,我可以看到图像是144 DPI。基本上,如果DPI是144或更大,那么它就是视网膜,对吗

在给定图像的情况下,是否有某种方法可以使用Electron或NodeJ读取这些数据

注意:Mac OS X将屏幕截图作为PNG,因此没有exif数据

编辑和更新:我相信我可以通过查看十六进制信息来判断图像的DPI。例如,
fs.readFileSync('file.type').toString('hex')
,然后对于PNG,如前所述查找
70485973
,对于JPG,如前所述查找
FFD8FFE0000104A464946000101
。我现在遇到的问题是,当从剪贴板粘贴图像时,尝试使用Electron的NativeImage

如果我从剪贴板粘贴PNG,并执行
nativeImage.toPng().toString('hex')
,则会输出以下内容:

我在这个字符串的哪里可以找到DPI信息

编辑和更新2:我想知道这是否是Electron内部的一个bug。当我从预览中复制144 PPI的图像并将其粘贴到我的应用程序中,然后将其从我的应用程序中复制并粘贴到新的预览窗口中时,它将更改为72 PPI。有没有可能电子被剥离掉了这个信息

根据@robertklep的请求,这里是区块的屏幕截图(对不起,我在我的应用程序中覆盖了副本,所以我现在无法实际复制文本)

初始图像

复制/粘贴后
您显示的输出看起来是原始PNG数据(PNG签名是
0x89、0x50、0x4E、0x47、0x0D、0x0A、0x1A、0x0A

您可以解析数据中的不同块并查找块,这是(我认为)您需要从Mac OS X生成的PNG中提取分辨率信息的块

处理所有PNG块的简单解析器:

89504e470d0a1a0a0000000d49484452000001fc000001680806000000b2a54946000005c249444154789cedd5410dc03010c0b0ae448f3f8a0dc554a9b111e4976766de05005c6d9f0e0000fe67f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f80010f0014a0204ec5f3e63f20000000049454e44ae426082
var image=nativeImage.toPng();//或fs.readFile*()的结果
函数*解析块(数据){
var offset=8;//跳过PNG头
while(偏移量<数据长度){
var dataLength=data.readUInt32BE(偏移量);
var chunkLength=dataLength+12;
var typeStart=偏移量+4;
var dataStart=offset+8;
var dataEnd=偏移量+8+数据长度;
var crcEnd=dataEnd+4;
屈服{
类型:data.toString('ascii',typeStart,dataStart),
data:data.slice(dataStart,dataEnd),
crc:data.slice(数据端,crcEnd),
};
偏移量=crcEnd;
}
}
for(让块解析块(图像)){
//提取像素信息
if(chunk.type=='pHYs'){
var ppuX=chunk.data.readUInt32BE(0);
var ppuY=chunk.data.readUInt32BE(4);
var unit=chunk.data.readUInt8(8);//应始终为'1`
console.log('PPI',数学圆(ppuX*0.0254));
}
}

这在我的Mac电脑上输出了
PPI 144

你能提供一些样本图像吗?在Mac电脑上拍摄的任何屏幕截图都可以达到这一目的。我们并非都坐在Mac电脑上:)这实际上影响到所有的剪贴板,至少在Mac电脑上是如此。这不是一个关于Electron的bug,也不是任何可以解决的问题。谢谢你的回答,但请看我更新的问题。从剪贴板中读取图像时,是否有办法获得此信息?看起来复制的图像没有得到这些数据。因为这是我能得到的最接近的数据,而且它确实回答了原始问题,所以如果在赏金用完之前没有更好的答案,我会给你正确的答案,并奖励你赏金。@atdrago你能在粘贴的数据中发布一个区块列表吗?您可以重用我发布的代码,只需记录每个
块。键入
。或者,如果可能的话,你能将粘贴的图像写入文件并发布到某个地方,这样我就可以看一看了吗?@atdrago我相信Mac OS X剪贴板使用TIFF格式存储图像数据,这意味着PNG会转换为TIFF,一旦粘贴到Electron,就会再次转换为PNG。在这些转换过程中,元数据(如
pHYs
块)可能会丢失,最终导致图像大小加倍。我认为没有办法解决这个问题:-(遗憾的是,我认为你是对的。它似乎与电子没有任何关系。你可以通过截图、在预览中打开、Command+C、Command+N轻松地在预览中复制它。新图像将丢失DPI数据。
var image = nativeImage.toPng(); // or the result of fs.readFile*()

function* parseChunks(data) {
  var offset = 8; // skip PNG header

  while (offset < data.length) {
    var dataLength  = data.readUInt32BE(offset);
    var chunkLength = dataLength + 12;
    var typeStart   = offset + 4;
    var dataStart   = offset + 8;
    var dataEnd     = offset + 8 + dataLength;
    var crcEnd      = dataEnd + 4;

    yield {
      type : data.toString('ascii', typeStart, dataStart),
      data : data.slice(dataStart, dataEnd),
      crc  : data.slice(dataEnd, crcEnd),
    };

    offset = crcEnd;
  }
}

for (let chunk of parseChunks(image)) {
  // Extract pixel information
  if (chunk.type === 'pHYs') {
    var ppuX = chunk.data.readUInt32BE(0);
    var ppuY = chunk.data.readUInt32BE(4);
    var unit = chunk.data.readUInt8(8); // should always be `1`
    console.log('PPI', Math.round(ppuX * 0.0254));
  }
}