|
224 | 224 | "errorrandom":"Randomised Error Diffusion",
|
225 | 225 | "bayer2":"2x2 Bayer",
|
226 | 226 | "bayer4":"4x4 Bayer",
|
| 227 | + "comic":"Comic book" |
227 | 228 | };
|
228 | 229 |
|
229 |
| - const BAYER2 = [ |
230 |
| - [ 0, 2 ], |
231 |
| - [ 3, 1 ] |
232 |
| - ]; |
233 |
| - const BAYER4 = [ |
234 |
| - [ 0, 8, 2,10], |
235 |
| - [12, 4,14, 6], |
236 |
| - [ 3,11, 1, 9], |
237 |
| - [15, 7,13, 5] |
| 230 | + const DITHER = { |
| 231 | + BAYER2 : [ |
| 232 | + [ 0, 2 ], |
| 233 | + [ 3, 1 ] |
| 234 | + ], |
| 235 | + BAYER4 : [ |
| 236 | + [ 0, 8, 2,10], |
| 237 | + [12, 4,14, 6], |
| 238 | + [ 3,11, 1, 9], |
| 239 | + [15, 7,13, 5] |
| 240 | + ], |
| 241 | + COMICR : [ |
| 242 | + [-18,-16,-13,-15,-14,-9,-9,-15], |
| 243 | + [-12,-4,6,-4,-12,-4,6,-4], |
| 244 | + [-6,6,21,6,-6,6,21,6], |
| 245 | + [-11,0,13,0,-11,-4,6,-4], |
| 246 | + [-14,0,13,1,-10,-9,-9,-15], |
| 247 | + [-13,6,21,10,3,6,-4,-16], |
| 248 | + [-16,-4,6,3,10,21,6,-13], |
| 249 | + [-19,-16,-13,-12,-3,6,-4,-16] |
| 250 | + ], |
| 251 | + COMICG : [ |
| 252 | + [6,-13,-16,-4,6,3,10,21], |
| 253 | + [-4,-16,-19,-16,-13,-12,-3,6], |
| 254 | + [-9,-15,-18,-16,-13,-15,-14,-9], |
| 255 | + [6,-4,-12,-4,6,-4,-12,-4], |
| 256 | + [21,6,-6,6,21,6,-6,6], |
| 257 | + [6,-4,-11,0,13,0,-11,-4], |
| 258 | + [-9,-15,-14,0,13,1,-10,-9], |
| 259 | + [-4,-16,-13,6,21,10,3,6] |
| 260 | + ], |
| 261 | + COMICB : [ |
| 262 | + [-13,-20,-20,-16,3,32,37,10], |
| 263 | + [-16,-20,-20,-19,-12,3,10,-3], |
| 264 | + [-18,-16,-13,-16,-18,-16,-13,-16], |
| 265 | + [-12,3,10,-3,-16,-20,-20,-19], |
| 266 | + [3,32,37,10,-13,-20,-20,-16], |
| 267 | + [10,37,32,4,-12,-13,-16,-12], |
| 268 | + [-2,10,3,-8,-2,10,3,-8], |
| 269 | + [-12,-13,-16,-12,10,37,32,4] |
| 270 | + ], |
| 271 | + }; |
| 272 | + |
| 273 | + /* |
| 274 | + // to make the COMIC dither pattern |
| 275 | + // the idea is this is a pattern of blobs a bit like |
| 276 | + // you might get in a newspaper - hexagonal-ish, and different patterns for R,G and B |
| 277 | + let G = [ // gaussian |
| 278 | + [ 1, 4, 7, 4, 1], |
| 279 | + [ 4,16,26,16, 4], |
| 280 | + [ 7,26,41,26, 7], |
| 281 | + [ 4,16,26,16, 4], |
| 282 | + [ 1, 4, 7, 4, 1], |
238 | 283 | ];
|
239 | 284 |
|
| 285 | + let NR = [], NG = [], NB = []; |
| 286 | + for (var i=0;i<8;i++) { |
| 287 | + NR[i] = [0,0,0,0,0,0,0,0]; |
| 288 | + NG[i] = [0,0,0,0,0,0,0,0]; |
| 289 | + NB[i] = [0,0,0,0,0,0,0,0]; |
| 290 | + } |
| 291 | + function blob(x,y,ox,oy) { |
| 292 | + NR[(y+oy)&7][(x+ox)&7] += G[y][x]; |
| 293 | + NG[(y+oy+2)&7][(x+ox+2)&7] += G[y][x]; |
| 294 | + NB[(y+oy+10-ox)&7][(x+ox+oy)&7] += G[y][x]; |
| 295 | + } |
| 296 | + for (var y=0;y<G.length;y++) |
| 297 | + for (var x=0;x<G.length;x++) { |
| 298 | + blob(x,y,0,0); |
| 299 | + blob(x,y,4,0); |
| 300 | + blob(x,y,0,3); |
| 301 | + blob(x,y,3,4); |
| 302 | + } |
| 303 | + let offset = 20; |
| 304 | + NR = NR.map(R=>R.map(n=>n-offset)); |
| 305 | + NG = NG.map(R=>R.map(n=>n-offset)); |
| 306 | + NB = NB.map(R=>R.map(n=>n-offset)); |
| 307 | + console.log(" COMICR : [\n "+JSON.stringify(NR).replaceAll("],[","],\n [").substr(1)+",\n"+ |
| 308 | + " COMICG : [\n "+JSON.stringify(NG).replaceAll("],[","],\n [").substr(1)+",\n"+ |
| 309 | + " COMICB : [\n "+JSON.stringify(NB).replaceAll("],[","],\n [").substr(1)+",\n"); |
| 310 | +*/ |
| 311 | + |
| 312 | + |
240 | 313 | function clip(x) {
|
241 | 314 | if (x<0) return 0;
|
242 | 315 | if (x>255) return 255;
|
|
331 | 404 | eg += Math.random()*128 - 64;
|
332 | 405 | eb += Math.random()*128 - 64;
|
333 | 406 | } else if (options.diffusion == "bayer2") {
|
334 |
| - var th = BAYER2[x&1][y&1]*64 - 96; |
| 407 | + var th = DITHER.BAYER2[x&1][y&1]*64 - 96; |
335 | 408 | er += th;
|
336 | 409 | eg += th;
|
337 | 410 | eb += th;
|
338 | 411 | } else if (options.diffusion == "bayer4") {
|
339 |
| - var th = BAYER4[x&3][y&3]*16 - 96; |
| 412 | + var th = DITHER.BAYER4[x&3][y&3]*16 - 96; |
340 | 413 | er += th;
|
341 | 414 | eg += th;
|
342 | 415 | eb += th;
|
| 416 | + } if (options.diffusion == "comic") { |
| 417 | + er += DITHER.COMICR[x&7][y&7]*3 + Math.random()*24 - 12; |
| 418 | + eg += DITHER.COMICG[x&7][y&7]*3 + Math.random()*24 - 12; |
| 419 | + eb += DITHER.COMICB[x&7][y&7]*3 + Math.random()*24 - 12; |
343 | 420 | }
|
344 | 421 | if (options.inverted) {
|
345 | 422 | r=255-r;
|
|
558 | 635 |
|
559 | 636 | //if the image has fewer colors than our palette we need to fill in the remaining entries
|
560 | 637 | while (pixelCols.length < bppRange) {
|
561 |
| - pixelCols.push(0); |
| 638 | + pixelCols.push(0); |
562 | 639 | }
|
563 | 640 | // debugging...
|
564 | 641 | //console.log("Palette",pixelCols.map(c=>({col:0|c, cnt:colorUses[c], score:scores[c], rgb:(FORMATS["rgb565"].toRGBA(c)&0xFFFFFF).toString(16).padStart(6,"0")})));
|
|
0 commit comments