如何在JavaScript中获取图像颜色模式(CMYK,RGB ..)



javaScript可以检查图像的颜色模式吗?

我对此做了很多搜索,但是我唯一看到的是颜色模式转换(但是转换的要您设置原始颜色模式)


我添加了此信息:--allow-file-access-from-files要完全控制Canvas BeaCause中的IMG,我正在使用GoogleChrome

html

<canvas id="canvas" width=6000 height=7919></canvas>

JS

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.crossOrigin = "anonymous";
img.onload = start;
img.src = "file:///D:/vincent-van-gogh-the-starry-night-picture-157544-2.png";

是 - 基本上JavaScript能够确定PNG的颜色模式,因此需要它才能1.将png转换为base642.将base64转换为字节数组3.阅读/解析有关PNG规范的数组

可能看起来像这样的方法:

var PNG = {
        parse: function(imgTag) {
            var base64 = PNG.asBase64(imgTag);
            var byteData = PNG.utils.base64StringToByteArray(base64);
            var parsedPngData = PNG.utils.parseBytes(byteData);
            return PNG.utils.enrichParsedData(parsedPngData);
        },
        asBase64: function(imgTag) {
            var canvas = document.createElement("canvas");
            canvas.width = imgTag.width; 
            canvas.height = imgTag.height; 
            var ctx = canvas.getContext("2d"); 
            ctx.drawImage(imgTag, 0, 0); 
            var dataURL = canvas.toDataURL("image/png");
            return dataURL.split('base64,')[1];
        },
        utils: {
            base64StringToByteArray: function(base64String) {
                //http://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript
                var byteCharacters = atob(base64String);
                var byteNumbers = new Array(byteCharacters.length);
                for (var i = 0; i < byteCharacters.length; i++) {
                    byteNumbers[i] = byteCharacters.charCodeAt(i);
                }
                return new Uint8Array(byteNumbers);
            },
            parseBytes: function(bytes) {
                var pngData = {};
                //see https://en.wikipedia.org/wiki/Portable_Network_Graphics
                //verify file header
                pngData['headerIsValid'] = bytes[0] == 0x89
                            && bytes[1] == 0x50
                            && bytes[2] == 0x4E
                            && bytes[3] == 0x47
                            && bytes[4] == 0x0D
                            && bytes[5] == 0x0A
                            && bytes[6] == 0x1A
                            && bytes[7] == 0x0A
                if (!pngData.headerIsValid) {
                    console.warn('Provided data does not belong to a png');
                    return pngData;
                }
                //parsing chunks
                var chunks = [];
                var chunk = PNG.utils.parseChunk(bytes, 8);
                chunks.push(chunk);
                while (chunk.name !== 'IEND') {
                    chunk = PNG.utils.parseChunk(bytes, chunk.end);
                    chunks.push(chunk);
                }
                pngData['chunks'] = chunks;
                return pngData;
            },
            parseChunk: function(bytes, start) {
                var chunkLength = PNG.utils.bytes2Int(bytes.slice(start, start + 4));
                var chunkName = '';
                chunkName += String.fromCharCode(bytes[start + 4]);
                chunkName += String.fromCharCode(bytes[start + 5]);
                chunkName += String.fromCharCode(bytes[start + 6]);
                chunkName += String.fromCharCode(bytes[start + 7]);
                var chunkData = [];
                for (var idx = start + 8; idx<chunkLength + start + 8; idx++) {
                    chunkData.push(bytes[idx]);
                }
                //TODO validate crc as required!
                return {
                    start: start,
                    end: Number(start) + Number(chunkLength) + 12, //12 = 4 (length) + 4 (name) + 4 (crc)
                    length: chunkLength,
                    name: chunkName,
                    data: chunkData,
                    crc: [
                        bytes[chunkLength + start + 8],
                        bytes[chunkLength + start + 9],
                        bytes[chunkLength + start + 10],
                        bytes[chunkLength + start + 11]
                    ],
                    crcChecked: false
                };
            },
            enrichParsedData: function(pngData) {
                var idhrChunk = PNG.utils.getChunk(pngData, 'IDHR');
                //see http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
                pngData.width = PNG.utils.bytes2Int(idhrChunk.data.slice(0, 4));
                pngData.height = PNG.utils.bytes2Int(idhrChunk.data.slice(4, 8));
                pngData.bitDepth = PNG.utils.bytes2Int(idhrChunk.data.slice(8, 9));
                pngData.colorType = PNG.utils.bytes2Int(idhrChunk.data.slice(9, 10));
                pngData.compressionMethod = PNG.utils.bytes2Int(idhrChunk.data.slice(10, 11));
                pngData.filterMethod = PNG.utils.bytes2Int(idhrChunk.data.slice(11, 12));
                pngData.interlaceMethod = PNG.utils.bytes2Int(idhrChunk.data.slice(12, 13));
                pngData.isGreyScale = pngData.colorType == 0 || pngData.colorType == 4;
                pngData.isRgb = pngData.colorType == 2 || pngData.colorType == 6;
                pngData.hasAlpha = pngData.colorType == 4 || pngData.colorType == 6;
                pngData.hasPaletteMode = pngData.colorType == 3 && PNG.utils.getChunk(pngData, 'PLTE') != null;
                return pngData;
            },
            getChunks: function(pngData, chunkName) {
                var chunksForName = [];
                for (var idx = 0; idx<pngData.chunks.length; idx++) {
                    if (pngData.chunks[idx].name = chunkName) {
                        chunksForName.push(pngData.chunks[idx]);
                    }
                }
                return chunksForName;
            },
            getChunk: function(pngData, chunkName) {
                for (var idx = 0; idx<pngData.chunks.length; idx++) {
                    if (pngData.chunks[idx].name = chunkName) {
                        return pngData.chunks[idx];
                    }
                }
                return null;
            },
            bytes2Int: function(bytes) {
                var ret = 0;
                for (var idx = 0; idx<bytes.length; idx++) {
                    ret += bytes[idx];
                    if (idx < bytes.length - 1) {
                        ret = ret << 8;
                    }
                }
                return ret;
            }
        }
    }

