Skip to content

Commit 4914183

Browse files
authored
Merge pull request #5 from williamfridh/dev
Dev
2 parents e00b8cf + 51a6bac commit 4914183

File tree

4 files changed

+83
-55
lines changed

4 files changed

+83
-55
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ Download and include **Paletteron.min.js** or **Paletteron.js** from the dist fo
3232

3333
### getPalette()
3434
**PARAMETERS:**
35-
1. scale - The scale to downscale the image with (recommended is 0.3).
36-
2. colorsToPick - The amount of colors to pick from the image (recommended is 5).
35+
1. colorsToPick - The amount of colors to pick from the image (recommended is 5).
36+
2. speed - The speed of the algorithm (fast, medium, slow) (recommended is medium).
3737
3. minCoverage - The minimum coverage of a color to be included in the palette (recommended is 0).
3838
4. minWhiteDistance - Percentage of maximum color space distance to be min to include color (recommended is 0).
3939
5. minBlackDistance - Percentage of maximum color space distance to be min to include color (recommended is 0).
@@ -53,6 +53,8 @@ python -m http.server 8000
5353

5454
## Examples
5555

56+
**See file:** test/all.html
57+
5658
### Code Example
5759

5860
Before sending the img element to Palettereon, you need to make sure it's fully loaded. This can be done in many different ways. For instance:

dist/Paletteron.js

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
* 5. Print the palette to an HTML element for debugging by calling printDebuggingPalette.
1616
*
1717
* PARAMETERS:
18-
* 1. scale - The scale to downscale the image with (recommended is 0.3).
19-
* 2. colorsToPick - The amount of colors to pick from the image (recommended is 5).
18+
* 1. colorsToPick - The amount of colors to pick from the image (recommended is 5).
19+
* 2. speed - The speed of the algorithm (fast, medium, slow) (recommended is medium).
2020
* 3. minCoverage - The minimum coverage of a color to be included in the palette (recommended is 0).
2121
* 4. minWhiteDistance - Percentage of maximum color space distance to be min to include color (recommended is 0).
2222
* 5. minBlackDistance - Percentage of maximum color space distance to be min to include color (recommended is 0).
@@ -29,7 +29,7 @@
2929
* Author: William Fridh
3030
* GitHub: https://github.com/williamfridh
3131
* Repository: https://github.com/williamfridh/Paletteron-Image-Scanner-Palette-Maker
32-
* Version: 1.0.2
32+
* Version: 1.1.0
3333
*/
3434

