export module ImageConver { export function ImageToBase64(Texture2D: cc.Texture2D): string { let image: ImageBitmap = Texture2D["_image"]; let cv: HTMLCanvasElement = document.createElement("canvas"); let context: CanvasRenderingContext2D = cv.getContext("2d"); cv.width = image.width || 128; cv.height = image.height || 128; context.drawImage(image, 0, 0, image.width || 128, image.height || 128); let DataURL: string = cv.toDataURL(); return DataURL; } export function Base64toBlob(b64Data: any, contentType: string = "image/png", sliceSize: number = 512): Blob { let byteCharacters: string = atob(b64Data.substring(b64Data.indexOf(",") + 1)); const byteArrays: any[] = []; for (let offset: number = 0; offset < byteCharacters.length; offset += sliceSize) { const slice: string = byteCharacters.slice(offset, offset + sliceSize); const byteNumbers: any[] = new Array(slice.length); for (let i: number = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } const byteArray: Uint8Array = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } const blob: Blob = new Blob(byteArrays, { type: contentType }); return blob; } export function BlobToImageNode(BlobData: Blob, node: cc.Node): void { let reader: FileReader = new FileReader(); reader.onloadend = function (): void { ImageConver.Base64ToImageNode(reader.result + "", node); }; reader.readAsDataURL(BlobData); } export function Base64ToImageNode(base64: string, node: cc.Node): void { let image: HTMLImageElement = new Image(); image.src = base64; image.onload = function (): void { let texture: cc.Texture2D = new cc.Texture2D(); texture.initWithElement(image); texture.handleLoadedTexture(); let spriteFrame: cc.SpriteFrame = new cc.SpriteFrame(texture); let sprite: cc.Sprite = node.addComponent(cc.Sprite); sprite.spriteFrame = spriteFrame; return; }; } export function Node2Base64(nodeCapture: cc.Node): string { let nodeCamera: cc.Node = new cc.Node(); nodeCamera.parent = cc.find("Canvas"); let camera: cc.Camera = nodeCamera.addComponent(cc.Camera); let position: cc.Vec2 = nodeCapture.getPosition(); let width: number = nodeCapture.width; let height: number = nodeCapture.height; // 当 alignWithScreen 为 true 的时候,摄像机会自动将视窗大小调整为整个屏幕的大小。如果想要完全自由地控制摄像机,则需要将 alignWithScreen 设置为 false。(v2.2.1 新增) camera.alignWithScreen = false; // 设置摄像机的投影模式是正交(true)还是透视(false)模式 camera.ortho = true; // 摄像机在正交投影模式下的视窗大小。该属性在 alignWithScreen 设置为 false 时生效。 camera.orthoSize = height / 2; let texture: cc.RenderTexture = new cc.RenderTexture(); // 如果截图内容中不包含 Mask 组件,可以不用传递第三个参数 texture.initWithSize(width, height); // 如果设置了 targetTexture,那么摄像机渲染的内容不会输出到屏幕上,而是会渲染到 targetTexture 上。 camera.targetTexture = texture; // 创建画布 let canvas: HTMLCanvasElement = document.createElement("canvas"); canvas.width = width; canvas.height = height; let ctx: CanvasRenderingContext2D = canvas.getContext("2d"); nodeCapture.setPosition(cc.Vec2.ZERO); // 渲染一次摄像机,即更新一次内容到 RenderTexture 中 camera.render(nodeCapture); nodeCapture.setPosition(position); // 从 render texture 读取像素数据,数据类型为 RGBA 格式的 Uint8Array 数组。 // 默认每次调用此函数会生成一个大小为 (长 x 高 x 4) 的 Uint8Array。 let data: Uint8Array = texture.readPixels(); // write the render data // PNG 中 1 像素 = 32 bit(RGBA),1 byte = 8 bit,所以 1 像素 = 4 byte // 每行 width 像素,即 width * 4 字节 let rowBytes: number = width * 4; for (let row: number = 0; row < height; row++) { // RenderTexture 得到的纹理是上下翻转的 let srow: number = height - 1 - row; let imageData: ImageData = ctx.createImageData(width, 1); let start: number = srow * width * 4; for (let i: number = 0; i < rowBytes; i++) { imageData.data[i] = data[start + i]; } ctx.putImageData(imageData, 0, row); } let dataURL: string = canvas.toDataURL("image/png"); return dataURL; } }