简体   繁体   English

JavaScript/NodeJS 和 Electron 中的图像 DPI?

[英]Image DPI in JavaScript/NodeJS and Electron?

I'm building an application using Electron primarily for Mac OS X. The user can drop an image onto the page, the page creates an <img> with the source path of the dropped image, and the user sees the image.我正在使用Electron构建一个主要用于 Mac OS X 的应用程序。用户可以将图像拖放到页面上,页面创建一个<img>以及拖放图像的源路径,然后用户可以看到该图像。

Problem 问题

If the user takes a screenshot on a retina display and then drops the image onto the page, the image displays at double the size.如果用户在 Retina 显示屏上截取屏幕截图,然后将图像拖放到页面上,则图像会以双倍大小显示。 I need to somehow know to display this image at half its natural dimensions.我需要以某种方式知道以其自然尺寸的一半显示此图像。

Possible Solution 可能的解决方案

I believe I should be able to reliably tell if the image is retina if I check its DPI.我相信如果我检查它的 DPI,我应该能够可靠地判断图像是否是视网膜图像。 In the Preview app on the Mac I can see that the image is 144 DPI.在 Mac 上的预览应用程序中,我可以看到图像是 144 DPI。 Essentially, if the DPI is 144 or greater, then it's retina, right?本质上,如果 DPI 为 144 或更高,那么它就是视网膜,对吧?

Is there some way to read this data, given the image, using either Electron's Native Image or NodeJS?有没有什么方法可以使用 Electron 的原生图像或 NodeJS 来读取给定图像的数据?

Note: Mac OS X takes screenshots as PNGs, so there is no exif data.注意: Mac OS X 以 PNG 格式截屏,因此没有 exif 数据。

Edit and Update : I believe I can tell what the image's DPI is from looking at the HEX information.编辑和更新:我相信我可以通过查看 HEX 信息来判断图像的 DPI。 Ie, fs.readFileSync('file.type').toString('hex') , then for PNGs look for 70 48 59 73 , as mentioned here , or for JPGs look for FFD8FFE000104A464946000101 as mentioned here .即, fs.readFileSync('file.type').toString('hex') ,然后对于 PNG 文件查找70 48 59 73 ,如此所述,或者对于 JPG 文件查找FFD8FFE000104A464946000101 ,如此所述。 The problem I'm having now is when trying to work with Electron's NativeImage when an image is pasted from the clipboard.我现在遇到的问题是当从剪贴板粘贴图像时尝试使用 Electron 的 NativeImage。

If I paste a PNG from the clipboard, and do nativeImage.toPng().toString('hex') , the following is output:如果我从剪贴板粘贴 PNG 并执行nativeImage.toPng().toString('hex') ,则以下是 output:

89504e470d0a1a0a0000000d49484452000001fc000001680806000000b2a54946000005c249444154789cedd5410dc03010c0b0ae448f3f8a0dc554a9b111e4976766de05005c6d9f0e0000fe67f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f8001060f80010f0014a0204ec5f3e63f20000000049454e44ae426082

Where in this string would I find the DPI information?在此字符串中的何处可以找到 DPI 信息?

Edit and Update 2: I'm wondering if this could be a bug within Electron. When I copy an image that is 144 PPI from Preview and paste it into my app, then copy it out of my app and paste it into a new Preview window, it changes to 72 PPI.编辑和更新 2:我想知道这是否可能是 Electron 中的错误。当我从预览中复制 144 PPI 的图像并将其粘贴到我的应用程序中时,然后将其复制出我的应用程序并将其粘贴到新的预览中window,变为72 PPI。 Is it possible that Electron is stripped out this information? Electron 有没有可能被去掉这个信息?

预览 DPI

Chunks大块

Requested by @robertklep, here are screenshots of the chunks (sorry, I override the Copy in my app so I can't actually copy text right now).由@robertklep 请求,这里是块的屏幕截图(抱歉,我在我的应用程序中覆盖了复制,所以我现在不能实际复制文本)。

Initial Image初始图像最初的

After copied/pasted复制/粘贴后复制后

The output you're showing looks to be the raw PNG data (the PNG signature is 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A ).您显示的 output 看起来是原始 PNG 数据(PNG 签名是0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A )。

You can parse the different chunks in the data and look for the pHYs chunk, which is (I think) the chunk you need to extract resolution information from for Mac OS X-generated PNG's.您可以解析数据中的不同块并查找pHYs块,这是(我认为)您需要从 Mac OS X 生成的 PNG 中提取分辨率信息的块。

A simple parser which processes all PNG chunks:一个处理所有 PNG 块的简单解析器:

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));
  }
}

This outputs PPI 144 on my Mac, as expected.正如预期的那样,这会在我的 Mac 上输出PPI 144

I found that you can access raw PNG clipboard data for screenshot via clipboard.readBuffer("public.png") now.我发现您现在可以通过clipboard.readBuffer("public.png")访问原始 PNG 剪贴板数据以获取屏幕截图。 See https://ocadaruma.hatenablog.com/entry/2023/01/29/091354 for the details how it works.有关其工作原理的详细信息,请参阅https://ocadaruma.hatenablog.com/entry/2023/01/29/091354

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM