color-util-helpers 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # Color Utilities
2
+
3
+ ## Color Conversion
4
+
5
+ Converts RGB to HEX or HEX to RGB
6
+
7
+ ### Usage
8
+
9
+ rgbToHex(rgb: number[]): string
10
+
11
+ hexToRgb(hex: string): string
12
+
13
+
14
+ ## Color Pallette
15
+
16
+ define image path
17
+
18
+ this.colorSelectionService.getColorsFromImage('../assets/sample2.jpg')
19
+
20
+ ### Usage
21
+
22
+ this.colorSelectionService.palette.subscribe(data => this.palette = data)
23
+
24
+ ### Template Usage
25
+
26
+ <div *ngFor="let color of palette">
27
+ <div style="display: flex;">
28
+ <div
29
+ class="box"
30
+ [style.background-color]="color.color"
31
+ >
32
+ Color
33
+ </div>
34
+ <div
35
+ class="box"
36
+ [style.background-color]="color.complementaryColor"
37
+ >
38
+ Complementary
39
+ </div>
40
+ </div>
41
+ </div>
42
+
43
+ CSS Style
44
+
45
+ CSS
46
+ .box {
47
+ width: 100px;
48
+ height: 100px;
49
+ border: solid thin black;
50
+ color: black;
51
+ margin: 4px;
52
+ padding: 16px;
53
+ display: flex;
54
+ flex-wrap: wrap;
55
+ align-content: center;
56
+ justify-content: center;
57
+ }
58
+
59
+ ## Text Color
60
+
61
+ Provide a color that is used for a background and then provide the lightColor and darkColor
62
+ The function will return the appropriate color based on the background color provided
63
+
64
+ ### Usage
65
+
66
+ textColorForBgColor(bgColor: string, lightColor: string, darkColor: string)
Binary file
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ export * from './public-api';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sb3ItdXRpbC1oZWxwZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vcHJvamVjdHMvY29sb3ItdXRpbHMvc3JjL2NvbG9yLXV0aWwtaGVscGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILGNBQWMsY0FBYyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBHZW5lcmF0ZWQgYnVuZGxlIGluZGV4LiBEbyBub3QgZWRpdC5cbiAqL1xuXG5leHBvcnQgKiBmcm9tICcuL3B1YmxpYy1hcGknO1xuIl19
@@ -0,0 +1,39 @@
1
+ import { Injectable } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ export class ColorConversionService {
4
+ constructor() {
5
+ this.componentToHex = (c) => {
6
+ const hex = c.toString(16);
7
+ return hex.length === 1 ? "0" + hex : hex;
8
+ };
9
+ }
10
+ rgbToHex(rgb) {
11
+ if (rgb === null || rgb.length !== 3 || rgb.some(value => value < 0 || value > 255))
12
+ return '';
13
+ const [r, g, b] = rgb;
14
+ const hexR = this.componentToHex(r);
15
+ const hexG = this.componentToHex(g);
16
+ const hexB = this.componentToHex(b);
17
+ return "#" + hexR + hexG + hexB;
18
+ }
19
+ hexToRgb(hex) {
20
+ if (hex === null || hex === undefined)
21
+ return [];
22
+ hex = (hex.length === 3) ? hex + hex : hex;
23
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
24
+ return result ? [
25
+ parseInt(result[1], 16),
26
+ parseInt(result[2], 16),
27
+ parseInt(result[3], 16)
28
+ ] : [];
29
+ }
30
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorConversionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
31
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorConversionService, providedIn: 'root' }); }
32
+ }
33
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorConversionService, decorators: [{
34
+ type: Injectable,
35
+ args: [{
36
+ providedIn: 'root'
37
+ }]
38
+ }] });
39
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sb3ItY29udmVyc2lvbi5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvY29sb3ItdXRpbHMvc3JjL2xpYi9jb2xvci1jb252ZXJzaW9uLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7QUFLM0MsTUFBTSxPQUFPLHNCQUFzQjtJQUhuQztRQWVVLG1CQUFjLEdBQUcsQ0FBQyxDQUFTLEVBQUUsRUFBRTtZQUNyQyxNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQzNCLE9BQU8sR0FBRyxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUM1QyxDQUFDLENBQUE7S0FjRjtJQTNCQyxRQUFRLENBQUMsR0FBb0I7UUFDM0IsSUFBSSxHQUFHLEtBQUssSUFBSSxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxJQUFJLEtBQUssR0FBRyxHQUFHLENBQUM7WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUUvRixNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUM7UUFDdEIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEMsT0FBTyxHQUFHLEdBQUcsSUFBSSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7SUFDbEMsQ0FBQztJQU9ELFFBQVEsQ0FBQyxHQUE4QjtRQUNyQyxJQUFJLEdBQUcsS0FBSyxJQUFJLElBQUksR0FBRyxLQUFLLFNBQVM7WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUVqRCxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDM0MsTUFBTSxNQUFNLEdBQUcsMkNBQTJDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRXJFLE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQztZQUNkLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3ZCLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3ZCLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO1NBQ3hCLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNULENBQUM7K0dBNUJVLHNCQUFzQjttSEFBdEIsc0JBQXNCLGNBRnJCLE1BQU07OzRGQUVQLHNCQUFzQjtrQkFIbEMsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcblxyXG5ASW5qZWN0YWJsZSh7XHJcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBDb2xvckNvbnZlcnNpb25TZXJ2aWNlIHtcclxuXHJcbiAgcmdiVG9IZXgocmdiOiBudW1iZXJbXSB8IG51bGwpOiBzdHJpbmcge1xyXG4gICAgaWYgKHJnYiA9PT0gbnVsbCB8fCByZ2IubGVuZ3RoICE9PSAzIHx8IHJnYi5zb21lKHZhbHVlID0+IHZhbHVlIDwgMCB8fCB2YWx1ZSA+IDI1NSkpIHJldHVybiAnJztcclxuXHJcbiAgICBjb25zdCBbciwgZywgYl0gPSByZ2I7XHJcbiAgICBjb25zdCBoZXhSID0gdGhpcy5jb21wb25lbnRUb0hleChyKTtcclxuICAgIGNvbnN0IGhleEcgPSB0aGlzLmNvbXBvbmVudFRvSGV4KGcpO1xyXG4gICAgY29uc3QgaGV4QiA9IHRoaXMuY29tcG9uZW50VG9IZXgoYik7XHJcbiAgICByZXR1cm4gXCIjXCIgKyBoZXhSICsgaGV4RyArIGhleEI7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNvbXBvbmVudFRvSGV4ID0gKGM6IG51bWJlcikgPT4ge1xyXG4gICAgY29uc3QgaGV4ID0gYy50b1N0cmluZygxNik7XHJcbiAgICByZXR1cm4gaGV4Lmxlbmd0aCA9PT0gMSA/IFwiMFwiICsgaGV4IDogaGV4O1xyXG4gIH1cclxuXHJcbiAgaGV4VG9SZ2IoaGV4OiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogbnVtYmVyW10ge1xyXG4gICAgaWYgKGhleCA9PT0gbnVsbCB8fCBoZXggPT09IHVuZGVmaW5lZCkgcmV0dXJuIFtdO1xyXG5cclxuICAgIGhleCA9IChoZXgubGVuZ3RoID09PSAzKSA/IGhleCArIGhleCA6IGhleDtcclxuICAgIGNvbnN0IHJlc3VsdCA9IC9eIz8oW2EtZlxcZF17Mn0pKFthLWZcXGRdezJ9KShbYS1mXFxkXXsyfSkkL2kuZXhlYyhoZXgpO1xyXG5cclxuICAgIHJldHVybiByZXN1bHQgPyBbXHJcbiAgICAgIHBhcnNlSW50KHJlc3VsdFsxXSwgMTYpLFxyXG4gICAgICBwYXJzZUludChyZXN1bHRbMl0sIDE2KSxcclxuICAgICAgcGFyc2VJbnQocmVzdWx0WzNdLCAxNilcclxuICAgIF0gOiBbXTtcclxuICB9XHJcbn1cclxuIl19
@@ -0,0 +1,37 @@
1
+ import { Directive, HostListener, EventEmitter, Output } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ export class ColorExtractorDirective {
4
+ constructor(elementRef, renderer) {
5
+ this.elementRef = elementRef;
6
+ this.renderer = renderer;
7
+ this.colorValue = new EventEmitter();
8
+ }
9
+ get currentElement() {
10
+ return window.getComputedStyle(this.elementRef.nativeElement);
11
+ }
12
+ onMouseEnter() {
13
+ // console.log('ENTER', this.currentElement)
14
+ this.colorValue.emit(this.currentElement.getPropertyValue('background-color'));
15
+ }
16
+ onMouseLeave() {
17
+ // console.log('LEAVE', this.currentElement.getPropertyValue('background-color'))
18
+ this.colorValue.emit('white');
19
+ }
20
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorExtractorDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive }); }
21
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ColorExtractorDirective, selector: "[getColor]", outputs: { colorValue: "colorValue" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, ngImport: i0 }); }
22
+ }
23
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorExtractorDirective, decorators: [{
24
+ type: Directive,
25
+ args: [{
26
+ selector: '[getColor]'
27
+ }]
28
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }]; }, propDecorators: { colorValue: [{
29
+ type: Output
30
+ }], onMouseEnter: [{
31
+ type: HostListener,
32
+ args: ['mouseenter']
33
+ }], onMouseLeave: [{
34
+ type: HostListener,
35
+ args: ['mouseleave']
36
+ }] } });
37
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sb3ItZXh0cmFjdG9yLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2NvbG9yLXV0aWxzL3NyYy9saWIvY29sb3ItZXh0cmFjdG9yLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUF5QixZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQzs7QUFLckcsTUFBTSxPQUFPLHVCQUF1QjtJQUlsQyxZQUFvQixVQUFzQixFQUFVLFFBQW1CO1FBQW5ELGVBQVUsR0FBVixVQUFVLENBQVk7UUFBVSxhQUFRLEdBQVIsUUFBUSxDQUFXO1FBRjdELGVBQVUsR0FBeUIsSUFBSSxZQUFZLEVBQVUsQ0FBQztJQUVFLENBQUM7SUFFM0UsSUFBSSxjQUFjO1FBQ2hCLE9BQU8sTUFBTSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUdELFlBQVk7UUFDViw0Q0FBNEM7UUFDNUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUE7SUFDaEYsQ0FBQztJQUdELFlBQVk7UUFDVixpRkFBaUY7UUFDakYsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDL0IsQ0FBQzsrR0FwQlUsdUJBQXVCO21HQUF2Qix1QkFBdUI7OzRGQUF2Qix1QkFBdUI7a0JBSG5DLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLFlBQVk7aUJBQ3ZCO3lIQUdXLFVBQVU7c0JBQW5CLE1BQU07Z0JBU1AsWUFBWTtzQkFEWCxZQUFZO3VCQUFDLFlBQVk7Z0JBTzFCLFlBQVk7c0JBRFgsWUFBWTt1QkFBQyxZQUFZIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGlyZWN0aXZlLCBFbGVtZW50UmVmLCBSZW5kZXJlcjIsIEhvc3RMaXN0ZW5lciwgRXZlbnRFbWl0dGVyLCBPdXRwdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW2dldENvbG9yXSdcbn0pXG5leHBvcnQgY2xhc3MgQ29sb3JFeHRyYWN0b3JEaXJlY3RpdmUge1xuXG4gIEBPdXRwdXQoKSBjb2xvclZhbHVlOiBFdmVudEVtaXR0ZXI8c3RyaW5nPiA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZiwgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyKSB7fVxuXG4gIGdldCBjdXJyZW50RWxlbWVudCgpIHtcbiAgICByZXR1cm4gd2luZG93LmdldENvbXB1dGVkU3R5bGUodGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignbW91c2VlbnRlcicpXG4gIG9uTW91c2VFbnRlcigpIHtcbiAgICAvLyBjb25zb2xlLmxvZygnRU5URVInLCB0aGlzLmN1cnJlbnRFbGVtZW50KVxuICAgIHRoaXMuY29sb3JWYWx1ZS5lbWl0KHRoaXMuY3VycmVudEVsZW1lbnQuZ2V0UHJvcGVydHlWYWx1ZSgnYmFja2dyb3VuZC1jb2xvcicpKVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignbW91c2VsZWF2ZScpXG4gIG9uTW91c2VMZWF2ZSgpIHtcbiAgICAvLyBjb25zb2xlLmxvZygnTEVBVkUnLCB0aGlzLmN1cnJlbnRFbGVtZW50LmdldFByb3BlcnR5VmFsdWUoJ2JhY2tncm91bmQtY29sb3InKSlcbiAgICB0aGlzLmNvbG9yVmFsdWUuZW1pdCgnd2hpdGUnKVxuICB9XG5cbn1cbiJdfQ==
@@ -0,0 +1,157 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { BehaviorSubject } from 'rxjs';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "./color-conversion.service";
5
+ export class ColorPalletteService {
6
+ constructor(colorConversionService) {
7
+ this.colorConversionService = colorConversionService;
8
+ // define image path
9
+ // this.colorSelectionService.getColorsFromImage('../assets/sample2.jpg')
10
+ // get colors
11
+ // this.colorSelectionService.palette.subscribe(data => this.palette = data)
12
+ // sample html
13
+ // <div *ngFor="let color of palette">
14
+ // <div style="display: flex;">
15
+ // <div
16
+ // class="box"
17
+ // [style.background-color]="color.color"
18
+ // >
19
+ // Color
20
+ // </div>
21
+ // <div
22
+ // class="box"
23
+ // [style.background-color]="color.complementaryColor"
24
+ // >
25
+ // Complementary
26
+ // </div>
27
+ // </div>
28
+ // </div>
29
+ // CSS
30
+ // .box {
31
+ // width: 100px;
32
+ // height: 100px;
33
+ // border: solid thin black;
34
+ // color: black;
35
+ // margin: 4px;
36
+ // padding: 16px;
37
+ // display: flex;
38
+ // flex-wrap: wrap;
39
+ // align-content: center;
40
+ // justify-content: center;
41
+ // }
42
+ this.palette = new BehaviorSubject([]);
43
+ }
44
+ getColorsFromImage(imagePath, colors = 3) {
45
+ const image = new Image();
46
+ image.src = imagePath;
47
+ image.onload = () => {
48
+ const data = this.generateColorPalette(image, colors) || [];
49
+ this.palette.next(data);
50
+ };
51
+ }
52
+ generateColorPalette(image, colorCount = 6) {
53
+ const canvas = document.createElement('canvas');
54
+ const context = canvas.getContext('2d');
55
+ if (!context || !image)
56
+ return;
57
+ canvas.width = image.width;
58
+ canvas.height = image.height;
59
+ context.drawImage(image, 0, 0);
60
+ // Get the image data
61
+ const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
62
+ const pixels = imageData.data;
63
+ const pixelCount = imageData.width * imageData.height;
64
+ // Build an array of RGB colors
65
+ const colors = [];
66
+ for (let i = 0; i < pixelCount; i++) {
67
+ const offset = i * 4;
68
+ const r = pixels[offset];
69
+ const g = pixels[offset + 1];
70
+ const b = pixels[offset + 2];
71
+ colors.push([r, g, b]);
72
+ }
73
+ // Apply color quantization using k-means clustering
74
+ const quantizedColors = this.kMeansColorQuantization(colors, colorCount);
75
+ // Order colors by luminance
76
+ quantizedColors.sort((color1, color2) => {
77
+ const luminance1 = this.getLuminance(color1);
78
+ const luminance2 = this.getLuminance(color2);
79
+ return luminance2 - luminance1;
80
+ });
81
+ const palette = quantizedColors.map(color => {
82
+ const complementaryColor = color.map(component => 255 - component);
83
+ const hexColor = this.colorConversionService.rgbToHex(color);
84
+ const hexComplementaryColor = this.colorConversionService.rgbToHex(complementaryColor);
85
+ return { color: hexColor, complementaryColor: hexComplementaryColor };
86
+ });
87
+ return palette;
88
+ }
89
+ getLuminance(color) {
90
+ const [r, g, b] = color;
91
+ return 0.299 * r + 0.587 * g + 0.114 * b;
92
+ }
93
+ calculateColorDistance(color1, color2) {
94
+ const [r1, g1, b1] = color1;
95
+ const [r2, g2, b2] = color2;
96
+ const dr = r2 - r1;
97
+ const dg = g2 - g1;
98
+ const db = b2 - b1;
99
+ return Math.sqrt(dr * dr + dg * dg + db * db);
100
+ }
101
+ calculateMeanColor(colors) {
102
+ let sumR = 0;
103
+ let sumG = 0;
104
+ let sumB = 0;
105
+ for (let i = 0; i < colors.length; i++) {
106
+ const [r, g, b] = colors[i];
107
+ sumR += r;
108
+ sumG += g;
109
+ sumB += b;
110
+ }
111
+ const meanR = Math.round(sumR / colors.length);
112
+ const meanG = Math.round(sumG / colors.length);
113
+ const meanB = Math.round(sumB / colors.length);
114
+ return [meanR, meanG, meanB];
115
+ }
116
+ kMeansColorQuantization(colors, k) {
117
+ const clusterCenters = [];
118
+ for (let i = 0; i < k; i++) {
119
+ const randomColor = colors[Math.floor(Math.random() * colors.length)];
120
+ clusterCenters.push(randomColor);
121
+ }
122
+ const clusters = [];
123
+ for (let i = 0; i < colors.length; i++) {
124
+ const color = colors[i];
125
+ let minDistance = Infinity;
126
+ let nearestCenter = null;
127
+ for (let j = 0; j < clusterCenters.length; j++) {
128
+ const center = clusterCenters[j];
129
+ const distance = this.calculateColorDistance(color, center);
130
+ if (distance < minDistance) {
131
+ minDistance = distance;
132
+ nearestCenter = center;
133
+ }
134
+ }
135
+ clusters.push({ color, center: nearestCenter });
136
+ }
137
+ const updatedCenters = [];
138
+ for (let i = 0; i < clusterCenters.length; i++) {
139
+ const center = clusterCenters[i];
140
+ const clusterColors = clusters.filter(c => c.center === center).map(c => c.color);
141
+ if (clusterColors.length > 0) {
142
+ const updatedCenter = this.calculateMeanColor(clusterColors);
143
+ updatedCenters.push(updatedCenter);
144
+ }
145
+ }
146
+ return updatedCenters;
147
+ }
148
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPalletteService, deps: [{ token: i1.ColorConversionService }], target: i0.ɵɵFactoryTarget.Injectable }); }
149
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPalletteService, providedIn: 'root' }); }
150
+ }
151
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPalletteService, decorators: [{
152
+ type: Injectable,
153
+ args: [{
154
+ providedIn: 'root'
155
+ }]
156
+ }], ctorParameters: function () { return [{ type: i1.ColorConversionService }]; } });
157
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sb3ItcGFsbGV0dGUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2NvbG9yLXV0aWxzL3NyYy9saWIvY29sb3ItcGFsbGV0dGUuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBQzFDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxNQUFNLENBQUE7OztBQU10QyxNQUFNLE9BQU8sb0JBQW9CO0lBMEMvQixZQUNVLHNCQUE4QztRQUE5QywyQkFBc0IsR0FBdEIsc0JBQXNCLENBQXdCO1FBekN4RCxvQkFBb0I7UUFDcEIseUVBQXlFO1FBRXpFLGFBQWE7UUFDYiw0RUFBNEU7UUFFNUUsY0FBYztRQUNkLHdDQUF3QztRQUN4QyxtQ0FBbUM7UUFDbkMsZUFBZTtRQUNmLDBCQUEwQjtRQUMxQixxREFBcUQ7UUFDckQsWUFBWTtRQUNaLGdCQUFnQjtRQUNoQixpQkFBaUI7UUFDakIsZUFBZTtRQUNmLDBCQUEwQjtRQUMxQixrRUFBa0U7UUFDbEUsWUFBWTtRQUNaLHdCQUF3QjtRQUN4QixpQkFBaUI7UUFDakIsYUFBYTtRQUNiLFNBQVM7UUFFVCxNQUFNO1FBQ04sV0FBVztRQUNYLG9CQUFvQjtRQUNwQixxQkFBcUI7UUFDckIsZ0NBQWdDO1FBQ2hDLG9CQUFvQjtRQUNwQixtQkFBbUI7UUFDbkIscUJBQXFCO1FBQ3JCLHFCQUFxQjtRQUNyQix1QkFBdUI7UUFDdkIsNkJBQTZCO1FBQzdCLCtCQUErQjtRQUMvQixJQUFJO1FBRUksWUFBTyxHQUFHLElBQUksZUFBZSxDQUFrRCxFQUFFLENBQUMsQ0FBQTtJQUl0RixDQUFDO0lBRUwsa0JBQWtCLENBQUMsU0FBaUIsRUFBRSxNQUFNLEdBQUcsQ0FBQztRQUU5QyxNQUFNLEtBQUssR0FBRyxJQUFJLEtBQUssRUFBRSxDQUFBO1FBQ3pCLEtBQUssQ0FBQyxHQUFHLEdB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QyxVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJ1xyXG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJ1xyXG5pbXBvcnQgeyBDb2xvckNvbnZlcnNpb25TZXJ2aWNlIH0gZnJvbSAnLi9jb2xvci1jb252ZXJzaW9uLnNlcnZpY2UnXHJcblxyXG5ASW5qZWN0YWJsZSh7XHJcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBDb2xvclBhbGxldHRlU2VydmljZSB7XHJcblxyXG4gIC8vIGRlZmluZSBpbWFnZSBwYXRoXHJcbiAgLy8gdGhpcy5jb2xvclNlbGVjdGlvblNlcnZpY2UuZ2V0Q29sb3JzRnJvbUltYWdlKCcuLi9hc3NldHMvc2FtcGxlMi5qcGcnKVxyXG5cclxuICAvLyBnZXQgY29sb3JzXHJcbiAgLy8gdGhpcy5jb2xvclNlbGVjdGlvblNlcnZpY2UucGFsZXR0ZS5zdWJzY3JpYmUoZGF0YSA9PiB0aGlzLnBhbGV0dGUgPSBkYXRhKVxyXG5cclxuICAvLyBzYW1wbGUgaHRtbFxyXG4gIC8vICAgPGRpdiAqbmdGb3I9XCJsZXQgY29sb3Igb2YgcGFsZXR0ZVwiPlxyXG4gIC8vICAgICA8ZGl2IHN0eWxlPVwiZGlzcGxheTogZmxleDtcIj5cclxuICAvLyAgICAgICAgIDxkaXZcclxuICAvLyAgICAgICAgICAgICBjbGFzcz1cImJveFwiXHJcbiAgLy8gICAgICAgICAgICAgW3N0eWxlLmJhY2tncm91bmQtY29sb3JdPVwiY29sb3IuY29sb3JcIlxyXG4gIC8vICAgICAgICAgPlxyXG4gIC8vICAgICAgICAgQ29sb3JcclxuICAvLyAgICAgICAgIDwvZGl2PlxyXG4gIC8vICAgICAgICAgPGRpdlxyXG4gIC8vICAgICAgICAgICAgIGNsYXNzPVwiYm94XCJcclxuICAvLyAgICAgICAgICAgICBbc3R5bGUuYmFja2dyb3VuZC1jb2xvcl09XCJjb2xvci5jb21wbGVtZW50YXJ5Q29sb3JcIlxyXG4gIC8vICAgICAgICAgPlxyXG4gIC8vICAgICAgICAgQ29tcGxlbWVudGFyeVxyXG4gIC8vICAgICAgICAgPC9kaXY+XHJcbiAgLy8gICAgIDwvZGl2PlxyXG4gIC8vIDwvZGl2PlxyXG5cclxuICAvLyBDU1NcclxuICAvLyAgIC5ib3gge1xyXG4gIC8vICAgICB3aWR0aDogMTAwcHg7XHJcbiAgLy8gICAgIGhlaWdodDogMTAwcHg7XHJcbiAgLy8gICAgIGJvcmRlcjogc29saWQgdGhpbiBibGFjaztcclxuICAvLyAgICAgY29sb3I6IGJsYWNrO1xyXG4gIC8vICAgICBtYXJnaW46IDRweDtcclxuICAvLyAgICAgcGFkZGluZzogMTZweDtcclxuICAvLyAgICAgZGlzcGxheTogZmxleDtcclxuICAvLyAgICAgZmxleC13cmFwOiB3cmFwO1xyXG4gIC8vICAgICBhbGlnbi1jb250ZW50OiBjZW50ZXI7XHJcbiAgLy8gICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gIC8vIH1cclxuXHJcbiAgcHJpdmF0ZSBwYWxldHRlID0gbmV3IEJlaGF2aW9yU3ViamVjdDx7IGNvbG9yOiBzdHJpbmcsIGNvbXBsZW1lbnRhcnlDb2xvcjogc3RyaW5nIH1bXT4oW10pXHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBjb2xvckNvbnZlcnNpb25TZXJ2aWNlOiBDb2xvckNvbnZlcnNpb25TZXJ2aWNlXHJcbiAgKSB7IH1cclxuXHJcbiAgZ2V0Q29sb3JzRnJvbUltYWdlKGltYWdlUGF0aDogc3RyaW5nLCBjb2xvcnMgPSAzKSB7XHJcblxyXG4gICAgY29uc3QgaW1hZ2UgPSBuZXcgSW1hZ2UoKVxyXG4gICAgaW1hZ2Uuc3JjID0gaW1hZ2VQYXRoXHJcblxyXG4gICAgaW1hZ2Uub25sb2FkID0gKCkgPT4ge1xyXG4gICAgICBjb25zdCBkYXRhID0gdGhpcy5nZW5lcmF0ZUNvbG9yUGFsZXR0ZShpbWFnZSwgY29sb3JzKSB8fCBbXVxyXG4gICAgICB0aGlzLnBhbGV0dGUubmV4dChkYXRhKVxyXG4gICAgfVxyXG5cclxuICB9XHJcblxyXG4gIGdlbmVyYXRlQ29sb3JQYWxldHRlKGltYWdlOiBIVE1MSW1hZ2VFbGVtZW50LCBjb2xvckNvdW50ID0gNikge1xyXG5cclxuICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpXHJcbiAgICBjb25zdCBjb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoJzJkJylcclxuXHJcbiAgICBpZighY29udGV4dCB8fCAhaW1hZ2UpIHJldHVyblxyXG5cclxuICAgIGNhbnZhcy53aWR0aCA9IGltYWdlLndpZHRoXHJcbiAgICBjYW52YXMuaGVpZ2h0ID0gaW1hZ2UuaGVpZ2h0XHJcbiAgICBjb250ZXh0LmRyYXdJbWFnZShpbWFnZSwgMCwgMClcclxuXHJcbiAgICAvLyBHZXQgdGhlIGltYWdlIGRhdGFcclxuICAgIGNvbnN0IGltYWdlRGF0YSA9IGNvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodClcclxuICAgIGNvbnN0IHBpeGVscyA9IGltYWdlRGF0YS5kYXRhXHJcbiAgICBjb25zdCBwaXhlbENvdW50ID0gaW1hZ2VEYXRhLndpZHRoICogaW1hZ2VEYXRhLmhlaWdodFxyXG5cclxuICAgIC8vIEJ1aWxkIGFuIGFycmF5IG9mIFJHQiBjb2xvcnNcclxuICAgIGNvbnN0IGNvbG9ycyA9IFtdXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBpeGVsQ291bnQ7IGkrKykge1xyXG4gICAgICBjb25zdCBvZmZzZXQgPSBpICogNFxyXG4gICAgICBjb25zdCByID0gcGl4ZWxzW29mZnNldF1cclxuICAgICAgY29uc3QgZyA9IHBpeGVsc1tvZmZzZXQgKyAxXVxyXG4gICAgICBjb25zdCBiID0gcGl4ZWxzW29mZnNldCArIDJdXHJcbiAgICAgIGNvbG9ycy5wdXNoKFtyLCBnLCBiXSlcclxuICAgIH1cclxuXHJcbiAgICAvLyBBcHBseSBjb2xvciBxdWFudGl6YXRpb24gdXNpbmcgay1tZWFucyBjbHVzdGVyaW5nXHJcbiAgICBjb25zdCBxdWFudGl6ZWRDb2xvcnMgPSB0aGlzLmtNZWFuc0NvbG9yUXVhbnRpemF0aW9uKGNvbG9ycywgY29sb3JDb3VudClcclxuXHJcbiAgICAvLyBPcmRlciBjb2xvcnMgYnkgbHVtaW5hbmNlXHJcbiAgICBxdWFudGl6ZWRDb2xvcnMuc29ydCgoY29sb3IxLCBjb2xvcjIpID0+IHtcclxuICAgICAgY29uc3QgbHVtaW5hbmNlMSA9IHRoaXMuZ2V0THVtaW5hbmNlKGNvbG9yMSlcclxuICAgICAgY29uc3QgbHVtaW5hbmNlMiA9IHRoaXMuZ2V0THVtaW5hbmNlKGNvbG9yMilcclxuICAgICAgcmV0dXJuIGx1bWluYW5jZTIgLSBsdW1pbmFuY2UxXHJcbiAgICB9KVxyXG5cclxuICAgIGNvbnN0IHBhbGV0dGUgPSBxdWFudGl6ZWRDb2xvcnMubWFwKGNvbG9yID0+IHtcclxuICAgICAgY29uc3QgY29tcGxlbWVudGFyeUNvbG9yID0gY29sb3IubWFwKGNvbXBvbmVudCA9PiAyNTUgLSBjb21wb25lbnQpXHJcbiAgICAgIGNvbnN0IGhleENvbG9yID0gdGhpcy5jb2xvckNvbnZlcnNpb25TZXJ2aWNlLnJnYlRvSGV4KGNvbG9yKVxyXG4gICAgICBjb25zdCBoZXhDb21wbGVtZW50YXJ5Q29sb3IgPSB0aGlzLmNvbG9yQ29udmVyc2lvblNlcnZpY2UucmdiVG9IZXgoY29tcGxlbWVudGFyeUNvbG9yKVxyXG4gICAgICByZXR1cm4geyBjb2xvcjogaGV4Q29sb3IsIGNvbXBsZW1lbnRhcnlDb2xvcjogaGV4Q29tcGxlbWVudGFyeUNvbG9yIH1cclxuICAgIH0pXHJcblxyXG4gICAgcmV0dXJuIHBhbGV0dGVcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0THVtaW5hbmNlKGNvbG9yOiBudW1iZXJbXSkge1xyXG4gICAgY29uc3QgW3IsIGcsIGJdID0gY29sb3JcclxuICAgIHJldHVybiAwLjI5OSAqIHIgKyAwLjU4NyAqIGcgKyAwLjExNCAqIGJcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY2FsY3VsYXRlQ29sb3JEaXN0YW5jZShjb2xvcjE6IG51bWJlcltdLCBjb2xvcjI6IG51bWJlcltdKSB7XHJcbiAgICBjb25zdCBbcjEsIGcxLCBiMV0gPSBjb2xvcjFcclxuICAgIGNvbnN0IFtyMiwgZzIsIGIyXSA9IGNvbG9yMlxyXG4gICAgY29uc3QgZHIgPSByMiAtIHIxXHJcbiAgICBjb25zdCBkZyA9IGcyIC0gZzFcclxuICAgIGNvbnN0IGRiID0gYjIgLSBiMVxyXG4gICAgcmV0dXJuIE1hdGguc3FydChkciAqIGRyICsgZGcgKiBkZyArIGRiICogZGIpXHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNhbGN1bGF0ZU1lYW5Db2xvcihjb2xvcnM6IG51bWJlcltdW10pIHtcclxuICAgIGxldCBzdW1SID0gMFxyXG4gICAgbGV0IHN1bUcgPSAwXHJcbiAgICBsZXQgc3VtQiA9IDBcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29sb3JzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGNvbnN0IFtyLCBnLCBiXSA9IGNvbG9yc1tpXVxyXG4gICAgICBzdW1SICs9IHJcclxuICAgICAgc3VtRyArPSBnXHJcbiAgICAgIHN1bUIgKz0gYlxyXG4gICAgfVxyXG4gICAgY29uc3QgbWVhblIgPSBNYXRoLnJvdW5kKHN1bVIgLyBjb2xvcnMubGVuZ3RoKVxyXG4gICAgY29uc3QgbWVhbkcgPSBNYXRoLnJvdW5kKHN1bUcgLyBjb2xvcnMubGVuZ3RoKVxyXG4gICAgY29uc3QgbWVhbkIgPSBNYXRoLnJvdW5kKHN1bUIgLyBjb2xvcnMubGVuZ3RoKVxyXG4gICAgcmV0dXJuIFttZWFuUiwgbWVhbkcsIG1lYW5CXVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBrTWVhbnNDb2xvclF1YW50aXphdGlvbihjb2xvcnM6IG51bWJlcltdW10sIGs6IG51bWJlcikge1xyXG4gICAgY29uc3QgY2x1c3RlckNlbnRlcnMgPSBbXVxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBrOyBpKyspIHtcclxuICAgICAgY29uc3QgcmFuZG9tQ29sb3IgPSBjb2xvcnNbTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogY29sb3JzLmxlbmd0aCldXHJcbiAgICAgIGNsdXN0ZXJDZW50ZXJzLnB1c2gocmFuZG9tQ29sb3IpXHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgY2x1c3RlcnMgPSBbXVxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb2xvcnMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgY29uc3QgY29sb3IgPSBjb2xvcnNbaV1cclxuICAgICAgbGV0IG1pbkRpc3RhbmNlID0gSW5maW5pdHlcclxuICAgICAgbGV0IG5lYXJlc3RDZW50ZXIgPSBudWxsXHJcbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgY2x1c3RlckNlbnRlcnMubGVuZ3RoOyBqKyspIHtcclxuICAgICAgICBjb25zdCBjZW50ZXIgPSBjbHVzdGVyQ2VudGVyc1tqXVxyXG4gICAgICAgIGNvbnN0IGRpc3RhbmNlID0gdGhpcy5jYWxjdWxhdGVDb2xvckRpc3RhbmNlKGNvbG9yLCBjZW50ZXIpXHJcbiAgICAgICAgaWYgKGRpc3RhbmNlIDwgbWluRGlzdGFuY2UpIHtcclxuICAgICAgICAgIG1pbkRpc3RhbmNlID0gZGlzdGFuY2VcclxuICAgICAgICAgIG5lYXJlc3RDZW50ZXIgPSBjZW50ZXJcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgY2x1c3RlcnMucHVzaCh7IGNvbG9yLCBjZW50ZXI6IG5lYXJlc3RDZW50ZXIgfSlcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB1cGRhdGVkQ2VudGVycyA9IFtdXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNsdXN0ZXJDZW50ZXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGNvbnN0IGNlbnRlciA9IGNsdXN0ZXJDZW50ZXJzW2ldXHJcbiAgICAgIGNvbnN0IGNsdXN0ZXJDb2xvcnMgPSBjbHVzdGVycy5maWx0ZXIoYyA9PiBjLmNlbnRlciA9PT0gY2VudGVyKS5tYXAoYyA9PiBjLmNvbG9yKVxyXG4gICAgICBpZiAoY2x1c3RlckNvbG9ycy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgY29uc3QgdXBkYXRlZENlbnRlciA9IHRoaXMuY2FsY3VsYXRlTWVhbkNvbG9yKGNsdXN0ZXJDb2xvcnMpXHJcbiAgICAgICAgdXBkYXRlZENlbnRlcnMucHVzaCh1cGRhdGVkQ2VudGVyKVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHVwZGF0ZWRDZW50ZXJzXHJcbiAgfVxyXG5cclxufVxyXG4iXX0=
@@ -0,0 +1,58 @@
1
+ import { Injectable } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ import * as i1 from "./color-conversion.service";
4
+ export class TextColorService {
5
+ constructor(colorConversionService) {
6
+ this.colorConversionService = colorConversionService;
7
+ }
8
+ textColorForBgColor(bgColor, lightColor, darkColor) {
9
+ const UIColors = this.fixColor(bgColor);
10
+ const r = UIColors[0];
11
+ const g = UIColors[1];
12
+ const b = UIColors[2];
13
+ return ((r * 0.299 + g * 0.587 + b * 0.114) > 149) ? darkColor : lightColor;
14
+ }
15
+ darkerColor(color1, color2) {
16
+ return (this.isColorDarker(color1, color2)) ? color1 : color2;
17
+ }
18
+ isColorDarker(color1, color2) {
19
+ const newColor1 = this.fixColor(color1);
20
+ const newColor2 = this.fixColor(color2);
21
+ const luminance1 = this.calculateLuminance(newColor1[0], newColor1[1], newColor1[2]);
22
+ const luminance2 = this.calculateLuminance(newColor2[0], newColor2[1], newColor2[2]);
23
+ return (luminance1 > luminance2);
24
+ }
25
+ lighterColor(color1, color2) {
26
+ return (this.isColorLighter(color1, color2)) ? color1 : color2;
27
+ }
28
+ isColorLighter(color1, color2) {
29
+ const newColor1 = this.fixColor(color1);
30
+ const newColor2 = this.fixColor(color2);
31
+ const luminance1 = this.calculateLuminance(newColor1[0], newColor1[1], newColor1[2]);
32
+ const luminance2 = this.calculateLuminance(newColor2[0], newColor2[1], newColor2[2]);
33
+ return (luminance1 > luminance2);
34
+ }
35
+ calculateLuminance(r, g, b) {
36
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
37
+ }
38
+ fixColor(color) {
39
+ let newColor = color;
40
+ if (color.includes('#')) {
41
+ newColor = color.slice(1);
42
+ newColor = (newColor.length === 3) ? '#' + newColor.split('').map(hex => hex + hex).join('') : '#' + newColor;
43
+ }
44
+ const Reg_Exp = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
45
+ const colorIsHex = Reg_Exp.test(newColor);
46
+ const UIColors = (colorIsHex) ? this.colorConversionService.hexToRgb(newColor) : newColor.match(/\d+/g)?.map(item => parseInt(item)) || [];
47
+ return UIColors;
48
+ }
49
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextColorService, deps: [{ token: i1.ColorConversionService }], target: i0.ɵɵFactoryTarget.Injectable }); }
50
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextColorService, providedIn: 'root' }); }
51
+ }
52
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextColorService, decorators: [{
53
+ type: Injectable,
54
+ args: [{
55
+ providedIn: 'root'
56
+ }]
57
+ }], ctorParameters: function () { return [{ type: i1.ColorConversionService }]; } });
58
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dC1jb2xvci5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvY29sb3ItdXRpbHMvc3JjL2xpYi90ZXh0LWNvbG9yLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQTs7O0FBTTFDLE1BQU0sT0FBTyxnQkFBZ0I7SUFFM0IsWUFDVSxzQkFBOEM7UUFBOUMsMkJBQXNCLEdBQXRCLHNCQUFzQixDQUF3QjtJQUNyRCxDQUFDO0lBRUosbUJBQW1CLENBQUMsT0FBZSxFQUFFLFVBQWtCLEVBQUUsU0FBaUI7UUFFeEUsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUV2QyxNQUFNLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDckIsTUFBTSxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ3JCLE1BQU0sQ0FBQyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUVyQixPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUMsS0FBSyxHQUFHLENBQUMsR0FBQyxLQUFLLEdBQUcsQ0FBQyxHQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQztJQUV4RSxDQUFDO0lBRUQsV0FBVyxDQUFDLE1BQWMsRUFBRSxNQUFjO1FBQ3hDLE9BQU8sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sRUFBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztJQUMvRCxDQUFDO0lBRUQsYUFBYSxDQUFDLE1BQWMsRUFBRSxNQUFjO1FBRTFDLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxD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aEIsZ0JBQWdCLGNBRmYsTUFBTTs7NEZBRVAsZ0JBQWdCO2tCQUg1QixVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJ1xyXG5pbXBvcnQgeyBDb2xvckNvbnZlcnNpb25TZXJ2aWNlIH0gZnJvbSAnLi9jb2xvci1jb252ZXJzaW9uLnNlcnZpY2UnXHJcblxyXG5ASW5qZWN0YWJsZSh7XHJcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBUZXh0Q29sb3JTZXJ2aWNlIHtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwcml2YXRlIGNvbG9yQ29udmVyc2lvblNlcnZpY2U6IENvbG9yQ29udmVyc2lvblNlcnZpY2VcclxuICApIHt9XHJcblxyXG4gIHRleHRDb2xvckZvckJnQ29sb3IoYmdDb2xvcjogc3RyaW5nLCBsaWdodENvbG9yOiBzdHJpbmcsIGRhcmtDb2xvcjogc3RyaW5nKSB7XHJcblxyXG4gICAgY29uc3QgVUlDb2xvcnMgPSB0aGlzLmZpeENvbG9yKGJnQ29sb3IpXHJcblxyXG4gICAgY29uc3QgciA9IFVJQ29sb3JzWzBdXHJcbiAgICBjb25zdCBnID0gVUlDb2xvcnNbMV1cclxuICAgIGNvbnN0IGIgPSBVSUNvbG9yc1syXVxyXG5cclxuICAgIHJldHVybiAoKHIqMC4yOTkgKyBnKjAuNTg3ICsgYiowLjExNCkgPiAxNDkpID8gZGFya0NvbG9yIDogbGlnaHRDb2xvcjtcclxuXHJcbiAgfVxyXG5cclxuICBkYXJrZXJDb2xvcihjb2xvcjE6IHN0cmluZywgY29sb3IyOiBzdHJpbmcpIHtcclxuICAgIHJldHVybiAodGhpcy5pc0NvbG9yRGFya2VyKGNvbG9yMSxjb2xvcjIpKSA/IGNvbG9yMSA6IGNvbG9yMjtcclxuICB9XHJcblxyXG4gIGlzQ29sb3JEYXJrZXIoY29sb3IxOiBzdHJpbmcsIGNvbG9yMjogc3RyaW5nKSB7XHJcblxyXG4gICAgY29uc3QgbmV3Q29sb3IxID0gdGhpcy5maXhDb2xvcihjb2xvcjEpXHJcbiAgICBjb25zdCBuZXdDb2xvcjIgPSB0aGlzLmZpeENvbG9yKGNvbG9yMilcclxuXHJcbiAgICBjb25zdCBsdW1pbmFuY2UxID0gdGhpcy5jYWxjdWxhdGVMdW1pbmFuY2UobmV3Q29sb3IxWzBdLCBuZXdDb2xvcjFbMV0sIG5ld0NvbG9yMVsyXSlcclxuICAgIGNvbnN0IGx1bWluYW5jZTIgPSB0aGlzLmNhbGN1bGF0ZUx1bWluYW5jZShuZXdDb2xvcjJbMF0sIG5ld0NvbG9yMlsxXSwgbmV3Q29sb3IyWzJdKVxyXG5cclxuICAgIHJldHVybiAobHVtaW5hbmNlMSA+IGx1bWluYW5jZTIpXHJcblxyXG4gIH1cclxuXHJcbiAgbGlnaHRlckNvbG9yKGNvbG9yMTogc3RyaW5nLCBjb2xvcjI6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gKHRoaXMuaXNDb2xvckxpZ2h0ZXIoY29sb3IxLGNvbG9yMikpID8gY29sb3IxIDogY29sb3IyO1xyXG4gIH1cclxuXHJcbiAgaXNDb2xvckxpZ2h0ZXIoY29sb3IxOiBzdHJpbmcsIGNvbG9yMjogc3RyaW5nKSB7XHJcbiAgICBcclxuICAgIGNvbnN0IG5ld0NvbG9yMSA9IHRoaXMuZml4Q29sb3IoY29sb3IxKTtcclxuICAgIGNvbnN0IG5ld0NvbG9yMiA9IHRoaXMuZml4Q29sb3IoY29sb3IyKTtcclxuICBcclxuICAgIGNvbnN0IGx1bWluYW5jZTEgPSB0aGlzLmNhbGN1bGF0ZUx1bWluYW5jZShuZXdDb2xvcjFbMF0sIG5ld0NvbG9yMVsxXSwgbmV3Q29sb3IxWzJdKTtcclxuICAgIGNvbnN0IGx1bWluYW5jZTIgPSB0aGlzLmNhbGN1bGF0ZUx1bWluYW5jZShuZXdDb2xvcjJbMF0sIG5ld0NvbG9yMlsxXSwgbmV3Q29sb3IyWzJdKTtcclxuICBcclxuICAgIHJldHVybiAobHVtaW5hbmNlMSA+IGx1bWluYW5jZTIpXHJcblxyXG4gIH1cclxuXHJcbiAgY2FsY3VsYXRlTHVtaW5hbmNlKHI6IG51bWJlciwgZzogbnVtYmVyLCBiOiBudW1iZXIpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIDAuMjEyNiAqIHIgKyAwLjcxNTIgKiBnICsgMC4wNzIyICogYjtcclxuICB9XHJcblxyXG4gIGZpeENvbG9yKGNvbG9yOiBzdHJpbmcpIHtcclxuXHJcbiAgICBsZXQgbmV3Q29sb3IgPSBjb2xvclxyXG5cclxuICAgIGlmKGNvbG9yLmluY2x1ZGVzKCcjJykpIHtcclxuICAgICAgbmV3Q29sb3IgPSBjb2xvci5zbGljZSgxKVxyXG4gICAgICBuZXdDb2xvciA9IChuZXdDb2xvci5sZW5ndGggPT09IDMpID8gJyMnICsgbmV3Q29sb3Iuc3BsaXQoJycpLm1hcChoZXggPT4gaGV4ICsgaGV4KS5qb2luKCcnKSA6ICcjJyArIG5ld0NvbG9yXHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgUmVnX0V4cCA9IC9eIyhbQS1GYS1mMC05XXs2fXxbQS1GYS1mMC05XXszfSkkL1xyXG4gICAgY29uc3QgY29sb3JJc0hleCA9IFJlZ19FeHAudGVzdChuZXdDb2xvcilcclxuXHJcbiAgICBjb25zdCBVSUNvbG9ycyA9IChjb2xvcklzSGV4KSA/IHRoaXMuY29sb3JDb252ZXJzaW9uU2VydmljZS5oZXhUb1JnYihuZXdDb2xvcikgOiBuZXdDb2xvci5tYXRjaCgvXFxkKy9nKT8ubWFwKGl0ZW0gPT4gcGFyc2VJbnQoaXRlbSkpIHx8IFtdXHJcblxyXG4gICAgcmV0dXJuIFVJQ29sb3JzXHJcblxyXG4gIH1cclxuXHJcbn1cclxuIl19
@@ -0,0 +1,8 @@
1
+ /*
2
+ * Public API Surface of color-utils
3
+ */
4
+ export * from './lib/color-conversion.service';
5
+ export * from './lib/color-extractor.directive';
6
+ export * from './lib/color-pallette.service';
7
+ export * from './lib/text-color.service';
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL2NvbG9yLXV0aWxzL3NyYy9wdWJsaWMtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyxnQ0FBZ0MsQ0FBQztBQUMvQyxjQUFjLGlDQUFpQyxDQUFDO0FBQ2hELGNBQWMsOEJBQThCLENBQUM7QUFDN0MsY0FBYywwQkFBMEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBQdWJsaWMgQVBJIFN1cmZhY2Ugb2YgY29sb3ItdXRpbHNcbiAqL1xuXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb2xvci1jb252ZXJzaW9uLnNlcnZpY2UnO1xuZXhwb3J0ICogZnJvbSAnLi9saWIvY29sb3ItZXh0cmFjdG9yLmRpcmVjdGl2ZSc7XG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb2xvci1wYWxsZXR0ZS5zZXJ2aWNlJztcbmV4cG9ydCAqIGZyb20gJy4vbGliL3RleHQtY29sb3Iuc2VydmljZSc7XG4iXX0=
@@ -0,0 +1,294 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Injectable, EventEmitter, Directive, Output, HostListener } from '@angular/core';
3
+ import { BehaviorSubject } from 'rxjs';
4
+
5
+ class ColorConversionService {
6
+ constructor() {
7
+ this.componentToHex = (c) => {
8
+ const hex = c.toString(16);
9
+ return hex.length === 1 ? "0" + hex : hex;
10
+ };
11
+ }
12
+ rgbToHex(rgb) {
13
+ if (rgb === null || rgb.length !== 3 || rgb.some(value => value < 0 || value > 255))
14
+ return '';
15
+ const [r, g, b] = rgb;
16
+ const hexR = this.componentToHex(r);
17
+ const hexG = this.componentToHex(g);
18
+ const hexB = this.componentToHex(b);
19
+ return "#" + hexR + hexG + hexB;
20
+ }
21
+ hexToRgb(hex) {
22
+ if (hex === null || hex === undefined)
23
+ return [];
24
+ hex = (hex.length === 3) ? hex + hex : hex;
25
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
26
+ return result ? [
27
+ parseInt(result[1], 16),
28
+ parseInt(result[2], 16),
29
+ parseInt(result[3], 16)
30
+ ] : [];
31
+ }
32
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorConversionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
33
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorConversionService, providedIn: 'root' }); }
34
+ }
35
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorConversionService, decorators: [{
36
+ type: Injectable,
37
+ args: [{
38
+ providedIn: 'root'
39
+ }]
40
+ }] });
41
+
42
+ class ColorExtractorDirective {
43
+ constructor(elementRef, renderer) {
44
+ this.elementRef = elementRef;
45
+ this.renderer = renderer;
46
+ this.colorValue = new EventEmitter();
47
+ }
48
+ get currentElement() {
49
+ return window.getComputedStyle(this.elementRef.nativeElement);
50
+ }
51
+ onMouseEnter() {
52
+ // console.log('ENTER', this.currentElement)
53
+ this.colorValue.emit(this.currentElement.getPropertyValue('background-color'));
54
+ }
55
+ onMouseLeave() {
56
+ // console.log('LEAVE', this.currentElement.getPropertyValue('background-color'))
57
+ this.colorValue.emit('white');
58
+ }
59
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorExtractorDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive }); }
60
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: ColorExtractorDirective, selector: "[getColor]", outputs: { colorValue: "colorValue" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, ngImport: i0 }); }
61
+ }
62
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorExtractorDirective, decorators: [{
63
+ type: Directive,
64
+ args: [{
65
+ selector: '[getColor]'
66
+ }]
67
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }]; }, propDecorators: { colorValue: [{
68
+ type: Output
69
+ }], onMouseEnter: [{
70
+ type: HostListener,
71
+ args: ['mouseenter']
72
+ }], onMouseLeave: [{
73
+ type: HostListener,
74
+ args: ['mouseleave']
75
+ }] } });
76
+
77
+ class ColorPalletteService {
78
+ constructor(colorConversionService) {
79
+ this.colorConversionService = colorConversionService;
80
+ // define image path
81
+ // this.colorSelectionService.getColorsFromImage('../assets/sample2.jpg')
82
+ // get colors
83
+ // this.colorSelectionService.palette.subscribe(data => this.palette = data)
84
+ // sample html
85
+ // <div *ngFor="let color of palette">
86
+ // <div style="display: flex;">
87
+ // <div
88
+ // class="box"
89
+ // [style.background-color]="color.color"
90
+ // >
91
+ // Color
92
+ // </div>
93
+ // <div
94
+ // class="box"
95
+ // [style.background-color]="color.complementaryColor"
96
+ // >
97
+ // Complementary
98
+ // </div>
99
+ // </div>
100
+ // </div>
101
+ // CSS
102
+ // .box {
103
+ // width: 100px;
104
+ // height: 100px;
105
+ // border: solid thin black;
106
+ // color: black;
107
+ // margin: 4px;
108
+ // padding: 16px;
109
+ // display: flex;
110
+ // flex-wrap: wrap;
111
+ // align-content: center;
112
+ // justify-content: center;
113
+ // }
114
+ this.palette = new BehaviorSubject([]);
115
+ }
116
+ getColorsFromImage(imagePath, colors = 3) {
117
+ const image = new Image();
118
+ image.src = imagePath;
119
+ image.onload = () => {
120
+ const data = this.generateColorPalette(image, colors) || [];
121
+ this.palette.next(data);
122
+ };
123
+ }
124
+ generateColorPalette(image, colorCount = 6) {
125
+ const canvas = document.createElement('canvas');
126
+ const context = canvas.getContext('2d');
127
+ if (!context || !image)
128
+ return;
129
+ canvas.width = image.width;
130
+ canvas.height = image.height;
131
+ context.drawImage(image, 0, 0);
132
+ // Get the image data
133
+ const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
134
+ const pixels = imageData.data;
135
+ const pixelCount = imageData.width * imageData.height;
136
+ // Build an array of RGB colors
137
+ const colors = [];
138
+ for (let i = 0; i < pixelCount; i++) {
139
+ const offset = i * 4;
140
+ const r = pixels[offset];
141
+ const g = pixels[offset + 1];
142
+ const b = pixels[offset + 2];
143
+ colors.push([r, g, b]);
144
+ }
145
+ // Apply color quantization using k-means clustering
146
+ const quantizedColors = this.kMeansColorQuantization(colors, colorCount);
147
+ // Order colors by luminance
148
+ quantizedColors.sort((color1, color2) => {
149
+ const luminance1 = this.getLuminance(color1);
150
+ const luminance2 = this.getLuminance(color2);
151
+ return luminance2 - luminance1;
152
+ });
153
+ const palette = quantizedColors.map(color => {
154
+ const complementaryColor = color.map(component => 255 - component);
155
+ const hexColor = this.colorConversionService.rgbToHex(color);
156
+ const hexComplementaryColor = this.colorConversionService.rgbToHex(complementaryColor);
157
+ return { color: hexColor, complementaryColor: hexComplementaryColor };
158
+ });
159
+ return palette;
160
+ }
161
+ getLuminance(color) {
162
+ const [r, g, b] = color;
163
+ return 0.299 * r + 0.587 * g + 0.114 * b;
164
+ }
165
+ calculateColorDistance(color1, color2) {
166
+ const [r1, g1, b1] = color1;
167
+ const [r2, g2, b2] = color2;
168
+ const dr = r2 - r1;
169
+ const dg = g2 - g1;
170
+ const db = b2 - b1;
171
+ return Math.sqrt(dr * dr + dg * dg + db * db);
172
+ }
173
+ calculateMeanColor(colors) {
174
+ let sumR = 0;
175
+ let sumG = 0;
176
+ let sumB = 0;
177
+ for (let i = 0; i < colors.length; i++) {
178
+ const [r, g, b] = colors[i];
179
+ sumR += r;
180
+ sumG += g;
181
+ sumB += b;
182
+ }
183
+ const meanR = Math.round(sumR / colors.length);
184
+ const meanG = Math.round(sumG / colors.length);
185
+ const meanB = Math.round(sumB / colors.length);
186
+ return [meanR, meanG, meanB];
187
+ }
188
+ kMeansColorQuantization(colors, k) {
189
+ const clusterCenters = [];
190
+ for (let i = 0; i < k; i++) {
191
+ const randomColor = colors[Math.floor(Math.random() * colors.length)];
192
+ clusterCenters.push(randomColor);
193
+ }
194
+ const clusters = [];
195
+ for (let i = 0; i < colors.length; i++) {
196
+ const color = colors[i];
197
+ let minDistance = Infinity;
198
+ let nearestCenter = null;
199
+ for (let j = 0; j < clusterCenters.length; j++) {
200
+ const center = clusterCenters[j];
201
+ const distance = this.calculateColorDistance(color, center);
202
+ if (distance < minDistance) {
203
+ minDistance = distance;
204
+ nearestCenter = center;
205
+ }
206
+ }
207
+ clusters.push({ color, center: nearestCenter });
208
+ }
209
+ const updatedCenters = [];
210
+ for (let i = 0; i < clusterCenters.length; i++) {
211
+ const center = clusterCenters[i];
212
+ const clusterColors = clusters.filter(c => c.center === center).map(c => c.color);
213
+ if (clusterColors.length > 0) {
214
+ const updatedCenter = this.calculateMeanColor(clusterColors);
215
+ updatedCenters.push(updatedCenter);
216
+ }
217
+ }
218
+ return updatedCenters;
219
+ }
220
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPalletteService, deps: [{ token: ColorConversionService }], target: i0.ɵɵFactoryTarget.Injectable }); }
221
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPalletteService, providedIn: 'root' }); }
222
+ }
223
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ColorPalletteService, decorators: [{
224
+ type: Injectable,
225
+ args: [{
226
+ providedIn: 'root'
227
+ }]
228
+ }], ctorParameters: function () { return [{ type: ColorConversionService }]; } });
229
+
230
+ class TextColorService {
231
+ constructor(colorConversionService) {
232
+ this.colorConversionService = colorConversionService;
233
+ }
234
+ textColorForBgColor(bgColor, lightColor, darkColor) {
235
+ const UIColors = this.fixColor(bgColor);
236
+ const r = UIColors[0];
237
+ const g = UIColors[1];
238
+ const b = UIColors[2];
239
+ return ((r * 0.299 + g * 0.587 + b * 0.114) > 149) ? darkColor : lightColor;
240
+ }
241
+ darkerColor(color1, color2) {
242
+ return (this.isColorDarker(color1, color2)) ? color1 : color2;
243
+ }
244
+ isColorDarker(color1, color2) {
245
+ const newColor1 = this.fixColor(color1);
246
+ const newColor2 = this.fixColor(color2);
247
+ const luminance1 = this.calculateLuminance(newColor1[0], newColor1[1], newColor1[2]);
248
+ const luminance2 = this.calculateLuminance(newColor2[0], newColor2[1], newColor2[2]);
249
+ return (luminance1 > luminance2);
250
+ }
251
+ lighterColor(color1, color2) {
252
+ return (this.isColorLighter(color1, color2)) ? color1 : color2;
253
+ }
254
+ isColorLighter(color1, color2) {
255
+ const newColor1 = this.fixColor(color1);
256
+ const newColor2 = this.fixColor(color2);
257
+ const luminance1 = this.calculateLuminance(newColor1[0], newColor1[1], newColor1[2]);
258
+ const luminance2 = this.calculateLuminance(newColor2[0], newColor2[1], newColor2[2]);
259
+ return (luminance1 > luminance2);
260
+ }
261
+ calculateLuminance(r, g, b) {
262
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
263
+ }
264
+ fixColor(color) {
265
+ let newColor = color;
266
+ if (color.includes('#')) {
267
+ newColor = color.slice(1);
268
+ newColor = (newColor.length === 3) ? '#' + newColor.split('').map(hex => hex + hex).join('') : '#' + newColor;
269
+ }
270
+ const Reg_Exp = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
271
+ const colorIsHex = Reg_Exp.test(newColor);
272
+ const UIColors = (colorIsHex) ? this.colorConversionService.hexToRgb(newColor) : newColor.match(/\d+/g)?.map(item => parseInt(item)) || [];
273
+ return UIColors;
274
+ }
275
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextColorService, deps: [{ token: ColorConversionService }], target: i0.ɵɵFactoryTarget.Injectable }); }
276
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextColorService, providedIn: 'root' }); }
277
+ }
278
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextColorService, decorators: [{
279
+ type: Injectable,
280
+ args: [{
281
+ providedIn: 'root'
282
+ }]
283
+ }], ctorParameters: function () { return [{ type: ColorConversionService }]; } });
284
+
285
+ /*
286
+ * Public API Surface of color-utils
287
+ */
288
+
289
+ /**
290
+ * Generated bundle index. Do not edit.
291
+ */
292
+
293
+ export { ColorConversionService, ColorExtractorDirective, ColorPalletteService, TextColorService };
294
+ //# sourceMappingURL=color-util-helpers.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-util-helpers.mjs","sources":["../../../projects/color-utils/src/lib/color-conversion.service.ts","../../../projects/color-utils/src/lib/color-extractor.directive.ts","../../../projects/color-utils/src/lib/color-pallette.service.ts","../../../projects/color-utils/src/lib/text-color.service.ts","../../../projects/color-utils/src/public-api.ts","../../../projects/color-utils/src/color-util-helpers.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class ColorConversionService {\r\n\r\n rgbToHex(rgb: number[] | null): string {\r\n if (rgb === null || rgb.length !== 3 || rgb.some(value => value < 0 || value > 255)) return '';\r\n\r\n const [r, g, b] = rgb;\r\n const hexR = this.componentToHex(r);\r\n const hexG = this.componentToHex(g);\r\n const hexB = this.componentToHex(b);\r\n return \"#\" + hexR + hexG + hexB;\r\n }\r\n\r\n private componentToHex = (c: number) => {\r\n const hex = c.toString(16);\r\n return hex.length === 1 ? \"0\" + hex : hex;\r\n }\r\n\r\n hexToRgb(hex: string | null | undefined): number[] {\r\n if (hex === null || hex === undefined) return [];\r\n\r\n hex = (hex.length === 3) ? hex + hex : hex;\r\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\r\n\r\n return result ? [\r\n parseInt(result[1], 16),\r\n parseInt(result[2], 16),\r\n parseInt(result[3], 16)\r\n ] : [];\r\n }\r\n}\r\n","import { Directive, ElementRef, Renderer2, HostListener, EventEmitter, Output } from '@angular/core';\n\n@Directive({\n selector: '[getColor]'\n})\nexport class ColorExtractorDirective {\n\n @Output() colorValue: EventEmitter<string> = new EventEmitter<string>();\n\n constructor(private elementRef: ElementRef, private renderer: Renderer2) {}\n\n get currentElement() {\n return window.getComputedStyle(this.elementRef.nativeElement);\n }\n\n @HostListener('mouseenter')\n onMouseEnter() {\n // console.log('ENTER', this.currentElement)\n this.colorValue.emit(this.currentElement.getPropertyValue('background-color'))\n }\n\n @HostListener('mouseleave')\n onMouseLeave() {\n // console.log('LEAVE', this.currentElement.getPropertyValue('background-color'))\n this.colorValue.emit('white')\n }\n\n}\n","import { Injectable } from '@angular/core'\r\nimport { BehaviorSubject } from 'rxjs'\r\nimport { ColorConversionService } from './color-conversion.service'\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class ColorPalletteService {\r\n\r\n // define image path\r\n // this.colorSelectionService.getColorsFromImage('../assets/sample2.jpg')\r\n\r\n // get colors\r\n // this.colorSelectionService.palette.subscribe(data => this.palette = data)\r\n\r\n // sample html\r\n // <div *ngFor=\"let color of palette\">\r\n // <div style=\"display: flex;\">\r\n // <div\r\n // class=\"box\"\r\n // [style.background-color]=\"color.color\"\r\n // >\r\n // Color\r\n // </div>\r\n // <div\r\n // class=\"box\"\r\n // [style.background-color]=\"color.complementaryColor\"\r\n // >\r\n // Complementary\r\n // </div>\r\n // </div>\r\n // </div>\r\n\r\n // CSS\r\n // .box {\r\n // width: 100px;\r\n // height: 100px;\r\n // border: solid thin black;\r\n // color: black;\r\n // margin: 4px;\r\n // padding: 16px;\r\n // display: flex;\r\n // flex-wrap: wrap;\r\n // align-content: center;\r\n // justify-content: center;\r\n // }\r\n\r\n private palette = new BehaviorSubject<{ color: string, complementaryColor: string }[]>([])\r\n\r\n constructor(\r\n private colorConversionService: ColorConversionService\r\n ) { }\r\n\r\n getColorsFromImage(imagePath: string, colors = 3) {\r\n\r\n const image = new Image()\r\n image.src = imagePath\r\n\r\n image.onload = () => {\r\n const data = this.generateColorPalette(image, colors) || []\r\n this.palette.next(data)\r\n }\r\n\r\n }\r\n\r\n generateColorPalette(image: HTMLImageElement, colorCount = 6) {\r\n\r\n const canvas = document.createElement('canvas')\r\n const context = canvas.getContext('2d')\r\n\r\n if(!context || !image) return\r\n\r\n canvas.width = image.width\r\n canvas.height = image.height\r\n context.drawImage(image, 0, 0)\r\n\r\n // Get the image data\r\n const imageData = context.getImageData(0, 0, canvas.width, canvas.height)\r\n const pixels = imageData.data\r\n const pixelCount = imageData.width * imageData.height\r\n\r\n // Build an array of RGB colors\r\n const colors = []\r\n for (let i = 0; i < pixelCount; i++) {\r\n const offset = i * 4\r\n const r = pixels[offset]\r\n const g = pixels[offset + 1]\r\n const b = pixels[offset + 2]\r\n colors.push([r, g, b])\r\n }\r\n\r\n // Apply color quantization using k-means clustering\r\n const quantizedColors = this.kMeansColorQuantization(colors, colorCount)\r\n\r\n // Order colors by luminance\r\n quantizedColors.sort((color1, color2) => {\r\n const luminance1 = this.getLuminance(color1)\r\n const luminance2 = this.getLuminance(color2)\r\n return luminance2 - luminance1\r\n })\r\n\r\n const palette = quantizedColors.map(color => {\r\n const complementaryColor = color.map(component => 255 - component)\r\n const hexColor = this.colorConversionService.rgbToHex(color)\r\n const hexComplementaryColor = this.colorConversionService.rgbToHex(complementaryColor)\r\n return { color: hexColor, complementaryColor: hexComplementaryColor }\r\n })\r\n\r\n return palette\r\n }\r\n\r\n private getLuminance(color: number[]) {\r\n const [r, g, b] = color\r\n return 0.299 * r + 0.587 * g + 0.114 * b\r\n }\r\n\r\n private calculateColorDistance(color1: number[], color2: number[]) {\r\n const [r1, g1, b1] = color1\r\n const [r2, g2, b2] = color2\r\n const dr = r2 - r1\r\n const dg = g2 - g1\r\n const db = b2 - b1\r\n return Math.sqrt(dr * dr + dg * dg + db * db)\r\n }\r\n\r\n private calculateMeanColor(colors: number[][]) {\r\n let sumR = 0\r\n let sumG = 0\r\n let sumB = 0\r\n for (let i = 0; i < colors.length; i++) {\r\n const [r, g, b] = colors[i]\r\n sumR += r\r\n sumG += g\r\n sumB += b\r\n }\r\n const meanR = Math.round(sumR / colors.length)\r\n const meanG = Math.round(sumG / colors.length)\r\n const meanB = Math.round(sumB / colors.length)\r\n return [meanR, meanG, meanB]\r\n }\r\n\r\n private kMeansColorQuantization(colors: number[][], k: number) {\r\n const clusterCenters = []\r\n for (let i = 0; i < k; i++) {\r\n const randomColor = colors[Math.floor(Math.random() * colors.length)]\r\n clusterCenters.push(randomColor)\r\n }\r\n\r\n const clusters = []\r\n for (let i = 0; i < colors.length; i++) {\r\n const color = colors[i]\r\n let minDistance = Infinity\r\n let nearestCenter = null\r\n for (let j = 0; j < clusterCenters.length; j++) {\r\n const center = clusterCenters[j]\r\n const distance = this.calculateColorDistance(color, center)\r\n if (distance < minDistance) {\r\n minDistance = distance\r\n nearestCenter = center\r\n }\r\n }\r\n clusters.push({ color, center: nearestCenter })\r\n }\r\n\r\n const updatedCenters = []\r\n for (let i = 0; i < clusterCenters.length; i++) {\r\n const center = clusterCenters[i]\r\n const clusterColors = clusters.filter(c => c.center === center).map(c => c.color)\r\n if (clusterColors.length > 0) {\r\n const updatedCenter = this.calculateMeanColor(clusterColors)\r\n updatedCenters.push(updatedCenter)\r\n }\r\n }\r\n\r\n return updatedCenters\r\n }\r\n\r\n}\r\n","import { Injectable } from '@angular/core'\r\nimport { ColorConversionService } from './color-conversion.service'\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class TextColorService {\r\n\r\n constructor(\r\n private colorConversionService: ColorConversionService\r\n ) {}\r\n\r\n textColorForBgColor(bgColor: string, lightColor: string, darkColor: string) {\r\n\r\n const UIColors = this.fixColor(bgColor)\r\n\r\n const r = UIColors[0]\r\n const g = UIColors[1]\r\n const b = UIColors[2]\r\n\r\n return ((r*0.299 + g*0.587 + b*0.114) > 149) ? darkColor : lightColor;\r\n\r\n }\r\n\r\n darkerColor(color1: string, color2: string) {\r\n return (this.isColorDarker(color1,color2)) ? color1 : color2;\r\n }\r\n\r\n isColorDarker(color1: string, color2: string) {\r\n\r\n const newColor1 = this.fixColor(color1)\r\n const newColor2 = this.fixColor(color2)\r\n\r\n const luminance1 = this.calculateLuminance(newColor1[0], newColor1[1], newColor1[2])\r\n const luminance2 = this.calculateLuminance(newColor2[0], newColor2[1], newColor2[2])\r\n\r\n return (luminance1 > luminance2)\r\n\r\n }\r\n\r\n lighterColor(color1: string, color2: string): string {\r\n return (this.isColorLighter(color1,color2)) ? color1 : color2;\r\n }\r\n\r\n isColorLighter(color1: string, color2: string) {\r\n \r\n const newColor1 = this.fixColor(color1);\r\n const newColor2 = this.fixColor(color2);\r\n \r\n const luminance1 = this.calculateLuminance(newColor1[0], newColor1[1], newColor1[2]);\r\n const luminance2 = this.calculateLuminance(newColor2[0], newColor2[1], newColor2[2]);\r\n \r\n return (luminance1 > luminance2)\r\n\r\n }\r\n\r\n calculateLuminance(r: number, g: number, b: number): number {\r\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\r\n }\r\n\r\n fixColor(color: string) {\r\n\r\n let newColor = color\r\n\r\n if(color.includes('#')) {\r\n newColor = color.slice(1)\r\n newColor = (newColor.length === 3) ? '#' + newColor.split('').map(hex => hex + hex).join('') : '#' + newColor\r\n }\r\n\r\n const Reg_Exp = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/\r\n const colorIsHex = Reg_Exp.test(newColor)\r\n\r\n const UIColors = (colorIsHex) ? this.colorConversionService.hexToRgb(newColor) : newColor.match(/\\d+/g)?.map(item => parseInt(item)) || []\r\n\r\n return UIColors\r\n\r\n }\r\n\r\n}\r\n","/*\n * Public API Surface of color-utils\n */\n\nexport * from './lib/color-conversion.service';\nexport * from './lib/color-extractor.directive';\nexport * from './lib/color-pallette.service';\nexport * from './lib/text-color.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.ColorConversionService"],"mappings":"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"}
package/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ /// <amd-module name="color-util-helpers" />
5
+ export * from './public-api';
@@ -0,0 +1,8 @@
1
+ import * as i0 from "@angular/core";
2
+ export declare class ColorConversionService {
3
+ rgbToHex(rgb: number[] | null): string;
4
+ private componentToHex;
5
+ hexToRgb(hex: string | null | undefined): number[];
6
+ static ɵfac: i0.ɵɵFactoryDeclaration<ColorConversionService, never>;
7
+ static ɵprov: i0.ɵɵInjectableDeclaration<ColorConversionService>;
8
+ }
@@ -0,0 +1,13 @@
1
+ import { ElementRef, Renderer2, EventEmitter } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ export declare class ColorExtractorDirective {
4
+ private elementRef;
5
+ private renderer;
6
+ colorValue: EventEmitter<string>;
7
+ constructor(elementRef: ElementRef, renderer: Renderer2);
8
+ get currentElement(): CSSStyleDeclaration;
9
+ onMouseEnter(): void;
10
+ onMouseLeave(): void;
11
+ static ɵfac: i0.ɵɵFactoryDeclaration<ColorExtractorDirective, never>;
12
+ static ɵdir: i0.ɵɵDirectiveDeclaration<ColorExtractorDirective, "[getColor]", never, {}, { "colorValue": "colorValue"; }, never, never, false, never>;
13
+ }
@@ -0,0 +1,18 @@
1
+ import { ColorConversionService } from './color-conversion.service';
2
+ import * as i0 from "@angular/core";
3
+ export declare class ColorPalletteService {
4
+ private colorConversionService;
5
+ private palette;
6
+ constructor(colorConversionService: ColorConversionService);
7
+ getColorsFromImage(imagePath: string, colors?: number): void;
8
+ generateColorPalette(image: HTMLImageElement, colorCount?: number): {
9
+ color: string;
10
+ complementaryColor: string;
11
+ }[] | undefined;
12
+ private getLuminance;
13
+ private calculateColorDistance;
14
+ private calculateMeanColor;
15
+ private kMeansColorQuantization;
16
+ static ɵfac: i0.ɵɵFactoryDeclaration<ColorPalletteService, never>;
17
+ static ɵprov: i0.ɵɵInjectableDeclaration<ColorPalletteService>;
18
+ }
@@ -0,0 +1,15 @@
1
+ import { ColorConversionService } from './color-conversion.service';
2
+ import * as i0 from "@angular/core";
3
+ export declare class TextColorService {
4
+ private colorConversionService;
5
+ constructor(colorConversionService: ColorConversionService);
6
+ textColorForBgColor(bgColor: string, lightColor: string, darkColor: string): string;
7
+ darkerColor(color1: string, color2: string): string;
8
+ isColorDarker(color1: string, color2: string): boolean;
9
+ lighterColor(color1: string, color2: string): string;
10
+ isColorLighter(color1: string, color2: string): boolean;
11
+ calculateLuminance(r: number, g: number, b: number): number;
12
+ fixColor(color: string): number[];
13
+ static ɵfac: i0.ɵɵFactoryDeclaration<TextColorService, never>;
14
+ static ɵprov: i0.ɵɵInjectableDeclaration<TextColorService>;
15
+ }
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "color-util-helpers",
3
+ "version": "1.0.2",
4
+ "peerDependencies": {
5
+ "@angular/common": "^15.2.0",
6
+ "@angular/core": "^15.2.0"
7
+ },
8
+ "dependencies": {
9
+ "tslib": "^2.3.0"
10
+ },
11
+ "sideEffects": false,
12
+ "module": "fesm2022/color-util-helpers.mjs",
13
+ "typings": "index.d.ts",
14
+ "exports": {
15
+ "./package.json": {
16
+ "default": "./package.json"
17
+ },
18
+ ".": {
19
+ "types": "./index.d.ts",
20
+ "esm2022": "./esm2022/color-util-helpers.mjs",
21
+ "esm": "./esm2022/color-util-helpers.mjs",
22
+ "default": "./fesm2022/color-util-helpers.mjs"
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,4 @@
1
+ export * from './lib/color-conversion.service';
2
+ export * from './lib/color-extractor.directive';
3
+ export * from './lib/color-pallette.service';
4
+ export * from './lib/text-color.service';