Hướng dẫn javascript convert ascii - javascript chuyển đổi ascii

Dạo gần đây tự nhiên rộ lên cái trend convert ảnh sang ASCII art [ảnh dưới dạng các ký tự ASCII]. Sau khi tìm hiểu thì mình thấy cách phổ biến nhất mà mọi người thường làm là lên google search "convert image to ASCII art" rồi upload ảnh lên, sau đó copy các ký tự ASCII về rồi in ra hoặc dùng một lib nào đó. Những cách đó cũng được thôi, nhưng bạn sẽ không thể custom cũng như là không hiểu các tool đó họ làm như thế nào.

Bạn nào nôn nóng có thể xem trước demo hoặc Github Repo

Trong bài viết này mình sẽ hướng dẫn các bạn convert từ ảnh sang ASCII art chỉ bằng javascript và không dùng bất kỳ thư viện nào cả. Ok bắt đầu nhé.

Thuật toán chuyển ảnh sang ASCII art

Có một bài post thú vị các bạn có thể xem How do ASCII art image conversion algorithms work?

Chuyển sang ASCII art cơ bản có 2 bước:

  1. Chuyển ảnh màu sang ảnh trắng đen [gray colors]

  2. Map từng pixel sang các ký tự dựa trên giá trị grayscale

Ví dụ,

const canvas = document.getElementById['preview']

const fileInput = document.querySelector['input[type="file"]']

const context = canvas.getContext['2d']

fileInput.onchange = [e] => {

const file = e.target.files[0]

const reader = new FileReader[]

reader.onload = [event] => {

const image = new Image[]

image.onload = [] => {

canvas.width = image.width

canvas.height = image.height

context.drawImage[image, 0, 0]

}

image.src = event.target.result

}

reader.readAsDataURL[file]

}

6 thì tối màu hơn

const canvas = document.getElementById['preview']

const fileInput = document.querySelector['input[type="file"]']

const context = canvas.getContext['2d']

fileInput.onchange = [e] => {

const file = e.target.files[0]

const reader = new FileReader[]

reader.onload = [event] => {

const image = new Image[]

image.onload = [] => {

canvas.width = image.width

canvas.height = image.height

context.drawImage[image, 0, 0]

}

image.src = event.target.result

}

reader.readAsDataURL[file]

}

7, cũng tối màu hơn

const canvas = document.getElementById['preview']

const fileInput = document.querySelector['input[type="file"]']

const context = canvas.getContext['2d']

fileInput.onchange = [e] => {

const file = e.target.files[0]

const reader = new FileReader[]

reader.onload = [event] => {

const image = new Image[]

image.onload = [] => {

canvas.width = image.width

canvas.height = image.height

context.drawImage[image, 0, 0]

}

image.src = event.target.result

}

reader.readAsDataURL[file]

}

8.

Trong bài viết này, mình sẽ triển khai thuật toán này bằng JS thuần và chạy trên trình duyệt.

Upload ảnh sang Canvas

Niiya Mayu cho bác nào muốn hỏi

Bước đầu tiên chúng ta cần cho phép người dùng upload ảnh, vì thế ta cần một input file. Sau đó mình sẽ phân tích ảnh sang từng pixel, mình sẽ dùng một

const canvas = document.getElementById['preview']

const fileInput = document.querySelector['input[type="file"]']

const context = canvas.getContext['2d']

fileInput.onchange = [e] => {

const file = e.target.files[0]

const reader = new FileReader[]

reader.onload = [event] => {

const image = new Image[]

image.onload = [] => {

canvas.width = image.width

canvas.height = image.height

context.drawImage[image, 0, 0]

}

image.src = event.target.result

}

reader.readAsDataURL[file]

}

9. Dưới đây là HTML mà mình sử dụng.

html

DOCTYPE html>

Ascii Art Converter

Ascii Art Converter

Tại bước này, mình có thể upload một ảnh lên input nhưng chưa có gì xảy ra cả. Đó là bởi vì mình cần chuyển file ảnh đó sang

const canvas = document.getElementById['preview']

const fileInput = document.querySelector['input[type="file"]']

const context = canvas.getContext['2d']

fileInput.onchange = [e] => {

const file = e.target.files[0]

const reader = new FileReader[]

reader.onload = [event] => {

const image = new Image[]

image.onload = [] => {

canvas.width = image.width

canvas.height = image.height

context.drawImage[image, 0, 0]

}

image.src = event.target.result

}

reader.readAsDataURL[file]

}

9 element. Mình sẽ sử dụng

GrayScale = 0.21 R + 0.72 G + 0.07 B

1 API:

js

const canvas = document.getElementById['preview']

const fileInput = document.querySelector['input[type="file"]']

