Skip to content

Commit 3a55438

Browse files
committed
Add 'comic' dithering mode
1 parent 7e42839 commit 3a55438

File tree

1 file changed

+89
-12
lines changed

1 file changed

+89
-12
lines changed

imageconverter.js

+89-12
Original file line numberDiff line numberDiff line change
@@ -224,19 +224,92 @@
224224
"errorrandom":"Randomised Error Diffusion",
225225
"bayer2":"2x2 Bayer",
226226
"bayer4":"4x4 Bayer",
227+
"comic":"Comic book"
227228
};
228229

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],
238283
];
239284
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+
240313
function clip(x) {
241314
if (x<0) return 0;
242315
if (x>255) return 255;
@@ -331,15 +404,19 @@
331404
eg += Math.random()*128 - 64;
332405
eb += Math.random()*128 - 64;
333406
} 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;
335408
er += th;
336409
eg += th;
337410
eb += th;
338411
} 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;
340413
er += th;
341414
eg += th;
342415
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;
343420
}
344421
if (options.inverted) {
345422
r=255-r;
@@ -558,7 +635,7 @@
558635

559636
//if the image has fewer colors than our palette we need to fill in the remaining entries
560637
while (pixelCols.length < bppRange) {
561-
pixelCols.push(0);
638+
pixelCols.push(0);
562639
}
563640
// debugging...
564641
//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

Comments
 (0)