Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript将画布转换为PGM_Javascript_Image_Canvas_Image Conversion_Pgm - Fatal编程技术网

JavaScript将画布转换为PGM

JavaScript将画布转换为PGM,javascript,image,canvas,image-conversion,pgm,Javascript,Image,Canvas,Image Conversion,Pgm,我正在尝试将JavaScript中的画布转换为pgm。 转换文件并下载到桌面后,它具有pgm扩展名,但当我用编辑器打开它时,它被编码为png。 我认为,如果JavaScript没有识别出您想要转换为的扩展,它会在默认情况下将其转换为png。 所以JavaScript可以转换成png、jpeg等格式,但不能转换成pgm 我的问题是,是否可以使用JavaScript将画布转换为pgm,如果没有,是否有任何可用的插件或Js库可以这样做 function image_download() { c

我正在尝试将JavaScript中的画布转换为pgm。 转换文件并下载到桌面后,它具有pgm扩展名,但当我用编辑器打开它时,它被编码为png。 我认为,如果JavaScript没有识别出您想要转换为的扩展,它会在默认情况下将其转换为png。 所以JavaScript可以转换成png、jpeg等格式,但不能转换成pgm

我的问题是,是否可以使用JavaScript将画布转换为pgm,如果没有,是否有任何可用的插件或Js库可以这样做

function image_download() {
    canvas = $('#canvas').get(0);
    var image = new Image();
    image.src = canvas.toDataURL("image/pgm");


    var download = document.createElement('a');
    download.href = image.src;
    download.download = 'map.pgm';
    download.click();
}
PGM编写器 要将画布另存为PGM,我只需查看文件格式的详细信息,并使用该信息创建一个函数,将画布转换为PGM bin

转化 该文件有一个描述文件和内容的头,然后是一个8位或16位值的二进制数组

因此,从标题开始,将其创建为字符串

const CR = "\n";
var header = "P5" // required
header += CR; // add whitespace char
header += canvas.width;     
header += CR; // add whitespace char
header += canvas.height;     
header += CR; // add whitespace char
标题不完整,但我们需要获得像素值的最大值,以便转换图像并找到最大值

因此,通过2D上下文获取像素数据

var imgData = ctx.getImageData(0,0,ctx.canvas.width,ctx.height);
对于所需的数据,您有几个选项。该格式为某些值指定对数刻度,为其他值指定线性刻度。如果维护gamma很重要的话,我将把它留给您来查找转换。(请注意,仅当您计划广播或保留光照值(如天文图像)时才需要)

有一个实用程序可以将线性函数转换为BT.709伽马函数。参见链接文档

我添加了一些简单的格式。两个为16位,最大值为3*255

如果要从jpeg编码的图像进行转换,最好先将像素RGB转换为HSL并仅将L保存为8位值,从而从图像中提取亮度,这将阻止jpeg劣质色调和饱和度数据影响结果(jpeg具有近乎无损的灰度数据)

如果您是从最初存储为jpeg(jpg)的图像中保存图像,则应使用此格式

    format = formats.jpegLumPreserve;
感性的 因为总有一些聪明啊。。。需要兜售感知亮度转换的人,我也会补充,因为他们通常会弄错。因为我认为转换是一个古老的笑话,转换是基于2/7/1规则,在对数空间中完成的

    formats.perceptual = {
        convert (r, g, b) { bin[j++] = Math.sqrt(r * r * 0.2 + g * g * 0.7 + b * b * 0.1) | 0},
        dataStore (w, h) { return new Uint8Array(w * h) },
    }

这是基于成年人感知红色、绿色和蓝色三种原色的平均能力,并将灰色(亮度)结果与感知的颜色亮度匹配。

我根本不知道这种格式,我相信大多数浏览器都不提供对其进行本机编码的选项,但是,从中,将您从中获得的
[rgba]
位图数组转换为PGM和PPM并不难。谢谢,您的回答帮助我找到了解决此问题的好方法,但方法不同。(对我迟来的答复表示抱歉)我认为这个回答掩盖了一些关键问题。根据我的理解,你的画布将是sRBG。有许多灰度公式可以应用,具体取决于您是否已将它们转换为线性(--Title:Color to grayscale:该方法在图像识别中是否重要?)。PGM要求709非线性伽马压缩合法,但该标准承认许多变体(es:线性rgb灰度)。
    formats.jpegLumPreserve = {
        convert (r, g, b) { bin[j++] = rgb2hsl(r + g + b).l},
        dataStore (w, h) { return new Uint8Array(w * h) },
    }
    format = formats.jpegLumPreserve;
    formats.perceptual = {
        convert (r, g, b) { bin[j++] = Math.sqrt(r * r * 0.2 + g * g * 0.7 + b * b * 0.1) | 0},
        dataStore (w, h) { return new Uint8Array(w * h) },
    }