ignace Posted February 12, 2016 Share Posted February 12, 2016 Hi, I am building a 2D car configurator and I need some help with the coloring. Currently I am using this technique to color the car: http://jsfiddle.net/m1erickson/2d7ZN/ But now I am wondering how can I select a color using a color picker like this: <form action="" method="post"> <label for="color">Pick color</color> <input type="color" name="color" id="color"> </form>And then transform the selected color to match the car's (thus keeping the reflection). I am not looking specifically for code more the name of the algorithm or technique to get me on my way. I am guessing it's something with taking the RGB value of a pixel of the car and then somehow closely represent this color in the other color. Entering that in Google returns squat. Maybe one of you have experience in this sort of thing? Quote Link to comment Share on other sites More sharing options...
requinix Posted February 12, 2016 Share Posted February 12, 2016 That technique works well (for images that aren't too large, at least) but only works because it recolors by shifting the hue of each relevant pixel (it being much easier to do this using HSL than with RGB). It's not so much a mapping of blue to green but a mapping of a range of green colors of some size to a range of blue colors of the same size. So you have to figure out two ranges: what you want to recolor from and what you want to recolor to. If all you have to work with is "blue" or "green" then you can guess by picking the midpoint of the hue range for that color and adding/subtracting roughly 60° *. Those will affect the if condition and the colorshift value, so it's probably best to make those all parameters. function recolorPants(hueStart, hueEnd, colorshift) { // correct hueStart and hueEnd for out-of-range values, both <0 and >=360 hueStart = (360 + (hueStart % 360)) % 360; hueEnd = (360 + (hueEnd % 360)) % 360; if (hueStart < hueEnd && hue > hueStart && hue < hueEnd || hueStart > hueEnd && (hue > hueStart || hue < hueEnd)) {- If the color you're starting with is RGB, convert it to HSL and use the hue value.- I suggest "bold" colors for the color choices; you can convert hue=0..360°, saturation=100%, lightness=50% to get them. * Hue ranges from 0 to 360°, and with 6 basic colors that's 60° per color and ±30°. But there's also overlap - consider how teal is greenish and blueish. So you bump that limit out to, say, 50-60° instead. Quote Link to comment Share on other sites More sharing options...
ignace Posted February 12, 2016 Author Share Posted February 12, 2016 Okay I changed the code a bit: function changeColor(color) { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0); var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height); var data = imgData.data, red, green, blue, alpha; var rgb = HexToRGB(color); var hsl = rgbToHsl(rgb.R, rgb.G, rgb.B); for (var i = 0, l = data.length; i < l; i += 4) { red = data[i]; green = data[i + 1]; blue = data[i + 2]; alpha = data[i + 3]; if (alpha < 200) continue; var imgHsl = rgbToHsl(red, green, blue); var newRgb = hslToRgb(hsl.h, hsl.s, imgHsl.l); data[i] = newRgb.r; data[i + 1] = newRgb.g; data[i + 2] = newRgb.b; data[i + 3] = 255; } ctx.putImageData(imgData, 0, 0); }This works for some reason well, I can now create blackish and brownish cars. White however I can't get to work. Because I maintain the luminance of the original image (which is red) the black or brown also appears lighter, so I somehow would need to adjust the luminance of the car according to the color I selected. For dark colors, make it darker, for lighter colors make it lighter. I also can't help but feel that this sort of thing has to be in some sort of game library but I tried EaselJS and THREE but none appear to have this feature. Quote Link to comment Share on other sites More sharing options...
requinix Posted February 13, 2016 Share Posted February 13, 2016 So being able to handle white makes things awkward: it's not a hue range but both a saturation (how much color bleeds in) and lightness (grayscale) range. Playing around, it looks like good ranges are - White is S=[0.0,0.1] L=[0.9,1.0] - Gray is S=[0.0,0.1] L=[0.1,0.9] - Black is S=[0.0,0.1] L=[0.0,0.1] I figure* the best approach would be deciding what HSL ranges constitute each color, then doing some quick math to convert each component between the current color's ranges and the desired color's ranges. For example, you might say that red is H=[330,15] (meaning both [330,360] and [0,15]) S=[0.1,1.0] (so not to overlap with the grayscale) L=[0.1,1.0]; mapping a value which you've determined to qualify as "red" onto "white" could be h[white] = h[red] // hue unchanged s[white] = (s[red] - S[red,min]) / (S[red,max] - S[red,min]) * (S[white,max] - S[white,min]) + S[white,min] // convert 0.1<s[red]<1.0 to 0.0<s[white]<0.1 l[white] = (l[red] - L[red,min]) / (L[red,max] - L[red,min]) * (L[white,max] - L[white,min]) + L[white,min] // convert 0.1<l[red]<1.0 to 0.9<l[white]<1.0 That's a linear transformation - something polynomial (eg, bell curve, sigmoid) would get different results but it would take more planning and math. * I know math and the RGB and HSL colorspaces, but beyond that it's just educated guesswork. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.