const context = canvas.getContext['2d']

fileInput.onchange = [e] => {

const file = e.target.files[0]

const reader = new FileReader[]

reader.onload = [event] => {

const image = new Image[]

image.onload = [] => {

canvas.width = image.width

canvas.height = image.height

context.drawImage[image, 0, 0]

}

image.src = event.target.result

}

reader.readAsDataURL[file]

}

Khi input thay đổi, mình sẽ tạo một

GrayScale = 0.21 R + 0.72 G + 0.07 B

1 object mới, điều này sẽ giúp mình đọc file và chuyển vào

const canvas = document.getElementById['preview']

const fileInput = document.querySelector['input[type="file"]']

const context = canvas.getContext['2d']

fileInput.onchange = [e] => {

const file = e.target.files[0]

const reader = new FileReader[]

reader.onload = [event] => {

const image = new Image[]

image.onload = [] => {

canvas.width = image.width

canvas.height = image.height

context.drawImage[image, 0, 0]

}

image.src = event.target.result

}

reader.readAsDataURL[file]

}

9. Mình đã đặt size canvas bằng với size ảnh upload để tránh bị giảm chất lượng. 2 tham số cuối của

GrayScale = 0.21 R + 0.72 G + 0.07 B

4 xác định nơi đặt ảnh trong canvas. Trong trường hợp này, mình muốn vẽ một bức 'ảnh' từ vị trí góc trên cùng bên trái. [tọa độ [0,0]].

Một khi mình đã nhúng đoạn script này vào trang HTML, mình có thể upload một bức ảnh bất kì và nó sẽ hiển thị trong

const canvas = document.getElementById['preview']

const fileInput = document.querySelector['input[type="file"]']

const context = canvas.getContext['2d']

fileInput.onchange = [e] => {

const file = e.target.files[0]

const reader = new FileReader[]

reader.onload = [event] => {

const image = new Image[]

image.onload = [] => {

canvas.width = image.width

canvas.height = image.height

context.drawImage[image, 0, 0]

}

image.src = event.target.result

}

reader.readAsDataURL[file]

}

9 element.

Chuyển ảnh sang ảnh trắng đen Gray Colors

Bây giờ bức ảnh đã được upload, mình cần chuyển nó sang ảnh trắng đen. Màu của mỗi pixel được tạo từ 3 màu cơ bản: red, green, blue như trong giá trị hexadicimal color css [

GrayScale = 0.21 R + 0.72 G + 0.07 B

6].

Một cách đơn giản để tính được thang màu xám tương ứng là lấy trung bình 3 giá trị này. Tuy nhiên, mắt con người chúng ta thì không nhạy cảm như nhau với 3 màu này. Ví dụ, mắt chúng ta rất nhạy cảm với màu green, trong khi blue thì sẽ hời hợt 1 chút. Do đó, chúng ta cần cân nhắc sử dụng các màu với các tỉ lệ khác nhau. Sau khi nghiên cứu chi tiết Grayscale Wikipedia Page, mình quyết định tính giá trị grayscale dựa trên công thức dưới đây:

bash

GrayScale = 0.21 R + 0.72 G + 0.07 B

Vì thế mình cần lặp qua mỗi pixel của bức ảnh và thay thế nó bằng giá trị grayscale.

const canvas = document.getElementById['preview']

const fileInput = document.querySelector['input[type="file"]']

const context = canvas.getContext['2d']

fileInput.onchange = [e] => {

const file = e.target.files[0]

const reader = new FileReader[]

reader.onload = [event] => {

const image = new Image[]

image.onload = [] => {

canvas.width = image.width

canvas.height = image.height

context.drawImage[image, 0, 0]

}

image.src = event.target.result

}

reader.readAsDataURL[file]

}

9 API cung cấp function

GrayScale = 0.21 R + 0.72 G + 0.07 B

8 để chúng ta phân tách từng pixel của bức ảnh.

js

const toGrayScale = [r, g, b] => 0.21 * r + 0.72 * g + 0.07 * b

