Canvas.toDataURL 用不了咋办?
只好自个
encode
了。
事由是这样的,接到一个截图需求(以 base64
输出),但是在某个环境下,Canvas.toDataURL
这个接口返回的数据是错误的。
为此,写一篇文章记录一下,如何绕过 Canvas.toDataURL
,生成 base64
字符串。
以下为 Cocos官网文档中给出的截图事例代码。https://docs.cocos.com/creator/manual/zh/render/camera.html#%E6%88%AA%E5%9B%BE
官网中的截图代码幸运的是 readPixels()
能读到位图的像素信息。
程序就是处理输入和输出的过程,为此,明确我们的输入输出。
- 输入:
data: Uint8Array
位图信息 和 图片宽高。 - 输出:带有图片信息的
base64
字符串。(可将该字符串放浏览器中的地址栏,会返回一张图片)
经思考🤔一番,决定采用以下几步实现:
- 像素数据 -> 转
JPG
数据 -> 转base64
如何转 JPG
格式?按照厂里的方法,应该去了解其文件格式如何生成,需要什么头文件信息,关于JPEG
相关内容可参考wiki : https://en.wikipedia.org/wiki/JPEG
但🥚,在思考前,可以考虑是否有前任👩的轮子。毕竟时间也是一种成本。
很快,很有型地在大型交友网站 github
中找到了前人留下的轮子。
https://github.com/jpeg-js/jpeg-js/blob/master/lib/encoder.js
这是 JavaScript
的代码,白玉无冰这里操作的是直接拷贝出来,放到一个 TypeScript
代码中,导出 encodeJPG
方法。
再参考 jpeg-js
中的实例代码,组织一下,很快就生成了 JPEG
的数据。
再把JPEG
的数据中 Uint8Array
转 base64
。
但发现截图反了。
截图反了最后,再对原来的数据翻转一下,完整的核心代码如下:
// 这样我们就能从 RenderTexture 中获取到数据了
let data = texture.readPixels();
let width = texture.width;
let height = texture.height;
// 接下来翻转y的数据
const flipYData = new Uint8Array(width * height * 4);
let rowBytes = width * 4;
for (let row = 0; row < height; row++) {
let startRow = height - 1 - row;
let start = startRow * width * 4;
for (let i = 0; i < rowBytes; i++) {
flipYData[row * width * 4 + i] = data[start + i];
}
}
// 准备生成 jpegImageData
const rawImageData = {
data: flipYData,
width: width,
height: height,
};
const jpegImageData = encodeJPG(rawImageData, 50);
// jpeg -> base64
function uint8ToString(buf) {
var i, length, out = '';
for (i = 0, length = buf.length; i < length; i += 1) {
out += String.fromCharCode(buf[i]);
}
return out;
}
const base64 = btoa(uint8ToString(jpegImageData.data));
cc.warn('base64', "data:image/jpg;base64," + base64);
完整代码工程:https://github.com/baiyuwubing/cocos-creator-examples/tree/master/2.4.x/assets/demo06
以上为白玉无冰使用 Cocos Creator 2.4
实现 "截图生成 base64"
的过程分享。
Fake3D && Shader
MatCap && Shader
如何抄shader
3D折纸
渐变色文字3.0
水排序效果
点击“阅读原文”查看精选导航
“点赞“ ”在看” 鼓励一下▼