2
0
Эх сурвалжийг харах

feat: init of generating blobs in chunk

Arnošt Pleskot 2 жил өмнө
parent
commit
2b19d53549
2 өөрчлөгдсөн 78 нэмэгдсэн , 3 устгасан
  1. 75 3
      src/data/blob.ts
  2. 3 0
      src/data/index.ts

+ 75 - 3
src/data/blob.ts

@@ -210,9 +210,7 @@ export const loadLibraryFromBlob = async (
   return parseLibraryJSON(await parseFileContents(blob), defaultStatus);
 };
 
-export const canvasToBlob = async (
-  canvas: HTMLCanvasElement,
-): Promise<Blob> => {
+const _canvasToBlob = async (canvas: HTMLCanvasElement): Promise<Blob> => {
   return new Promise((resolve, reject) => {
     try {
       canvas.toBlob((blob) => {
@@ -232,6 +230,80 @@ export const canvasToBlob = async (
   });
 };
 
+export const canvasToBlob = async (
+  canvas: HTMLCanvasElement,
+): Promise<Blob> => {
+  const chunkSize = 8000; // Adjust the chunk size according to your requirements
+
+  const chunkBlobs: Blob[] = []; // Array to hold the generated image chunk Blobs
+
+  console.log("canvas", canvas.width, canvas.height);
+
+  // Split the canvas into chunks and generate the image chunks
+  for (let x = 0; x < canvas.width; x += chunkSize) {
+    for (let y = 0; y < canvas.height; y += chunkSize) {
+      const chunkCanvas = document.createElement("canvas");
+      chunkCanvas.width = chunkSize;
+      chunkCanvas.height = chunkSize;
+      const chunkContext = chunkCanvas.getContext("2d");
+
+      if (!chunkContext) {
+        throw new Error("Could not get context");
+      }
+
+      // Copy the portion of the main canvas into the chunk canvas
+      chunkContext.drawImage(
+        canvas,
+        x,
+        y,
+        chunkSize,
+        chunkSize,
+        0,
+        0,
+        chunkSize,
+        chunkSize,
+      );
+
+      console.log(x, y, chunkSize);
+
+      // Convert the chunk canvas to a Blob
+      const blob = await _canvasToBlob(chunkCanvas);
+      chunkBlobs.push(blob);
+
+      chunkCanvas.remove();
+    }
+  }
+
+  // Convert each Blob into an ArrayBuffer and concatenate them
+  const arrayBuffers = await Promise.all(
+    chunkBlobs.map((blob) => {
+      return new Promise<ArrayBuffer>((resolve) => {
+        const reader = new FileReader();
+        reader.onloadend = () => {
+          if (reader.result instanceof ArrayBuffer) {
+            resolve(reader.result);
+          } else {
+            throw new Error("Failed to read ArrayBuffer");
+          }
+        };
+        reader.readAsArrayBuffer(blob);
+      });
+    }),
+  );
+  const totalLength = arrayBuffers.reduce(
+    (length, buffer) => length + buffer.byteLength,
+    0,
+  );
+  const concatenatedBuffer = new Uint8Array(totalLength);
+  let offset = 0;
+  for (const buffer of arrayBuffers) {
+    concatenatedBuffer.set(new Uint8Array(buffer), offset);
+    offset += buffer.byteLength;
+  }
+
+  return new Blob([concatenatedBuffer], { type: "image/png" });
+};
+
 /** generates SHA-1 digest from supplied file (if not supported, falls back
     to a 40-char base64 random id) */
 export const generateIdFromFile = async (file: File): Promise<FileId> => {

+ 3 - 0
src/data/index.ts

@@ -74,8 +74,11 @@ export const exportCanvas = async (
   tempCanvas.style.display = "none";
   document.body.appendChild(tempCanvas);
 
+  console.log("tempCanvas", tempCanvas.width, tempCanvas.height);
+
   if (type === "png") {
     let blob = await canvasToBlob(tempCanvas);
+    console.log("final blob size", blob.size);
     tempCanvas.remove();
     if (appState.exportEmbedScene) {
       blob = await (