可以使用如下:

var pngData = PNG.parse(document.getElementById('yourImageId'));
console.log(pngData);

它包含一些信息,例如颜色模式,块数量,块本身,位深度等。

希望它有帮助。

JavaScript可以检查图像的颜色模式吗?

是,否。

如果使用普通图像加载。在通过Image对象(HTMLImageElement)将浏览器支持的所有图像转换为RGB(a)。

此时,除了它的大小和来源外,还没有提供有关原始格式和颜色模型的信息。

画布仅处理RGBA作为显示的所有其他元素,并且没有本机方法来解决诸如cmyk之类的颜色模型。

您始终可以读取RGBA值并天真地转换为CMYK,但是,由于RGB的更广泛的范围,打印机以及打印中型特征,您将遇到各种问题的ICC配置文件,您将遇到各种问题必须通过ICC配置文件进行调整。这意味着在大多数情况下,结果不会产生正确的颜色。

您必须为此设置服务器端解决方案。将图像发送到服务器,转换为CMYK/应用ICC,然后发送到打印机。ImageMagick可能是一种方法。浏览器根本没有用于打印的处理。

如果您愿意手动编写图像解析器以及ICC解析器。您将需要支持各种格式和格式组合,还可以通过目标ICC应用ICC/gamma以及导出到CMYK(这意味着您需要支持XYZ/Lab color Spaces)。

导出将要求您编写支持CMYK颜色空间和ICC嵌入的文件作者。

成熟过程,错误,不稳定性等将是该过程的自然部分,可能不是您要立即在生产中使用的东西。

如果您只是遵循文件的颜色模式,并且可以像普通的图像一样加载图像,当然可以通过XHR加载文件,然后使用键入数组扫描文件,以定位描述颜色格式的信息格式。然后将键入的数组作为blob-> object -url作为图像加载,浏览画布并将每个像素转换为cmyk值。

但是,从这一点开始,您将遇到与上述相同的问题,并且不会逃脱编写文件作者等。

您可以使用exifreader软件包读取图像元数据。

import ExifReader from 'exifreader'
const reader = new FileReader()
reader.onload = (event) => {
  const metadata = ExifReader.load(event.target.result, { expanded: true })
  const { file: { 'Color Components': { value } } } = metadata
  switch (value) {
  case 3: console.log('RGB'); break
  case 4: console.log('CMYK'); break
  default: console.log('Unknown')
  }
}
reader.readAsArrayBuffer(instaceOfFileObject)

它不必是File对象,但是ExifReader.load()期望数组缓冲区作为其第一个ARG。

参考:https://www.get-metadata.com/file-info/color-components

最新更新