mirror of
				https://github.com/excalidraw/excalidraw.git
				synced 2025-10-31 10:54:33 +01:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			v0.16.0
			...
			arnost/png
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 671ed94d74 | ||
|   | d5ac76d4ea | ||
|   | 2b19d53549 | 
| @@ -44,6 +44,7 @@ | ||||
|     "png-chunk-text": "1.0.0", | ||||
|     "png-chunks-encode": "1.0.0", | ||||
|     "png-chunks-extract": "1.0.0", | ||||
|     "pngjs": "7.0.0", | ||||
|     "points-on-curve": "0.2.0", | ||||
|     "pwacompat": "2.0.17", | ||||
|     "react": "18.2.0", | ||||
| @@ -74,6 +75,7 @@ | ||||
|     "@types/lodash.throttle": "4.1.7", | ||||
|     "@types/pako": "1.0.3", | ||||
|     "@types/pica": "5.1.3", | ||||
|     "@types/pngjs": "6.0.1", | ||||
|     "@types/react": "18.0.15", | ||||
|     "@types/react-dom": "18.0.6", | ||||
|     "@types/resize-observer-browser": "0.1.7", | ||||
|   | ||||
| @@ -13,6 +13,7 @@ import { FileSystemHandle, nativeFileSystemSupported } from "./filesystem"; | ||||
| import { isValidExcalidrawData, isValidLibrary } from "./json"; | ||||
| import { restore, restoreLibraryItems } from "./restore"; | ||||
| import { ImportedLibraryData } from "./types"; | ||||
| import { PNG } from "pngjs/browser"; | ||||
|  | ||||
| const parseFileContents = async (blob: Blob | File) => { | ||||
|   let contents: string; | ||||
| @@ -210,9 +211,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 +231,86 @@ export const canvasToBlob = async ( | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| export const canvasToBlob = async ( | ||||
|   canvas: HTMLCanvasElement, | ||||
| ): Promise<Blob> => { | ||||
|   const tileWidth = 1000; | ||||
|   const tileHeight = 1000; | ||||
|   const tileDataArray: Uint8ClampedArray[][] = []; // Two-dimensional array to store tile data | ||||
|  | ||||
|   const { width: canvasWidth, height: canvasHeight } = canvas; | ||||
|  | ||||
|   const ctx = canvas.getContext("2d"); | ||||
|  | ||||
|   if (!ctx) { | ||||
|     throw new Error("No canvas context"); | ||||
|   } | ||||
|  | ||||
|   // Function to process each tile | ||||
|   function processTile(tileX: number, tileY: number) { | ||||
|     // Calculate the starting and ending coordinates for the tile | ||||
|     const startX = tileX * tileWidth; | ||||
|     const startY = tileY * tileHeight; | ||||
|     const endX = Math.min(startX + tileWidth, canvasWidth); | ||||
|     const endY = Math.min(startY + tileHeight, canvasHeight); | ||||
|  | ||||
|     // Get the image data for the tile directly from the main canvas | ||||
|     const imageData = ctx!.getImageData( | ||||
|       startX, | ||||
|       startY, | ||||
|       endX - startX, | ||||
|       endY - startY, | ||||
|     ).data; | ||||
|  | ||||
|     // Store the tile data in the two-dimensional array | ||||
|     tileDataArray[tileY] = tileDataArray[tileY] || []; | ||||
|     tileDataArray[tileY][tileX] = imageData; | ||||
|   } | ||||
|  | ||||
|   console.time("tiling"); | ||||
|   // Iterate over the tiles and process each one | ||||
|   for (let tileY = 0; tileY < canvasHeight / tileHeight; tileY++) { | ||||
|     for (let tileX = 0; tileX < canvasWidth / tileWidth; tileX++) { | ||||
|       processTile(tileX, tileY); | ||||
|     } | ||||
|   } | ||||
|   console.timeEnd("tiling"); | ||||
|  | ||||
|   console.time("create png"); | ||||
|   // Create a new PNG image with the final dimensions | ||||
|   const finalImage = new PNG({ width: canvasWidth, height: canvasHeight }); | ||||
|   console.timeEnd("create png"); | ||||
|  | ||||
|   console.time("concat tiles"); | ||||
|   // Merge the tiles into the final image | ||||
|   for (let tileY = 0; tileY < canvasHeight / tileHeight; tileY++) { | ||||
|     for (let tileX = 0; tileX < canvasWidth / tileWidth; tileX++) { | ||||
|       const imageData = tileDataArray[tileY][tileX]; | ||||
|       const destX = tileX * tileWidth; | ||||
|       const destY = tileY * tileHeight; | ||||
|  | ||||
|       // Copy the pixels from the tile to the final image | ||||
|       for (let y = 0; y < tileHeight; y++) { | ||||
|         for (let x = 0; x < tileWidth; x++) { | ||||
|           const index = (y * tileWidth + x) * 4; | ||||
|           const destIndex = ((destY + y) * canvasWidth + destX + x) * 4; | ||||
|           finalImage.data[destIndex] = imageData[index]; | ||||
|           finalImage.data[destIndex + 1] = imageData[index + 1]; | ||||
|           finalImage.data[destIndex + 2] = imageData[index + 2]; | ||||
|           finalImage.data[destIndex + 3] = imageData[index + 3]; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   console.timeEnd("concat tiles"); | ||||
|  | ||||
|   console.time("create buffer"); | ||||
|   const buffer = PNG.sync.write(finalImage); | ||||
|   console.timeEnd("create buffer"); | ||||
|  | ||||
|   return new Blob([buffer], { 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> => { | ||||
|   | ||||
| @@ -75,7 +75,9 @@ export const exportCanvas = async ( | ||||
|   document.body.appendChild(tempCanvas); | ||||
|  | ||||
|   if (type === "png") { | ||||
|     console.time("export png"); | ||||
|     let blob = await canvasToBlob(tempCanvas); | ||||
|     console.timeEnd("export png"); | ||||
|     tempCanvas.remove(); | ||||
|     if (appState.exportEmbedScene) { | ||||
|       blob = await ( | ||||
|   | ||||
							
								
								
									
										4
									
								
								src/global.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								src/global.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -120,3 +120,7 @@ declare module "image-blob-reduce" { | ||||
|   const reduce: ImageBlobReduce.ImageBlobReduceStatic; | ||||
|   export = reduce; | ||||
| } | ||||
|  | ||||
| declare module "pngjs/browser" { | ||||
|   export { PNG } from "pngjs"; | ||||
| } | ||||
|   | ||||
							
								
								
									
										12
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								yarn.lock
									
									
									
									
									
								
							| @@ -2714,6 +2714,13 @@ | ||||
|   resolved "https://registry.yarnpkg.com/@types/pica/-/pica-5.1.3.tgz#5ef64529a1f83f7d6586a8bf75a8a00be32aca02" | ||||
|   integrity sha512-13SEyETRE5psd9bE0AmN+0M1tannde2fwHfLVaVIljkbL9V0OfFvKwCicyeDvVYLkmjQWEydbAlsDsmjrdyTOg== | ||||
|  | ||||
| "@types/pngjs@6.0.1": | ||||
|   version "6.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/@types/pngjs/-/pngjs-6.0.1.tgz#c711ec3fbbf077fed274ecccaf85dd4673130072" | ||||
|   integrity sha512-J39njbdW1U/6YyVXvC9+1iflZghP8jgRf2ndYghdJb5xL49LYDB+1EuAxfbuJ2IBbWIL3AjHPQhgaTxT3YaYeg== | ||||
|   dependencies: | ||||
|     "@types/node" "*" | ||||
|  | ||||
| "@types/prettier@^2.1.5": | ||||
|   version "2.7.2" | ||||
|   resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" | ||||
| @@ -8227,6 +8234,11 @@ png-chunks-extract@1.0.0: | ||||
|   dependencies: | ||||
|     crc-32 "^0.3.0" | ||||
|  | ||||
| pngjs@7.0.0: | ||||
|   version "7.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-7.0.0.tgz#a8b7446020ebbc6ac739db6c5415a65d17090e26" | ||||
|   integrity sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow== | ||||
|  | ||||
| points-on-curve@0.2.0, points-on-curve@^0.2.0: | ||||
|   version "0.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/points-on-curve/-/points-on-curve-0.2.0.tgz#7dbb98c43791859434284761330fa893cb81b4d1" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user