← โปรเจกต์ทั้งหมด

Web App · 2026

ASCII9

เปลี่ยนรูปภาพเป็น ASCII art บนเบราว์เซอร์ แล้วดาวน์โหลดเป็น PNG, JPG หรือข้อความ ในขนาดที่พร้อมใช้ทำโพสต์ รูปโปรไฟล์ หรือวอลเปเปอร์ โดยไม่มีการอัปโหลดรูปเลย

SvelteTypeScriptViteWeb WorkerCanvasVitest

โจทย์

ASCII9 เริ่มจากเดโมที่ผมทำด้วย Lovable มันใช้งานได้ แต่ผมแก้โค้ดชุดนั้นได้ไม่มาก และหน้าตาก็ดูเป็น template ทั่วไป ผมอยากได้เว็บที่ทำแค่อย่างเดียว คือเปลี่ยนรูปเป็น ASCII art ที่เอาไปโพสต์ ตั้งเป็นรูปโปรไฟล์ หรือใช้เป็นวอลเปเปอร์ได้จริง ต้องใช้ง่ายสำหรับคนที่เข้ามาครั้งแรก กินทรัพยากรน้อย และเขียนด้วยโค้ดที่ผมอ่านและแก้เองได้

หน้าแปลงรูปของ ASCII9 แสดงภาพบุคคลเป็น ASCII สีขาวบนพื้นดำ พร้อมแผงตั้งค่า Look, Detail, Color และ Frame
กำลังตรวจสอบเว็บไซต์จริง…เปิดในแท็บใหม่ ↗

สิ่งที่ทำ

ASCII9 เป็นหน้าเดียวที่โหลดรูป แปลง และ export ได้ครบ เปิดมาจะเจอรูปตัวอย่างที่แปลงไว้แล้ว จึงกด Download ได้ทันที จะลากรูปมาวาง วาง (Ctrl/Cmd+V ได้ทุกเมื่อ) หรือเลือกไฟล์เอง ก็จะแทนที่รูปตัวอย่าง

แผงตั้งค่าแสดงแค่ 4 อย่างไว้ด้านหน้า:

  • Look: preset 6 แบบ (Original, Terminal, Amber, Blocks, Sketch, Neon)
  • Detail: 20–200 คอลัมน์
  • Color: Mono, Image หรือ Duotone
  • Frame: Original, 1:1, 4:5, 9:16 หรือ 16:9 เลือกได้ทั้ง Fill และ Fit

ที่เหลือ (style, ชุดตัวอักษร, slider ปรับโทน, invert, flip, edge detection, Auto adjust) อยู่ใน "More adjustments" คนใช้ครั้งแรกจึงไม่ต้องเจอ slider เต็มจอ บนมือถือ control จะย้ายไปอยู่ใน dock ด้านล่างและ bottom sheet

Download จะบันทึก PNG ในขนาดพิกเซลที่ตรงกับ frame พอดี เช่น 1080 × 1350 สำหรับ 4:5, 1080 × 1920 สำหรับ 9:16 และ 2560 × 1440 สำหรับ 16:9 ส่วน JPG และไฟล์ข้อความเลือกได้จากเมนูข้าง ๆ

เทคนิค

  • Svelte 5 + Vite + TypeScript ได้ bundle เล็กและ markup ที่ยังอ่านง่าย dependency ตอนรันมีแค่ svelte กับ font จาก @fontsource สองตัว ไม่มี router, component kit หรือ library สำหรับ toast และ animation
  • Engine เป็น TypeScript ล้วน แยกจาก UI รันใน Web Worker ด้วย OffscreenCanvas การลาก slider จึงไม่ทำให้หน้าเว็บค้าง งานถูก debounce และงานเก่าที่ค้างจะถูกทิ้ง ภาพล่าสุดยังแสดงอยู่จนกว่าภาพใหม่จะพร้อม จึงไม่กะพริบ
  • Cell grid ชุดเดียว ใช้กับทุก output engine คืน typed array (index ของตัวอักษรและสี RGB ต่อหนึ่งช่อง) ทั้งพรีวิวบน canvas, PNG/JPG และ TXT วาดจาก grid เดียวกัน สิ่งที่เห็นจึงตรงกับสิ่งที่ดาวน์โหลด และไม่มีการ parse HTML
  • รายละเอียดการแปลงที่สำคัญ บนพื้นดำ พิกเซลสว่างจะได้ตัวอักษรที่แน่น Sobel edge ไม่ทิ้งกรอบดำที่ขอบภาพ ชุดตัวอักษรที่กำหนดเองถูกแยกด้วย Intl.Segmenter emoji และตัวอักษรผสมจึงไม่แตก จำนวนแถวของ grid คำนวณจากสัดส่วนช่องตัวอักษรของฟอนต์ที่วัดจริง ไม่ใช่ค่าคงที่
  • ความเป็นส่วนตัวตั้งแต่โครงสร้าง เป็น static site ไม่มีโค้ดฝั่งเซิร์ฟเวอร์ รูปไม่ออกจากเบราว์เซอร์เลย และเก็บแค่การตั้งค่าไว้ใน localStorage

ผลลัพธ์

ASCII9 เปิดใช้งานจริงที่ ascii.naay.cc เป็น static build ของ Vite บน Vercel มีไฟล์เทสต์ Vitest 13 ไฟล์ ครอบคลุม engine (การ map ตัวอักษร โทน สี Sobel edge ขนาด grid ต่อ frame และ Auto adjust) ตัว render และการรับไฟล์

สิ่งที่ได้เรียนรู้

การสร้างใหม่จาก spec ที่เขียนไว้ได้ผลดีกว่าการไล่แก้โค้ดที่ generate มา ผมเริ่มจากจดว่าเดโมเดิมทำอะไรบ้าง รวมถึงข้อบกพร่องของมัน แล้วเขียน MVP design ที่ตัด scope อย่างเด็ดขาด ไม่มี gallery ไม่มี style เพิ่ม ไม่มี export เป็น SVG หรือ HTML และการเก็บงานหนักไว้ใน worker หลังโครงสร้างข้อมูลเดียว (cell grid) ทำให้ UI เรียบง่าย และทดสอบ engine ได้โดยไม่ต้องใช้เบราว์เซอร์