天天看點

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

Canvas.toDataURL 用不了咋辦?

官網中的截圖代碼

幸運的是

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

方法。

Canvas.toDataURL 用不了咋辦?

搬運與改造 jpeg-js

再參考

jpeg-js

中的執行個體代碼,組織一下,很快就生成了

JPEG

的資料。

Canvas.toDataURL 用不了咋辦?

像素資料 轉 JPEG 資料

再把

JPEG

的資料中

Uint8Array

base64

Canvas.toDataURL 用不了咋辦?

Uint8Array 轉 base64

但發現截圖反了。

Canvas.toDataURL 用不了咋辦?

截圖反了

最後,再對原來的資料翻轉一下,完整的核心代碼如下:

// 這樣我們就能從 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"

的過程分享。