在使用javascript toDataURL保存HTML5画布时,如何插入PNG注释块?

在使用javascript toDataURL保存HTML5画布时,如何插入PNG注释块?,javascript,html5-canvas,png,Javascript,Html5 Canvas,Png,我有一个压缩的canvas-to-png下载保护程序功能(见下面的代码)。 这段代码运行得很好,我对它的输出很满意。。。大部分。 第二次替换就足够了吗?那会是什么样子? 我唯一的其他选择是使用imagemagick对文件进行后期处理。 有什么想法吗 更完整地说:我想从javascript添加元数据。 我找到了这个链接 详细说明了结构,我可能有足够的时间弄清楚。 如果有人有经验,可以缩短这对我来说,我将不胜感激 //---------------------------------

我有一个压缩的canvas-to-png下载保护程序功能(见下面的代码)。 这段代码运行得很好,我对它的输出很满意。。。大部分。 第二次替换就足够了吗?那会是什么样子? 我唯一的其他选择是使用imagemagick对文件进行后期处理。 有什么想法吗

更完整地说:我想从javascript添加元数据。 我找到了这个链接 详细说明了结构,我可能有足够的时间弄清楚。 如果有人有经验,可以缩短这对我来说,我将不胜感激

        //------------------------------------------------------------------
        function save ()  // has to be function not var for onclick to work.
        //------------------------------------------------------------------
        {
            var element = document.getElementById("saver");
            element.download = savename;
            element.href = document.
                getElementById(id.figure1a.canvas).
                toDataURL("image/png").
                replace(/^data:image\/[^;]/,'data:application/octet-stream');
        }

Base-64表示与内部块几乎没有关系。它只是编码为字符串的[任何]二进制数据,因此可以通过纯字符串协议传输(或在文本上下文中显示)

创建一个示例可能有点宽泛,但希望展示主要步骤将有助于实现您的目标:

  • 要将块添加到PNG,首先必须使用XHR/将其数据转换为PNG格式(对于数据URI,或者对于PNG格式(我建议使用)。请参阅)
  • 向ArrayBuffer添加一个
  • 转到数组中表示IHDR块开始的位置0x08,读取块的长度()(对于几乎所有PNG,它很可能具有相同的静态大小,但因为可能会有更改,并且您不需要记住块的大小,我们将从这里读取它)。将长度添加到位置(+4表示块末尾的CRC-32,如果在读取长度时未移动指针,则添加+4),通常这将使您到达位置0x21
  • 您现在有了下一个块的位置,我们可以使用它插入我们自己的文本块
  • 使用带有原始ArrayBuffer的子数组将第一个零件拆分为零件数组(常规数组),例如
    new Uint8Array(ArrayBuffer,0,位置)-您也可以使用该方法
  • 将新块*生成为类型化数组并添加到部分数组
  • 将原始PNG数组中没有第一部分的剩余部分添加到零件数组中,例如
    new Uint8Array(arraybuffer,position,length-position)
  • 将零件数组直接用作参数(
    var newPng=newblob(零件数组,{type:“image/png”})
    ;)将零件数组转换为Blob。这将包含自定义块。从那里,您可以使用对象URL将其作为图像读回(或使其可供下载)
*)区块:

  • 对于
    tEXt
    请注意,它仅限于拉丁字符集,这意味着您必须粉刷要使用的字符串-对于unicode(UTF-8)内容使用
    iTXt
    -为了简单起见,我们将在此处使用
    tEXt
  • 关键字和值在
    文本
    块中由NUL字节(0x00)分隔,关键字必须按照中的定义准确键入
  • 以这种方式构建区块:
    • 从字符串获取字节大小
    • 添加12个字节(用于长度、四个cc和crc-32)
    • 以这种方式格式化数组(您也可以在此处使用数据视图):
      
      Uint32-块的长度(数据仅以字节数表示)
      Uint32-“文本”为四个cc
      […]-数据本身(按字节复制)
      Uint32-CRC32*包括四个CC,但不包括长度和自身。
PNG中的所有数据都是big-endian

要计算CRC-32,请随意使用pngtoy解决方案(LUT已构建)。以下是一种格式化四cc的方法:

function makeFourCC(n) {  // n = "tEXt" etc., big-endian
    var c = n.charCodeAt.bind(n);
    return (c(0) & 0x7f) << 24 | (c(1) & 0x7f) << 16 | (c(2) & 0x7f) << 8 | c(3) & 0x7f
}
函数makeFourCC(n){//n=“tEXt”等,大端 var c=n.charCodeAt.bind(n);
return(c(0)&0x7f)Base-64表示与内部块没有什么关系。它只是编码为字符串的[任何]二进制数据,因此可以通过纯字符串协议传输(或在文本上下文中显示)

创建一个示例可能有点宽泛,但希望展示主要步骤将有助于实现您的目标:

  • 要将块添加到PNG,首先必须使用XHR/将其数据转换为PNG格式(对于数据URI,或者对于PNG格式(我建议使用)。请参阅)
  • 向ArrayBuffer添加一个
  • 转到数组中表示IHDR区块开始的位置0x08,读取区块的长度()(对于几乎所有PNG,它很可能具有相同的静态大小,但因为可能会有更改,并且您不需要记住区块大小,我们将从这里读取)。将长度添加到位置(+4表示块末尾的CRC-32,如果在读取长度时未移动指针,则为+4),通常这会使您到达位置0x21
  • 您现在有了下一个块的位置,我们可以使用它插入我们自己的文本块
  • 使用带有原始ArrayBuffer的子数组将第一个零件拆分为零件数组(常规数组),例如,
    new Uint8Array(ArrayBuffer,0,position);
    -您也可以使用该方法
  • 将新块*生成为类型化数组并添加到部分数组
  • 将原始PNG数组的剩余部分(不包括第一部分)添加到零件数组中,例如
    new Uint8Array(arraybuffer,position,length-position);
  • 将零件数组直接用作参数(
    var newPng=new Blob(零件数组,{type:“image/png”})
    ;)将零件数组转换为Blob。这将包含自定义块。从那里,您可以使用对象URL将其作为图像读回(或使其可供下载)
*)区块:

  • 对于
    tEXt
    请注意,它仅限于拉丁字符集,这意味着您必须粉刷要使用的字符串-对于unicode(UTF-8)内容使用
    iTXt
    -为了简单起见,我们将在此处使用
    tEXt
  • 关键字和值由
    文本块中的NUL字节(0x00)和关键字m分隔