[in progress] a color utility i'm making for my pixel art painting process www.val.town/x/jennschiffer/pixelstats
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 118 lines 3.0 kB view raw
1import * as path from "@std/path"; 2import { Application, Router } from "@oak/oak"; 3import { getPixels } from "@unpic/pixels"; 4 5const app = new Application(); 6 7/** FILES **/ 8const moduleDir = path.dirname(path.fromFileUrl(import.meta.url)); 9const publicDir = path.join(moduleDir, "public"); 10 11function getPublicFile(...filePath: string[]): Promise < Uint8Array > { 12 return Deno.readFile(path.join(publicDir, ...filePath)); 13} 14 15/** ROUTES **/ 16const router = new Router(); 17 18// index 19router.get("/", async (ctx, next) => { 20 ctx.response.body = await getPublicFile("index.html"); 21 ctx.response.type = "text/html"; 22 await next(); 23}); 24 25// process 26router.post("/process-pixels", async (ctx, next) => { 27 const file = (await ctx.request.body.formData()).get("image"); 28 29 if (file instanceof File) { 30 31 try { 32 // create image from file uploaded 33 const uploadedFileBuffer = await file.arrayBuffer(); 34 const { width, height, data } = await getPixels(uploadedFileBuffer); 35 const colors = getPixelColors(data); 36 37 const processed = JSON.stringify({ 38 message: "success: pixels processed", 39 fileName: file.name, 40 fileSize: file.size, 41 fileType: file.type, 42 width, 43 height, 44 data, 45 colors, 46 }); 47 48 ctx.response.status = 200; 49 ctx.response.body = { processed } 50 51 } catch (err) { 52 ctx.response.status = 400; 53 ctx.response.body = { message: 'Error: Failed to create getPixels' } 54 } 55 } else { 56 ctx.response.status = 400; 57 ctx.response.body = { message: 'Error: File not uploaded' } 58 } 59 await next(); 60}) 61 62// routes & static files 63app.use(router.routes()); 64app.use(router.allowedMethods()); 65app.use(async (context, next) => { 66 const root = `${Deno.cwd()}/public` 67 try { 68 await context.send({ root }) 69 } catch { 70 next() 71 } 72}) 73 74 75/** CONSOLE/LISTEN **/ 76function printStartupMessage({ hostname, port, secure }: { 77 hostname: string; 78 port: number; 79 secure ? : boolean; 80}): void { 81 const address = new URL( 82 `http${secure ? "s" : ""}://${ 83 hostname === "0.0.0.0" ? "localhost" : hostname 84 }:${port}/`, 85 ).href; 86 console.log(`Listening at ${address}`); 87} 88app.addEventListener("listen", printStartupMessage); 89await app.listen({ port: 8000 }); 90 91 92/** HELPER FUNCTIONS */ 93// generate pixel colors json from image buffer 94function getPixelColors(data: Uint8Array): object { 95 let i = 0; 96 const pixelsArray = []; 97 98 while (i < data.length) { 99 pixelsArray.push([data[i], data[i + 1], data[i + 2], data[i + 3]].join()); 100 i = i + 4; 101 } 102 103 // eg. 2400 colors for a 60 x 40 image 104 const colorsDistribution = {}; 105 for (const pixel of pixelsArray) { 106 if (colorsDistribution[pixel]) { 107 colorsDistribution[pixel] += 1; 108 } else { 109 colorsDistribution[pixel] = 1; 110 } 111 } 112 113 const colorsDistributionSorted = Object.fromEntries( 114 Object.entries(colorsDistribution).sort(([, a], [, b]) => b - a), 115 ); 116 117 return { pixelsArray, colorsDistribution, colorsDistributionSorted }; 118}