img2ral
Hello and welcome to the New Year! It’s been quite some time since my last post. I must admit that the pace of work at my current job is quite high, which means I spend my free time relaxing, especially away from the computer 🥲. It’s very interesting to experience firsthand how significant the difference in work efficiency can be between different companies. OK, enough of these loose thoughts. Today, I would like to share with you a new project I recently started working on - I have tentatively named it img2ral.
RAL is a color management system created by the German company RAL GmbH. These colors have wide applications in the industry. You might be wondering why I chose this topic for my mini project - let me explain. Some time ago, I decided that the room where I work (since I work fully remotely, I mean my living room) needed a little makeover. Specifically, the wall where the TV is located. After meeting with a carpenter and discussing the project concept, I decided on a lacquered wall decor. The company that makes this decor uses the RAL palette. My task was to choose the right color to match the surroundings. I wanted to find a color similar to the floor.
My first idea was simple: I took a photo which I embedded on an HTML page. In the next step, using the Color Picker for Chrome, I selected several pixels and noted their colors (in RGB scale). From Wikipedia, I copied the RAL colors between range 1000-1020, which seemed to me the closest to the floor.
The idea for processing was also simple: having template colors (from the RAL palette), I compared each pixel from the image with the Euclidean distance formula to those from the template. The color which is closest in Euclidean space should be the most similar.
const RAL_COLORS = [
{ hex: '#CDBA88', colorName: 'Green beige' },
{ hex: '#D0B084', colorName: 'Beige' },
{ hex: '#D2AA6D', colorName: 'Sand yellow' },
{ hex: '#F9A800', colorName: 'Signal yellow' }
// ... more colors here
]
function hexToRgb(hex) {
let bigint = parseInt(hex.replace(/^#/, ''), 16)
return {
r: (bigint >> 16) & 255,
g: (bigint >> 8) & 255,
b: bigint & 255
}
}
function colorDistance(color1, color2) {
return Math.sqrt(
Math.pow(color1.r - color2.r, 2) +
Math.pow(color1.g - color2.g, 2) +
Math.pow(color1.b - color2.b, 2)
)
}
function findClosestColor([r, g, b], RAL_COLORS) {
let closestColor = null
let minDistance = Infinity
RAL_COLORS.forEach((colorObj) => {
const targetRgb = hexToRgb(colorObj.hex)
const distance = colorDistance({ r, g, b }, targetRgb)
if (distance < minDistance) {
minDistance = distance
closestColor = colorObj
}
})
return closestColor
}
const imagePixelRGB = [213, 198, 164]
console.log(findClosestColor(pixelRGB, RAL_COLORS))
I run script for all pixels I picked from original image. As a result, I got these colors: Ivory, Brown beige, Sand yellow as the most similar to my floor. Not all of the resulting colors are very similar; however, if you take a look into original photo, you will see that this floor is uneven with many shades, and the sample pixels were chosen in random places. Eventually, I decided that Ivory could be a good candidate for wall decor. But it’s not the end of the story 🤣🤣🤣.
I thought it would be good to automate this process. Of course, I’m not the first to come up with this idea. I found other applications that do the job, like ral-colours or color from picture. However, these apps don’t have a user-friendly interface and lack advanced functionality (I’m thinking about auto suggestions based on image histogram or the possibility to crop the image to the desired part). Thus, I think it would be good to have such an app.
To speed up the work a bit, I decided to use GitHub Copilot 🧐. I copied the HTML code from Wikipedia containing the table with all the colors from the palette and saved it to a local file. Copilot generated an object for me that maps the color number to its Hex value and name. Then I asked Copilot to create an accordion effect from the color samples (you can see its effect as the main image of this post). As always with AI collaboration, manual corrections were required to bring the code to order. Currently, the functionality of uploading an image is still missing, but I hope to complete this functionality this month. The project is deployed under this URL.
I hope the project will be helpful and will solve some interior design problems. That’s all for today. Once again, I wish all readers all the best in the New Year 2025!!!