Skip to content

Commit

Permalink
Extract color palette from image (#152)
Browse files Browse the repository at this point in the history
* Add mechanism for extract color palette from image

* types

* better types
  • Loading branch information
mcnuttandrew authored Oct 20, 2024
1 parent 1e6e0ce commit cee753d
Show file tree
Hide file tree
Showing 4 changed files with 1,905 additions and 858 deletions.
1 change: 1 addition & 0 deletions apps/color-buddy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"color-buddy-palette": "*",
"color-buddy-palette-lint": "*",
"colorjs.io": "^0.5.2",
"colorthief": "^2.6.0",
"d3-scale": "^4.0.2",
"d3-shape": "^3.2.0",
"driver.js": "^1.3.1",
Expand Down
59 changes: 58 additions & 1 deletion apps/color-buddy/src/controls/NewPal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
import configStore from "../stores/config-store";
import { processBodyTextToColors, newGenericPal } from "../lib/utils";
import { buttonStyle, denseButtonStyle } from "../lib/styles";
import { buttonStyle } from "../lib/styles";
import Tooltip from "../components/Tooltip.svelte";
import SuggestColorPal from "./SuggestColorPal.svelte";
import ColorThief from "colorthief";
$: currentPal = $colorStore.palettes[$colorStore.currentPal];
$: colorSpace = currentPal ? currentPal.colorSpace : "lab";
Expand Down Expand Up @@ -39,6 +40,48 @@
return;
}
}
let palFromImgError = "";
let palFromImgState: "idle" | "loading" = "idle";
function processImg(e: any, onClick: () => void) {
const colorThief = new ColorThief();
palFromImgState = "loading";
try {
const target = e.target as HTMLInputElement;
const files = target?.files;
console.log(files);
if (!files) {
return;
}
const file = [...files].at(0);
if (!file) {
return;
}
const reader = new FileReader();
reader.onload = (e) => {
const img = new Image();
img.src = (e.target as FileReader).result as string;
img.onload = () => {
try {
const colors = colorThief.getPalette(img, 5) as number[][];
const palRGB = colors.map((x) => `rgb(${x.join(", ")})`);
const pal = makePalFromString(palRGB);
console.log(colors);
newPal(pal, onClick);
} catch (e) {
console.error(e);
palFromImgState = "idle";
palFromImgError = "Error processing image";
}
};
};
reader.readAsDataURL(file);
} catch (e) {
console.error(e);
palFromImgError = "Error processing image";
palFromImgState = "idle";
}
}
</script>

<Tooltip>
Expand Down Expand Up @@ -114,6 +157,20 @@
<div class="font-bold">Generate a new palette using AI</div>
<SuggestColorPal />
{/if}
<div class="mt-5 border-t border-black"></div>
<div class="font-bold">Generate From Image (png or jpg)</div>
<input
type="file"
accept="image/*"
id="file"
on:change={(e) => processImg(e, onClick)}
/>
{#if palFromImgState === "loading"}
<div>Loading...</div>
{/if}
{#if palFromImgError}
<div class="text-red-600">{palFromImgError}</div>
{/if}
</div>
<button
slot="target"
Expand Down
17 changes: 17 additions & 0 deletions apps/color-buddy/src/custom-types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,20 @@ declare module "color-blind" {
const blinder: any;
export default blinder;
}

// https://github.com/lokesh/color-thief/issues/188
declare module "colorthief" {
export type RGBColor = [number, number, number];
export default class ColorThief {
getColor: (
img: HTMLImageElement | null,
quality: number = 10
) => RGBColor | null;

getPalette: (
img: HTMLImageElement | null,
colorCount: number = 10,
quality: number = 10
) => RGBColor[] | null;
}
}
Loading

0 comments on commit cee753d

Please sign in to comment.