ASCII Silhouettify - Chuyển đổi hình ảnh thành bóng ASCII
(meatfighter.com)- ASCII Silhouettify là ứng dụng trình duyệt và dòng lệnh biến đồ họa phẳng, tương phản cao như logo, banner, pixel art thành ASCII art dạng bóng được lấp đầy chỉ bằng 95 ký tự ASCII có thể in ra
- Nhận đầu vào
png,svg,jpg,webp,gif,tif,heif,avif,pdf, nhưng không render vùng đổ bóng, highlight, shadow hay gradient nên không phù hợp để chuyển đổi ảnh chụp - Đầu ra hỗ trợ văn bản màu ANSI, văn bản thường, HTML và định dạng ASCII art tùy chỉnh của Neofetch; định dạng Neofetch bị giới hạn ở 6 màu trong bảng màu ANSI mở rộng 256 màu
- Thuật toán chuyển đổi chia hình ảnh thành các mặt phẳng màu, rồi trong mỗi vùng 9×19 pixel chọn ký tự lớn nhất trong số các ký tự ASCII không xâm phạm đường viền bóng
- Để tối ưu hiệu năng, công cụ dùng bộ tích lũy 95 bit, 171 bitmask, phép tính leading zeros, xử lý song song trên các bộ xử lý logic, và áp dụng công thức chênh lệch màu cảm nhận CIEDE2000 vốn có chi phí tính toán cao cho việc khớp bảng màu
Ứng dụng chuyển đổi bóng ASCII
- ASCII Silhouettify là ứng dụng biến hình ảnh thành bóng ASCII
- Bóng ASCII là phong cách ASCII art làm nổi bật các hình khối hình học được lấp đầy đồng đều hơn là đường nét hay kết cấu
- Phù hợp với đồ họa phẳng mang tính tối giản, tương phản cao và không có chiều sâu không gian như logo, banner, pixel art
- Không phù hợp với ảnh chụp vì không render vùng đổ bóng, highlight, shadow hay gradient
- Bộ ký tự bị giới hạn ở 95 ký tự ASCII có thể in ra, là chất liệu truyền thống của các nghệ sĩ ASCII
- Không dùng các ký tự đường nét/khối thường thấy trong ANSI art hay nhiều ký tự Unicode của kaomoji
- Định dạng đầu ra thay đổi theo cấu hình
- Văn bản thường đơn sắc
- Văn bản có màu bằng ANSI escape sequence
- HTML có hoặc không có màu
- Định dạng ASCII art của Neofetch
- Đây là ứng dụng desktop có thể dùng trên trình duyệt và dòng lệnh
Ví dụ với logo Ubuntu và Neofetch
- Ví dụ minh họa quy trình đưa kết quả của ASCII Silhouettify vào đầu ra Neofetch trên một instance Ubuntu
- Để có ASCII art tối ưu, trước tiên lấy ảnh logo Ubuntu độ phân giải cao từ web và scale trước về kích thước sẽ hiển thị trên console
- Khi chuyển đổi ảnh bằng phiên bản dòng lệnh, mặc định sẽ tạo ra văn bản màu bằng ANSI escape sequence
- Có thể dùng cờ
-ođể gửi đầu ra vào tệp mà Neofetch sẽ hiển thị - Vì Neofetch chèn khoảng trắng rộng giữa ANSI art và các chỉ số hệ điều hành, ví dụ dùng định dạng tệp ASCII art tùy chỉnh của Neofetch
- Dòng đầu tiên của tệp đầu ra là danh sách chỉ số màu
- Các dòng sau là hình ảnh đã được mã hóa
- Sao chép dòng đầu vào clipboard trong trình soạn thảo văn bản rồi xóa nó đi
- Khi chạy Neofetch, dán giá trị đã lưu trong clipboard để dùng
- Để áp dụng vĩnh viễn, thay một phần script bash của Neofetch bằng chính giá trị đó
- Khi chồng logo gốc lên trên kết quả đã tạo để so sánh, có thể thấy rõ thuật toán chọn ký tự lớn nhất nằm bên trong đường viền của từng vùng màu
Cài đặt và gỡ bỏ
- Phiên bản dòng lệnh là ứng dụng Node.js
- Nếu chưa có Node.js, cần làm theo quy trình cài đặt Node.js trước
- Trên macOS và Linux, cần cấu hình
npmđể có thể cài đặt toàn cục mà không cần người dùng root - Lệnh cài đặt:
npm install -g ascii-silhouettify
- Lệnh gỡ bỏ:
npm uninstall -g ascii-silhouettify
Tùy chọn đầu vào/đầu ra
- Phiên bản trình duyệt và phiên bản dòng lệnh hỗ trợ cùng một tập tùy chọn
- Cờ
-hcủa phiên bản dòng lệnh sẽ in ra thông điệp tóm tắt các tùy chọn
- Cờ
- Có thể chuyển đổi nhiều hình ảnh cùng lúc
- Các định dạng hỗ trợ là
png,svg,jpg,webp,gif,tif,heif,avif,pdf - Cờ
-icủa phiên bản dòng lệnh nhận nhiều quy tắc khớp mẫu tên tệp - Ảnh đầu vào phải có nền đen hoặc trong suốt
- Các định dạng hỗ trợ là
- Đầu ra được chia thành bốn nhóm
- Văn bản thường hoặc văn bản màu ANSI
- Văn bản fixed-width ở định dạng HTML
- Định dạng ASCII art tùy chỉnh của Neofetch
- Định dạng Neofetch bị giới hạn ở 6 màu trong bảng màu ANSI mở rộng 256 màu
- Bảng màu mặc định là 240 màu từ bảng màu ANSI mở rộng 256 màu, không gồm bảng màu ANSI chuẩn 16 màu
- 16 màu ANSI chuẩn thường bị định nghĩa lại trong các terminal emulator hiện đại nên bị loại khỏi mặc định
- Người dùng có thể chọn 8 màu đầu của bảng ANSI chuẩn, toàn bộ 16 màu ANSI chuẩn, toàn bộ 256 màu ANSI mở rộng, hoặc bảng màu mặc định 240 màu
- Có thể chỉ định số lượng màu tối đa xuất hiện trong đầu ra
- Màu được coi là nền đen sẽ không bị tính vào số lượng
- Mặc định là 255
- Chế độ đơn sắc thực chất đặt giá trị này thành 1
- Mặc định của định dạng ASCII art tùy chỉnh Neofetch là 6, cũng là mức tối đa của định dạng này
Điều chỉnh kích thước hiển thị và chất lượng chuyển đổi
- Tỷ lệ khung hình của ASCII art tạo ra trong terminal emulator thay đổi theo font, cỡ font, line height và quy tắc làm tròn kích thước ký tự
- Để tối ưu, tác giả chụp lại ảnh văn bản của terminal rồi đo kích thước pixel của từng ký tự fixed-width, bao gồm cả khoảng cách giữa các dòng
- Ví dụ số đo trên desktop Windows của tác giả như sau
- IntelliJ Terminal: ký tự 8×22, cỡ font 10, line height 1.65
- Putty: ký tự 8×16, cỡ font 10, line height 1.2
- Notepad: ký tự 10×18, cỡ font 13, line height 1.04
- Notepad++: ký tự 9×19, cỡ font 12, line height 1.2
- Windows Command Prompt: ký tự 8×16, cỡ font 10, line height 1.2
- Windows Console Host: ký tự 9×20, cỡ font 12, line height 1.25
- Windows Terminal: ký tự 9×19, cỡ font 12, line height 1.2
- Lý tưởng nhất là scale trước ảnh đầu vào trong phần mềm vẽ về đúng kích thước mong muốn khi hiển thị trong terminal
- Để tinh chỉnh nhỏ, ASCII Silhouettify nhận hệ số scale ảnh
- Mặc định là 1
- Thuật toán chuyển đổi biến các vùng có độ sáng dưới 5% thành ký tự khoảng trắng để nền đen lộ ra hoàn toàn
- Người dùng có thể điều chỉnh ngưỡng tối này
- Mặc định, công cụ phân phối công việc lên tất cả các bộ xử lý logic có sẵn
- Người dùng có thể giảm số bộ xử lý được cấp phát xuống còn 1
- Giảm số bộ xử lý sẽ làm thời gian xử lý lâu hơn
Thuật toán chuyển đổi
- Trên desktop Windows nơi tác giả tạo ra ASCII Silhouettify, Terminal render mỗi ký tự fixed-width trong một hình chữ nhật 9×19 pixel khi dùng cấu hình mặc định Cascadia Mono 12 point, 1.2em
- Thuật toán chụp ảnh của 95 ký tự ASCII có thể in ra, rồi áp ngưỡng ở mức cường độ 50% để tạo ảnh ký tự chỉ gồm các pixel đen trắng
- Ảnh nguồn được tách thành các mặt phẳng màu duy nhất
- Mỗi mặt phẳng là một bóng màu trắng trên nền đen
- Mỗi mặt phẳng màu được chia thành ma trận các vùng hình chữ nhật 9×19 pixel
- Mỗi vùng được thay bằng một ký tự ASCII
- Ký tự tối ưu được chọn bằng cách so sánh theo từng pixel giữa vùng đó và toàn bộ ảnh ký tự ASCII
- Nếu pixel trắng của ảnh ký tự chồng lên pixel đen của vùng, ký tự đó bị loại để tránh làm méo đường viền bóng
- Trong số các ký tự còn lại, chọn ký tự có số pixel trắng khớp nhiều nhất
- Khi thay vùng bằng ký tự, hệ thống ghi lại số pixel trắng khớp được
- Sau khi chuyển đổi tất cả các mặt phẳng, chọn ký tự có số pixel trắng khớp cao nhất để gộp các mặt phẳng
- Ký tự cuối cùng được tô bằng màu của mặt phẳng đã sinh ra ký tự đó
Tăng tốc bằng bitmask
- Trước khi chuyển đổi, ảnh ký tự ASCII được sắp xếp theo số lượng pixel trắng
- Ký tự khoảng trắng có 0 pixel trắng, là ít nhất
- Ký tự
@có nhiều pixel trắng nhất
- Thuật toán bắt đầu từ
@và đi ngược xuống để so sánh từng vùng với các ảnh ký tự- Ngay khi tìm được ký tự nằm hoàn toàn trong bóng, vùng đó sẽ được thay bằng ký tự đó
- Nhờ thứ tự sắp xếp, đó là ứng viên có số pixel trắng nhiều nhất
- Để tăng tốc đáng kể, công cụ chuẩn bị 171 bitmask cho từng pixel trong vùng 9×19
- Mỗi bitmask biểu diễn tập các ảnh ký tự ASCII có pixel đen tại tọa độ đó
- Mỗi bitmask chứa 95 bit
- bit-0 tương ứng với ký tự khoảng trắng, bit-94 tương ứng với ký tự
@
- Trong lúc chuyển đổi vùng, một bộ tích lũy 95 bit được dùng để dần thu hẹp tập ứng viên ký tự ASCII còn khả dụng
- Ban đầu bộ tích lũy được khởi tạo với tất cả bit bằng 1
- Với mỗi pixel đen của vùng, lấy bộ tích lũy hiện tại thực hiện bitwise AND với bitmask của pixel đó
- Phép toán này loại bỏ các ảnh ký tự có pixel trắng ở vị trí mà vùng đang là pixel đen
- Sau khi xử lý toàn bộ vùng, các set bit trong bộ tích lũy là những ký tự ứng viên có thể thay thế
- Vì các ký tự đã được sắp xếp, số lượng leading zeros của bộ tích lũy trở thành chỉ số của ảnh ký tự ASCII có nhiều pixel trắng nhất mà vẫn nằm trọn trong bóng
- Với sự hỗ trợ của thư viện, công cụ gọi lệnh leading zeros calculation của vi xử lý để lấy giá trị cần thiết một cách nhanh chóng
Tối ưu điểm gốc và khớp màu
- Khi chia ảnh nguồn thành ma trận các vùng hình chữ nhật, điểm gốc của ma trận sẽ ảnh hưởng đến kết quả
- Để tối ưu kết quả, thuật toán lặp lại quá trình chuyển đổi toàn bộ ảnh với mọi tọa độ gốc nguyên trong vùng 9×19 pixel quanh gốc ảnh
- Để xử lý được lượng tính toán lớn, công việc được phân phối lên các bộ xử lý logic sẵn có
- Tùy theo cấu hình người dùng, bảng màu có thể bị giới hạn từ 8 màu đầu của bảng ANSI chuẩn cho tới toàn bộ bảng ANSI mở rộng 256 màu
- Khi tách ảnh nguồn thành các mặt phẳng màu duy nhất, công cụ dùng công thức chênh lệch màu cảm nhận CIEDE2000 có chi phí tính toán cao để tìm màu gần nhất trong bảng màu
Mã nguồn
- Command-line version: kho lưu trữ phiên bản dòng lệnh của ASCII Silhouettify
- Browser version: kho lưu trữ phiên bản trình duyệt của ASCII Silhouettify
1 bình luận
Ý kiến trên Hacker News
Có vẻ trang ngầu nhất trên site này là bộ sưu tập màu: https://meatfighter.com/ascii-silhouettify/color-gallery.htm...
Nó tạo cảm giác khiến người ta nhìn thiết kế đồ họa biểu tượng từ một góc độ khác
Tôi đã làm một công cụ tương tự để tạo game sprite có thể đưa thẳng vào code: https://memalign.github.io/m/pceimage/index.html
Nó chạy trên web, và cả đầu ra ASCII có màu cũng chỉnh sửa được
Chỉ là để ra kết quả đẹp thì phải tự tắt Wobble và chỉnh kích thước lấy mẫu pixel nên hơi khó dùng
Nếu được đề xuất thì sẽ hay hơn nếu có một chế độ bỏ rung lắc nhưng vẫn giữ cảm giác dễ thương do làm dày và bo tròn góc tạo ra
Nếu bạn thích nghệ thuật liên quan đến ASCII, có lẽ bạn cũng sẽ thích công cụ ASCII động biến GIF thành ASCII: https://www.gifcii.fun
Nhân tiện thì tôi tự làm đấy
Sẽ tuyệt nếu có cách nào đó để lưu lại, ví dụ xuất ngược lại thành GIF hoặc video thì sẽ rất hay
Bản web không chạy xong trên trình duyệt nền tảng Chromium, nhưng bản CLI thì hoạt động: https://meatfighter.com/ascii-silhouettify/spa/index.html#/
Tiện thể tôi cũng thử làm một ASCII art lớn trông giống logo HN
Làm rất tuyệt, và nó gợi tôi nhớ đến Telnet Matrix có màu :)
Sau đó tôi còn phát hiện ra https://ascii.theater/
Vài năm trước tôi cũng làm thứ tương tự cho bộ chuyển đổi ảnh máy tính retro, dùng phông chữ đơn cách cố định của máy đó và còn áp dụng dithering trước khi chuyển ký tự
Vì như vậy ảnh cho ra các dải chuyển sắc mượt hơn: https://github.com/KodeMunkie/imagetozxspec/blob/master/src/...
“Điều đã có rồi sẽ lại có, điều đã làm rồi sẽ lại được làm; dưới mặt trời chẳng có gì mới.”
Làm rất tốt
Ngày xưa người ta cũng từng dùng mật độ in của ký tự trong EBCDIC và ASCII để in banner sinh nhật và hình ảnh rất giống thế này trên máy in băng giấy liên tục, rồi sau đó là máy in kim
Hôm nay chắc sẽ có khá nhiều người đi sửa
/etc/motdhoặc/etc/issueTôi từng thử làm thứ tương tự bằng một hàm rung lắc chuyển động theo thời gian thực: https://piter-genuary2024.netlify.app/genuary9/
Lại là npm nữa
Dự án thì tuyệt, nhưng tôi không hiểu sao cứ phải làm kiểu này
Không biết cách cài đặt bình thường đã đi đâu mất rồi
NPM hoạt động theo cùng một cách ở khắp mọi nơi, và không có trình quản lý gói nào được dùng rộng rãi trên nhiều nền tảng như NPM
Chỉ cần chạy bằng npx là được
Mỗi lần cấu hình theo cách khác là lại tốn hàng giờ và thành một mớ hỗn độn, nên các kho CLI của tôi được nối khắp nơi bằng
npm/yarn linkThậm chí tôi còn phát triển cả script Python bằng
nodemon main.py, cảm giác như chỉ dân Node mới biết thứ gì cần thiếtDù vậy tôi vẫn sẽ tiếp tục dùng https://asciiflow.com/# thay vì Figma