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



我有一个紧凑的画布到png下载保护程序功能(见下面的代码)。 这段代码运行良好,我对它的输出感到满意......主要。 第二个替换就足够了吗? 那个替换会是什么样子? 我唯一的其他选择是使用imagemagick对文件进行后期处理。 有什么想法吗?

更完整:我想从javascript添加元数据。 我发现这个链接 http://dev.exiv2.org/projects/exiv2/wiki/The_Metadata_in_PNG_files 其中详细介绍了结构,我也许有足够的时间弄清楚。 如果有人有经验并且可以为我缩短时间,我将不胜感激。

//------------------------------------------------------------------
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/fetch(对于Data-URI)将其数据转换为ArrayBuffer,或者在将PNG作为Blob的情况下使用FileReader(我推荐)。见toBlob())。
  • 将 DataView 添加到 ArrayBuffer
  • 转到表示 IHDR 块开始的数组中的位置0x08,读取块的长度 (Uint32)(它很可能对几乎任何 PNG 都具有相同的静态大小,但由于可能会有更改,并且您不需要记住块大小,我们将从这里读取它)。将长度添加到位置(+4 表示块末尾的 CRC-32,如果您在读取长度时没有移动指针,则为 +4),通常这应该使您处于位置 0x21。
  • 您现在有了下一个块的位置,我们可以使用它来插入我们自己的文本块
  • 使用具有原始 ArrayBuffer 的子数组将第一部分拆分为部分数组(常规数组),例如new Uint8Array(arraybuffer, 0, position);- 您也可以使用子数组方法。
  • 将新的块*生成为类型化数组并添加到部分数组中
  • 将原始 PNG 数组的剩余部分(不含第一部分)添加到部分数组中,例如new Uint8Array(arraybuffer, position, length - position);
  • 使用部分数组直接作为参数将部分数组转换为 Blob (var newPng = new Blob(partArray, {type: "image/png"});)。现在,这将包含自定义区块。从那里,您可以使用对象 URL 将其作为图像读回(或使其可供下载)。

*) 块:

  • tEXt请注意,它仅限于拉丁语-1 字符集,这意味着您必须粉饰要使用的字符串 - 对 unicode (UTF-8) 内容使用iTXt- 为了简单起见,我们将在此处使用tEXt
  • 关键字和值在tEXt块中由 NUL 字节 (0x00) 分隔,并且关键字必须完全按照规范中的定义进行键入。
  • 以这种方式构建块:
    • 从字符串中获取字节大小
    • 添加 12 个字节(用于长度、4-cc 和 CRC-32)
    • 以这种方式格式化数组(您也可以在此处使用 DataView):
      Uint32 - length of chunk (data only in number of bytes) Uint32 - "tEXt" as four-cc [...] - The data itself (copy byte-wise) Uint32 - CRC32* which includes the FourCC but not length and itself.

PNG 中的所有数据都是大端序。

要计算CRC-32,请随意使用我的pngtoy解决方案的这一部分(LUT就是这样构建的)。以下是格式化四抄送的一种方法:

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
}

最新更新