-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvectorize.js
More file actions
141 lines (116 loc) · 4.06 KB
/
vectorize.js
File metadata and controls
141 lines (116 loc) · 4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
let map = []
export class Vectorize {
constructor(url) {
let img = new Image()
img.src = url
img.onload = () => {
let imgData
let sorted
let colorMap
let canvas = document.createElement("canvas")
let ctx = canvas.getContext("2d")
canvas.height = img.height
canvas.width = img.width
ctx.drawImage(img, 0, 0)
imgData = ctx.getImageData(0, 0, img.width, img.height).data
sorted = sortPixels(imgData)
colorMap = setPixels(sorted)
map = reShape(colorMap, img.height, img.width)
localStorage.setItem("image", JSON.stringify(map))
}
this.map = map = JSON.parse(localStorage.getItem("image"))
return map
}
}
Array.prototype.draw2d = (scale = 1) => {
let zcanv = document.createElement("canvas")
let ztx = zcanv.getContext("2d")
document.body.appendChild(zcanv)
zcanv.height = map[0].length * scale
zcanv.width = map.length * scale
drawArray(ztx, map, scale)
}
function sortPixels(array) {
// TODO: add handler for transparent pixels (r=0, g=0, b=0, a=0)
let out = [] // our temporary array for sorting
// read image data
for (let i = 0; i < array.length; i++) {
/* we only want the rgba values 255 and 0,
* a white pixel is r=255, g=255, b=255, a=255
* a black pixel is r=0, g=0, b=0, a=255 */
if (array[i] == 255) {
out.push(255)
} else if (array[i] == 0) {
out.push(0)
} else {
console.error("⚠️ Please provide a black and white image")
// here we use break so we dont get the same error for each colored pixel
break
}
}
return out
}
function setPixels(array) {
let a = []
// for each pixel, check if its black or white, put into new array
for (let n = 0; n < array.length; n += 4) {
// shorthand if statement: if white pixel, push 1, if black, push 0
array[n] == 255 ? a.push(1) : a.push(0)
}
return a
}
function reShape(array, rows, cols) {
// convert 1d array to 2d
var copy = array.slice(0) // Copy all elements.
array.length = 0 // Clear out existing array.
// go through each (x, y) pair
for (var x = 0; x < rows; x++) {
var row = []
// build array of length rows (image width)
for (var y = 0; y < cols; y++) {
var n = x * cols + y
if (n < copy.length) {
row.push(copy[n])
}
}
// push that row to the 2d array
array.push(row)
}
// return rotated 2d array
return transpose(array)
}
function transpose(matrix) {
// rotate 2d array 90 degrees to the right
return matrix.reduce(
(prev, next) => next.map((item, i) => (prev[i] || []).concat(next[i])),
[]
)
}
export function drawArray(
ctx,
array,
scale = 1,
colors = { fg: "white", bg: "black" }
) {
// loop through each indice
for (let x = 0; x < array.length; x++) {
for (let y = 0; y < array[0].length; y++) {
if (array[x][y] == 1) {
// '1' == black
ctx.fillStyle = colors.fg
// you could add a different width or height arguments for each square
// it would be interesting but sort of pointless, so we do it this way
// here we need (x * scale) cause that will give us the coordinate to draw on the canvas
ctx.fillRect(x * scale, y * scale, scale, scale)
}
if (array[x][y] == 0) {
// '0' == white
ctx.fillStyle = colors.bg
// you could add a different width or height arguments for each square
// it would be interesting but sort of pointless, so we do it this way
// here we need (x * scale), etc. cause that will give us the coordinate to draw on the canvas
ctx.fillRect(x * scale, y * scale, scale, scale)
}
}
}
}