const convertToGrayScales = [context, width, height] => {

const imageData = context.getImageData[0, 0, width, height]

const grayScales = []

for [let i = 0; i {

const file = e.target.files[0]

const reader = new FileReader[]

reader.onload = [event] => {

const image = new Image[]

image.onload = [] => {

canvas.width = image.width

canvas.height = image.height

context.drawImage[image, 0, 0]

}

image.src = event.target.result

}

reader.readAsDataURL[file]

}

9. Mình đã đặt size canvas bằng với size ảnh upload để tránh bị giảm chất lượng. 2 tham số cuối của

GrayScale = 0.21 R + 0.72 G + 0.07 B

4 xác định nơi đặt ảnh trong canvas. Trong trường hợp này, mình muốn vẽ một bức 'ảnh' từ vị trí góc trên cùng bên trái. [tọa độ [0,0]].

Một khi mình đã nhúng đoạn script này vào trang HTML, mình có thể upload một bức ảnh bất kì và nó sẽ hiển thị trong

const canvas = document.getElementById['preview']

const fileInput = document.querySelector['input[type="file"]']

const context = canvas.getContext['2d']

fileInput.onchange = [e] => {

const file = e.target.files[0]

const reader = new FileReader[]

reader.onload = [event] => {

const image = new Image[]

image.onload = [] => {

canvas.width = image.width

canvas.height = image.height

context.drawImage[image, 0, 0]

}

image.src = event.target.result

}

reader.readAsDataURL[file]

}

9 element.

Chuyển ảnh sang ảnh trắng đen Gray Colors

Bây giờ bức ảnh đã được upload, mình cần chuyển nó sang ảnh trắng đen. Màu của mỗi pixel được tạo từ 3 màu cơ bản: red, green, blue như trong giá trị hexadicimal color css [

GrayScale = 0.21 R + 0.72 G + 0.07 B

6].

Một cách đơn giản để tính được thang màu xám tương ứng là lấy trung bình 3 giá trị này. Tuy nhiên, mắt con người chúng ta thì không nhạy cảm như nhau với 3 màu này. Ví dụ, mắt chúng ta rất nhạy cảm với màu green, trong khi blue thì sẽ hời hợt 1 chút. Do đó, chúng ta cần cân nhắc sử dụng các màu với các tỉ lệ khác nhau. Sau khi nghiên cứu chi tiết Grayscale Wikipedia Page, mình quyết định tính giá trị grayscale dựa trên công thức dưới đây:

bash

Vì thế mình cần lặp qua mỗi pixel của bức ảnh và thay thế nó bằng giá trị grayscale.

const canvas = document.getElementById['preview']

const fileInput = document.querySelector['input[type="file"]']

const context = canvas.getContext['2d']

fileInput.onchange = [e] => {

const file = e.target.files[0]

const reader = new FileReader[]

reader.onload = [event] => {

const image = new Image[]

image.onload = [] => {

canvas.width = image.width

canvas.height = image.height

context.drawImage[image, 0, 0]

}

image.src = event.target.result

}

reader.readAsDataURL[file]

}

9 API cung cấp function

GrayScale = 0.21 R + 0.72 G + 0.07 B

8 để chúng ta phân tách từng pixel của bức ảnh.

getImageData sẽ cho ra một object chứa thuộc tính

GrayScale = 0.21 R + 0.72 G + 0.07 B

9 là một Uint8ClampedArray. Data này là một mảng một chiều chứa các giá trị red, green, blue, alpha [RGBA] theo thứ tự, với các số nguyên có giá trị từ 0 - 255. Vì thế mình lặp qua mảng bằng cách tăng lên 4 mỗi lần lặp, lấy giá trị RGB từ 3 phần tử đầu tiên, tính toán tỉ lệ gray và sau đó tiếp tục cho đến hết.

grayRamp1 = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|[]1{}[]?-_+~i!lI;:,\"^`'. "

Lưu ý là RGBA khác RGBa nha. Với RGBA thì A là alpha đại diện cho độ trong suốt có giá trị là số nguyên từ 0 - 255. Còn RGBa được sử dụng phổ biến trong CSS với a cũng là alpha nhưng giá trị là số thập phân từ 0 - 1. Nghe có vẻ RGBa có thể biểu thị được alpha nhiều hơn vì không giới hạn về mặt lý thuyết nhưng điều này về mặt phần cứng thì không phải vậy. Có sự khác biệt nào giữa alpha

const toGrayScale = [r, g, b] => 0.21 * r + 0.72 * g + 0.07 * b

const convertToGrayScales = [context, width, height] => {

const imageData = context.getImageData[0, 0, width, height]

const grayScales = []

for [let i = 0; i 0.21 * r + 0.72 * g + 0.07 * b

const convertToGrayScales = [context, width, height] => {

const imageData = context.getImageData[0, 0, width, height]

const grayScales = []

for [let i = 0; i 0.21 * r + 0.72 * g + 0.07 * b

const convertToGrayScales = [context, width, height] => {

const imageData = context.getImageData[0, 0, width, height]

const grayScales = []

for [let i = 0; i 0.21 * r + 0.72 * g + 0.07 * b

const convertToGrayScales = [context, width, height] => {

const imageData = context.getImageData[0, 0, width, height]

const grayScales = []

for [let i = 0; i

Bài Viết Liên Quan

Chủ Đề