3535
class Paletteron {
@@ -48,16 +48,14 @@ class Paletteron {
4848
* Opertunity to set the scale, colors to pick and min coverage.
4949
* Larger scale will result in faster processing but less accurate results.
5050
*
51-
* @param {number} scale - The scale to downscale the image with.
5251
* @param {number} colorsToPick - The amount of colors to pick from the image.
52+
* @param {string} speed - The speed of the algorithm (fast, medium, slow).
5353
* @param {number} minCoverage - The minimum coverage of a color to be included in the palette.
5454
* @param {number} minWhiteDistance - Percentage of maximum color space distance to be min to include color.
5555
* @param {number} minBlackDistance - Percentage of maximum color space distance to be min to include color.
5656
*/
57-
constructor(scale, colorsToPick, minCoverage, minWhiteDistance, minBlackDistance) {
57+
constructor(colorsToPick, speed, minCoverage, minWhiteDistance, minBlackDistance) {
5858
// Check input values
59-
if (scale && (scale < 0 || scale > 1))
60-
throw new Error(`Scale must be between 0 and 1.`)
6159
if (colorsToPick && (colorsToPick < 1 || colorsToPick > Paletteron.MAX_COLORS_AMOUNT))
6260
throw new Error(`Colors to pick must be between 1 and ${Paletteron.MAX_COLORS_AMOUNT}.`)
6361
if (minCoverage && (minCoverage < 0 || minCoverage > 1))
@@ -67,11 +65,30 @@ class Paletteron {
6765
if (minBlackDistance && (minBlackDistance < 0 || minBlackDistance > 1))
6866
throw new Error(`Ignore dark must be between 0 and 1.`)
6967
// Set the values
70-
this.scale = scale || 0.2
7168
this.colorsToPick = colorsToPick || 5
69+
this.speed = speed || 'medium'
7270
this.minCoverage = minCoverage || 0
7371
this.minWhiteDistance = minWhiteDistance || 0
7472
this.minBlackDistance = minBlackDistance || 0
73+
74+
switch (this.speed) {
75+
case 'fast':
76+
this.averageColorDistanceJump = 8;
77+
this.scale = 0.2;
78+
break;
79+
case 'medium':
80+
this.averageColorDistanceJump = 5;
81+
this.scale = 0.3;
82+
break;
83+
case 'slow':
84+
this.averageColorDistanceJump = 3;
85+
this.scale = 0.5;
86+
break;
87+
default:
88+
averageColorDistanceJump = 5;
89+
this.scale = 0.3;
90+
console.warn(`Speed not recognized, defaulting to medium.`);
91+
}
7592
}
7693

7794
/**
@@ -94,22 +111,22 @@ class Paletteron {
94111

95112
// Process the pixels to find the most common colors
96113
const flattenedColors = this.flattenColors(pixels);
97-
console.log(`flattenedColors: `, flattenedColors);
114+
//console.log(`flattenedColors: `, flattenedColors);
98115

99116
const colorsWithoutBrightDark = this.removeBrightDarkColors(flattenedColors);
100-
console.log(`colorsWithoutBrightDark: `, colorsWithoutBrightDark);
117+
//console.log(`colorsWithoutBrightDark: `, colorsWithoutBrightDark);
101118

102-
const bundledColors = this.bundleColors(colorsWithoutBrightDark);
103-
console.log(`bundledColors: `, bundledColors);
119+
const noLowCoverageColors = this.removeLowCoverageColors(colorsWithoutBrightDark, pixels.length);
120+
//console.log(`noLowCoverageColors: `, noLowCoverageColors);
104121

105-
const noLowCoverageColors = this.removeLowCoverageColors(bundledColors, pixels.length);
106-
console.log(`noLowCoverageColors: `, noLowCoverageColors);
122+
const bundledColors = this.bundleColors(noLowCoverageColors);
123+
//console.log(`bundledColors: `, bundledColors);
107124

108-
const colorsWithScore = this.calculateScore(noLowCoverageColors);
109-
console.log(`colorsWithScore: `, colorsWithScore);
125+
const colorsWithScore = this.calculateScore(bundledColors);
126+
//console.log(`colorsWithScore: `, colorsWithScore);
110127

111128
const finalColors = this.finalizeColors(colorsWithScore);
112-
console.log(`finalColors: `, finalColors);
129+
//console.log(`finalColors: `, finalColors);
113130

114131
// Cleanup the canvas
115132
canvas.remove();
@@ -152,6 +169,7 @@ class Paletteron {
152169
* @returns {[HTMLCanvasElement, CanvasRenderingContext2D]} - The canvas and its context.
153170
*/
154171
downscale(picture) {
172+
155173
// Calculate new dimensions
156174
const w = picture.width * this.scale;
157175
const h = picture.height * this.scale;
@@ -165,12 +183,6 @@ class Paletteron {
165183
// Draw the picture on the canvas
166184
context.drawImage(picture, 0, 0, w, h);
167185

168-
// Append the canvas to the document (hidden)
169-
document.body.appendChild(canvas);
170-
canvas.style.position = 'fixed';
171-
canvas.style.top = '9999px';
172-
canvas.style.left = '9999px';
173-
174186
// Return the canvas and its context
175187
return [canvas, context];
176188
}
@@ -266,8 +278,8 @@ class Paletteron {
266278
let colorPairs = 0;
267279

268280
// Loop over each pair of colors
269-
for (let i = 0; i < colors.length; i++) {
270-
for (let j = i + 1; j < colors.length; j++) {
281+
for (let i = 0; i < colors.length + this.averageColorDistanceJump; i = i + this.averageColorDistanceJump) {
282+
for (let j = i + this.averageColorDistanceJump; j < colors.length; j = j + this.averageColorDistanceJump) {
271283
// Calculate the distance between the two colors
272284
totalColorSpaceDistance += this.calculateDistance(
273285
[colors[i].r, colors[i].g, colors[i].b],
@@ -291,12 +303,13 @@ class Paletteron {
291303
* @returns {Object[]} - The bundled array of color objects.
292304
*/
293305
bundleColors(colors) {
294-
// Sort the array by the amount of pixels of each color to prioritize the most common colors.
295-
colors.sort((a, b) => b.amount - a.amount);
296306

297307
// Calculate the average color distance.
298308
const averageColorDistance = this.findAverageColorDistance(colors);
299309

310+
// Sort the array by the amount of pixels of each color to prioritize the most common colors.
311+
colors.sort((a, b) => b.amount - a.amount);
312+
300313
// Bundle/merge colors that are close to each other.
301314
for (let i = 0; i < colors.length; i++) {
302315
for (let j = i + 1; j < colors.length; j++) {

dist/Paletteron.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/all.html

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,49 @@
33
<head>
44
<title>Test</title>
55
<script src="https://cdnjs.cloudflare.com/ajax/libs/color-thief/2.3.0/color-thief.umd.js"></script>
6-
<script src="../dist/Paletteron.js"></script>
6+
<script src="../dist/Paletteron.min.js"></script>
77
<script>
88
document.addEventListener('DOMContentLoaded', function() {
99
console.log('DOMContentLoaded');
10-
const paletteron = new Paletteron(0.3, 5);
10+
const paletteron = new Paletteron(5);
11+
let totalTime = 0;
12+
let callCount = 0;
13+
1114
// For each image
1215
const imgHolders = document.querySelectorAll('.img-holder');
1316
imgHolders.forEach(imgHolder => {
14-
const img = imgHolder.querySelector('img');
15-
const paletteElement = imgHolder.querySelector('.palette');
17+
const img = imgHolder.querySelector('img');
18+
const paletteElement = imgHolder.querySelector('.palette');
19+
20+
// Add listener to wait for image to be loaded
21+
const processImage = () => {
22+
console.log('Processing image');
23+
const startTime = performance.now();
24+
const palette = paletteron.getPalette(img);
25+
const endTime = performance.now();
26+
totalTime += (endTime - startTime);
27+
callCount++;
28+
paletteron.printDebuggingPalette(palette, paletteElement);
29+
};
30+
31+
if (img.complete) {
32+
console.log('Image already loaded');
33+
processImage();
34+
} else {
35+
img.addEventListener('load', () => {
36+
console.log('Image loaded');
37+
processImage();
38+
});
39+
}
40+
});
1641

17-
// Add listener to wait for image to be loaded
18-
if (img.complete) {
19-
console.log('Image already loaded');
20-
console.time('getPalette');
21-
const palette = paletteron.getPalette(img);
22-
console.timeLog('getPalette');
23-
paletteron.printDebuggingPalette(palette, paletteElement);
24-
console.timeEnd('getPalette');
25-
} else {
26-
img.addEventListener('load', () => {
27-
console.log('Image loaded');
28-
console.time('getPalette');
29-
const palette = paletteron.getPalette(img);
30-
console.timeLog('getPalette');
31-
paletteron.printDebuggingPalette(palette, paletteElement);
32-
console.timeEnd('getPalette');
33-
});
34-
}
35-
42+
// Log the average time after all images are processed
43+
window.addEventListener('load', () => {
44+
if (callCount > 0) {
45+
console.log(`Average time per getPalette call: ${totalTime / callCount} ms`);
46+
} else {
47+
console.log('No getPalette calls were made.');
48+
}
3649
});
3750
});
3851
</script>
@@ -53,7 +66,7 @@
5366
<div class="img-holder">
5467
<img src="img/Localiza.jpg" width="400" />
5568
<div class="palette"></div>
56-
</div><!--
69+
</div>
5770
<div class="img-holder">
5871
<img src="img/Bite.jpg" width="400" />
5972
<div class="palette"></div>
@@ -89,7 +102,7 @@
89102
<div class="img-holder">
90103
<img src="img/Lipton.jpg" width="400" />
91104
<div class="palette"></div>
92-
</div>-->
105+
</div>
93106
</body>
94107
</html>
95108

0 commit comments

Comments
 (0)