[NOTE: The live web app that encompasses this functionality can be found here: https://www.paintmap.studio. All of the underlying code for that site can be found here: https://github.com/bytebodger/color-map.]
In the previous articles of this series, I went into extensive detail about subjects such as pixelating, color matching, dithering, and color depth. But I wanted to wrap it up by showing how I personally use these features - specifically, as it pertains to my painting.
Color inventory
Once I'm done tinkering with an image in Paint Map Studio, I need some information about the transformed image itself. On the home page, all of the output is in the form of the rendered image. But at some point I'll need to see how that image translates into colors.
When the image has finished rendering, two new links appear in the top nav. One is "MAP". The other is "STATS". First, we'll look at STATS.
STATS shows a list of all paints that were matched in the image, listed in descending order. The most-used paints are at the top. The least-used are at the bottom.
And here's what the Stats component looks like:
// Stats.js
export const Stats = () => {
const uiState = useContext(UIState);
const navigateTo = useNavigate();
const allColors = useAllColors();
let colors = [];
const getColorCell = (paintName = '') => {
const color = uiState.stats.colors.find(color => color.name === paintName);
return <TableCell style={{backgroundColor: `rgb(${color.red}, ${color.green}, ${color.blue})`}}/>;
}
const getTableRows = () => {
colors = allColors.get();
const colorCounts = sortColorCounts(uiState.stats);
return colorCounts.map((colorCount, index) => {
const [paintName, count] = colorCount;
const paintIndex = colors.findIndex(color => color.name === paintName);
return (
<TableRow
key={paintName}
sx={{'&:last-child td, &:last-child th': {border: 0}}}
>
<TableCell style={{textAlign: css3.textAlign.center}}><b>{index + 1}.</b></TableCell>
<TableCell style={{textAlign: css3.textAlign.center}}>{paintIndex}</TableCell>
<TableCell style={{textAlign: css3.textAlign.center}}>{count}</TableCell>
{getColorCell(paintName)}
<TableCell>
<span
className={'paintName'}
id={paintName}
onClick={handlePaintNameClick}
>
{paintName}
</span>
</TableCell>
</TableRow>
);
})
}
const handlePaintNameClick = (event = {}) => {
uiState.toggleHighlightedColor(event.target.id);
navigateTo('/map');
}
const sortColorCounts = (stats = {}) => {
const sort = (a, b) => {
const [, aCount] = a;
const [, bCount] = b;
if (aCount > bCount)
return -1;
else if (aCount < bCount)
return 1;
else
return 0;
};
const colorCounts = [];
Object.entries(stats.colorCounts).forEach(colorCount => colorCounts.push(colorCount));
return colorCounts.sort(sort);
};
const navigateToMap = () => navigateTo('/map');
if (Object.keys(uiState.stats
