paint-by-numbers

Relaxing paint-by-numbers game  https://p.ce9e.org/paint-by-numbers/
git clone https://git.ce9e.org/paint-by-numbers.git

commit
2ec0f32913ad73d7c98420ba5a0db5f33803ecb5
parent
76d3b8809c6cf3828c031be9c28e325f26b88850
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2025-08-11 06:57
consider rounding during distance calculation

avoid clusters that end up with an identical hex code

Diffstat

M js/color.js 15 +++++++++++++++
M js/loader.js 13 ++-----------

2 files changed, 17 insertions, 11 deletions


diff --git a/js/color.js b/js/color.js

@@ -63,3 +63,18 @@ export var hex = function(rgb) {
   63    63         + Math.floor(rgb[2] / 16).toString(16);
   64    64 };
   65    65 
   -1    66 export var roundLab = function(lab) {
   -1    67     var rgb = labToRgb(lab);
   -1    68     rgb = rgb.map(c => Math.floor(c / 16) * 16);
   -1    69     return rgbToLab(rgb);
   -1    70 };
   -1    71 
   -1    72 export var distance = function(lab1, lab2) {
   -1    73     var rounded1 = roundLab(lab1);
   -1    74     var rounded2 = roundLab(lab2);
   -1    75     return Math.sqrt(
   -1    76         Math.pow(rounded1[0] - rounded2[0], 2)
   -1    77         + Math.pow(rounded1[1] - rounded2[1], 2)
   -1    78         + Math.pow(rounded1[2] - rounded2[2], 2)
   -1    79     );
   -1    80 };

diff --git a/js/loader.js b/js/loader.js

@@ -1,4 +1,4 @@
    1    -1 import { rgbToLab, labToRgb, hex } from './color.js';
   -1     1 import { rgbToLab, labToRgb, distance, hex } from './color.js';
    2     2 
    3     3 var file2img = function(file) {
    4     4     // FIXME: uses unsafe inline image
@@ -28,21 +28,12 @@ var img2data = function(img, width) {
   28    28     return _ctx.getImageData(0, 0, _canvas.width, _canvas.height);
   29    29 };
   30    30 
   31    -1 
   32    31 class Cluster {
   33    32     constructor(center) {
   34    33         this.center = center;
   35    34         this.count = 1;
   36    35     }
   37    36 
   38    -1     distance(color) {
   39    -1         return Math.sqrt(
   40    -1             Math.pow(this.center[0] - color[0], 2)
   41    -1             + Math.pow(this.center[1] - color[1], 2)
   42    -1             + Math.pow(this.center[2] - color[2], 2)
   43    -1         );
   44    -1     }
   45    -1 
   46    37     add(color) {
   47    38         this.center = [
   48    39             (this.center[0] * this.count + color[0]) / (this.count + 1),
@@ -65,7 +56,7 @@ var analyze = function(img) {
   65    56         ]);
   66    57 
   67    58         for (j = 0; j < clusters.length; j++) {
   68    -1             if (clusters[j].distance(lab) < 0.08) {
   -1    59             if (distance(clusters[j].center, lab) < 0.08) {
   69    60                 clusters[j].add(lab);
   70    61                 out.push(j + 1);
   71    62                 break;