【求助】原生平台下,截图后得到的 Unit8Array 如何转有效的 PNG Base64编码字符串

根据官方的DEMO的原生平台截图保存代码:

saveFile (picData) {
    if (CC_JSB) {
        let filePath = jsb.fileUtils.getWritablePath() + 'render_to_sprite_image.png';

        let success = jsb.saveImageData(picData, this._width, this._height, filePath)
        if (success) {
            cc.log("save image data success, file: " + filePath);
        }
        else {
            cc.error("save image data failed!");
        }
    }
},

得到的picData其实是一个 Unit8Array 数据类型,请问如何将它保存为一个有效的 png Base64编码呢?

已经尝试过下面方法,但是都不能直接显示为一张PNG图

/**
 * Uint8Array 转 string
 */
static Uint8ArrayToString(unit8Array: Uint8Array): string {
    let CHUNK_SZ = 0x8000;
    let chars = [];
    for (let i = 0; i < unit8Array.length; i += CHUNK_SZ) {
        chars.push(String.fromCharCode.apply(null, unit8Array.subarray(i, i + CHUNK_SZ)));
    }
    return chars.join("");
}

// 用 js-base64 库去编码
let baseForNative = "data:image/png;base64," + Base64.btoa(Uint8ArrayToString(picData));

// 用浏览器原生API 去编码
let base64ForWeb = "data:image/png;base64," + btoa(Uint8ArrayToString(picData));

得出的两个编码都不能正常解码出可以显示的png图片,感觉应该不是Base64编码问题,因该是 picData 应该要做点什么处理在去编码为Base64吗?

求助~~~~

1赞

@BigBear @953459485

getBase64(unit8Array)
{
let keyStr = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=”;
var output = “”;
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
while (i < unit8Array.length) {
chr1 = unit8Array[i++];
chr2 = unit8Array[i++];
chr3 = unit8Array[i++];

        enc1 = chr1 >> 2;
        enc2 = (chr1 & 3) << 4 | chr2 >> 4;
        enc3 = (chr2 & 15) << 2 | chr3 >> 6;
        enc4 = chr3 & 63;

        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }
        output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
    }
    return output;
},

很旧的帖子了,十分感谢回复~

楼主问题解决了吗,可以来个方案吗?怎么把uint8的数组转化为图片文件呢,或者buffer文件的二进制流

这个很简单,在github找个png decode encode的工具,例如UPNG之类的自己看下就知道了

1赞

感谢回复,是时候研究一下下了

楼主有解决了吗

终于解决,这里jsbData的字节流不是png编码,先保存一次,在读出来,转Base64就对了
function uint8ToBase64String(u8a: Uint8Array) {
// 创建一个新的 Uint8Array 来存储字节流
const byteData = new Uint8Array(u8a.buffer);
// 转换为 base64
let binary = ‘’;
for (let i = 0; i < byteData.length; i++) {
binary += String.fromCharCode(byteData[i]);
}
let base64 = window.btoa(binary);
return base64;
}

function flipYImage (data: Uint8Array, width: number, height: number) {
// create the data array
let picData = new Uint8Array(width * height * 4);
let rowBytes = width * 4;
for (let row = 0; row < height; row++) {
let srow = height - 1 - row;
let start = srow * width * 4;
let reStart = row * width * 4;
// save the piexls data
for (let i = 0; i < rowBytes; i++) {
picData[reStart + i] = data[start + i];
}
}
return picData;
};
const data = texture.readPixels(pixels, 0, 0, width, height); // texture为RenderTexture对象
var jsbData = flipYImage(data); // 这里需要翻转图片
var tmpFilePath = jsb.fileUtils.getWritablePath() + ‘tmpImg.png’;
jsb.saveImageData(jsbData, width, height, tmpFilePath);
window.fsUtils.readArrayBuffer(tmpFilePath, function (err, byteData: Uint8Array) {
if (!err) {
var b64encoded = uint8ToBase64String(byteData);
console.log(‘isNative base64 len=’, b64encoded.length);
callback && callback(‘data:image/png;base64,’ + b64encoded);
} else {
callback && callback(null);
}
});