Recoloring an image based on current theme? - c++

I want to develop a program which recolors the input image based on the given theme the same way as ms-powerpoint application does.
I am giving following link that shows what exactly i want to do.
I want to generate images same as images in below link under the Dark Variations and light Variations title based on the current theme.
http://blogs.msdn.com/powerpoint/archive/2006/07/06/658238.aspx
Can anybody give me idea,info regarding how to achieve it efficiently ??

You can give a look to the HSL colorspace to be able to have the same result. HSL means Hue, Saturation, Lightness.
You can keep the lightness of each pixel of your image and change only the hue. I think this will allow you to achieve what you want. You can find the RGB to HSL conversion on the wiki page.
Hope that helps.

Step 1: Choose the colors you want to represent black and white. For the dark variations, choose black and a light color; for the light variations, choose a dark color and white.
Step 2: Convert a pixel to gray. A common formula for this is L = R*0.3 + G*0.59 + B*0.11.
Step 3: Interpolate between the colors using the gray value. output.R = (L/255)*light.R + (1-(L/255))*dark.R and likewise for green and blue.

You can use a library like CxImage and convert the image to grayscale, then use the mix command with another image that you have made that is the same size as the original, and mix the two with the Mix command, using the filters. You can do mix-screen, and this should tint the pixels the color of the second image in the resultant image. Try playing with CxImage a bit, see if it will do what you want it to do. This is all coming off the top of my head, and its been a while since I have tried to do anything like this. YMMV, but this would be the simplest implementation. You could always look at how CxImage does the blend, and apply it to the image yourself.

I must say thanks to Mark and Patrice for ur guidance which helped me achieved it.
For light variation, I have done it by converting the theme colors to HSV colorspace and found relation between output color and theme color for black color (input) .
The relation was found to be linear for saturation and value and hue was almost constant.
I have used interpolation formula to make it generic for any given theme.
I have also make use of color matrix to achieve desired result.
Similarly for dark variation i have used white color as input and apply the same technique.

Related

How to find color of the objects(cloth color of human being)?

I had come across several stack overflow questions and solutions, in all the questions the solution is based on a particular color(red or green or blue). I need to identify the color of objects which are of multiple type. I need to detect color which ranged between 0 to 255. So can anybody help me with a solution based on opencv.
Thanks in advance.
If you already know about what could be the possible color then it very simple. I will talk about one example and you can follow the same procedure for rest.
Lets say that you have several possible combinations, for example a t-shirt could have red and cyan color and you already have an image of such a sample. Then you should do the following:
Step-1: Load the template/sample image. Calculate its Hue-histogram (or Hue-Saturation histogram).
Step-2: Load the image for which you want to know the color. Calculte the histogram for this image also.
Step-3: Perform histogram matching() between all the sample/template/example/possbile image's histogram (i.e. step-1) and the image for which you want to know the color (i.e. step-2).
Step-4: For which so ever combination, you get the maximum value...your image has that color. For example, lets say your sample images have an image of red & cyan t-shirt, another image of bule & purple t-shirt and so on. And you get the maximum histogram matching() value for blue& purple , it means that your image for which you want to know have blue and purple color.

Range of HSV values to sample an Image as done by adobe

I have an image as shown in the inset. I sampled it in Adobe Photoshop using the blue color as the image shows. The sampled image is shown in gray-scale on the left.
I know that openCV provides a similar method to sample images that is the inRange() function. How can I find out the range of HSV values that Adobe checked for to sample my image. Since the resultant image is pretty much what I want and I am not able to determine the range myself It would be a great help if some one could guide me for the same.
You can convert your image in HSV with cv::cvtColor(...) here the documentation
Then accordingly to Wikipedia the blue is near to 240° of the HUE channel of your image.
You can set something like maxHue = 270 and a minHue = 180 or other values to scan your image.
Maybe you should set a minSaturation and a minValue to avoid the black and white.
To find the best ranges you can link them with some sliders in a Qt GUI and change them until you get the same result as photoshop...

Determine most visible foreground color [duplicate]

I'm drawing a color selection button and I'm looking for a nice and simple formula to get a good text color (foreground) for a given background color in RGB.
A simple try would be to just take the complement color but this will produce an odd looking button for colors like pure blue or pure red.
Is there something well known that does this?
If it matters at all, I'm using QT.
For maximum legibility, you want maximum brightness contrast without getting into hues which don't work together. The most consistent way to do this is to stick with black or white for the text color. You might be able to come up with more aesthetically pleasing schemes, but none of them will be more legible.
To pick between black or white, you need to know the brightness of the background. This gets a little more complicated, due to two factors:
The perceived brightness of the individual primaries red, green, and blue are not identical. The quickest advice I can give is to use the traditional formula to convert RGB to gray - R*0.299 + G*0.587 + B*0.114. There are lots of other formulas.
The gamma curve applied to displays makes the middle gray value higher than you'd expect. This is easily solved by using 186 as the middle value rather than 128. Anything less than 186 should use white text, anything greater than 186 should use black text.
I'm no expert on programming things related to RGB, but from a designer's perspective, often the most readable color will be just a much lighter (if the background color is dark) or darker (if the background color is light) version of the same shade.
Basically you'd take your RGB values and if they're closer to 0 (dark) you'd push them each up by an equal amount for your foreground color, or vice versa if it's a light BG.
Complement colors can actually be really painful on the eyes for readability.
Leverage an outline for legibility
If by "good text color (foreground)" you intend it for legibility purposes when the user chooses any background colour, you can always produce white text having a black outline. It will be legible on any solid, patterned or gradient background, from black through white and anything in between.
Even if this doesn't hit the mark of your intention, I think it worthwhile posted here because I came looking for similar solutions.
Building on top of Mark's response, here's some Ruby code that'll do the work
rgbval = "8A23C0".hex
r = rgbval >> 16
g = (rgbval & 65280) >> 8
b = rgbval & 255
brightness = r*0.299 + g*0.587 + b*0.114
return (brightness > 160) ? "#000" : "#fff"
You are better off with a high difference in luminosity. In general, colored backgrounds with colored text suck for readability, hurting the eyes over time. Lightly tinted colors (e.g. in HSB, S~10%, B>90%) with black text work fine, or lightly tinted text over a black background. I'd stay away from coloring both. Dark text (b~30%, s>50%) with a subtle coloration over a white background can also be fine. Yellow (amber) text on a deep blue background has excellent readability, as does amber or green on black. This is why old dumbterms (vt100, vt52, etc.) went for these colors.
If you really need to do color-on-color for the 'look', you could reverse both H and B, while pinning saturation at a moderate to low level.
And one last note: if you have a 50% gray background, rethink your interface. You're robbing yourself of half your dynamic range! You're alienating low-visibility users, including anyone over 35...
Color combinations often look terrible when not carefully chosen. Why not use either white or black for the text, depending on the Brightness of the color. (Will need to convert to HSB first.)
Or let the user choose either black or white text.
Or use pre-defined combinations. This is what Google does in their calendar product.
I've been looking for a simailr answer and came across this post and some others that I thought I'd share. According to http://juicystudio.com/services/luminositycontrastratio.php#specify the "Success Criterion 1.4.3 of WCAG 2.0 requires the visual presentation of text and images of text has a contrast ratio of at least 4.5:1" with some exceptions. That site lets you put in foreground and background colors to compute their contrast, although it would be helpful if it would suggest alternatives or ranges.
One of the best sites I've found for visualizing color contrast is http://colorizer.org/ It lets you adjust almost all manner of color scales (RGB, CMYK, etc.) at the same time and then shows you the result on the screen, such as white text on a yellow background.
I usually look at color complements, they also have color complement wheels to help
http://www.makart.com/resources/artclass/cwheel.html
If your color is HSL, flip the Hue by 180 degrees for a decent calculation
I wanted to put #MarkRansom's answer into use and managed to create this snippet:
I got the values From seeing how sRGB converts to CIE XYZ and built upon that.
The script simply tracks the position of the foreground item and it's position regarding the colored background items.
Then based on background luminosity it gradually changes the foreground text color to either black or white.
Open the codepen for full example
https://codepen.io/AndrewKnife/pen/XWBggQq
const calculateLight = (colorItem: number) => {
let c = colorItem / 255.0;
if (c <= 0.03928) {
c /= 12.92;
} else {
c = Math.pow((c + 0.055) / 1.055, 2.4);
}
return c;
};
const calculateLuminosity = (color: RGBColor) => {
return (
0.2126 * calculateLight(color.r) +
0.7152 * calculateLight(color.g) +
0.0722 * calculateLight(color.b)
);
};
const getContrastColor = (color: RGBColor) => {
if (calculateLuminosity(color) > LUMINOSITY_LIMIT) {
return FONT_COLOR_DARK;
}
return FONT_COLOR_LIGHT;
};
I thing that converting to HSV might be the way, but IMO changing hue would look weird. I'd try keeping the hue and fiddling with value and maybe saturation (light red buttons with dark red text ... hm sounds scary :-) ).

OpenCV - HSV range of values for tracking red color

Could you please tell me how to what are ranges for Hue, Saturation and Value indices for intense red?
I try to use this values for color tracking and I couldn't find a specific answer via Google.
you can map any color to OpenCV HSV. Actually opencv use 1800 hue cylinder while ideally it is 360, on the orher hand MS paint use 2400 cyllinder.
So to get OpenCV HSV value, simply open MS paint, open mixer, and read the value of HSV, now to map this value into OpenCV HSV multiply it with 180/240.
the range to value for saturation and value is 00-1800
You are the only one who can answer this question, since we don't know your criteria for "intense red". Collect as many samples as you can, some of which you consider intense red and some which are close but just miss the cut. Convert them all to HSL. Study the pattern.
You might put together a small app that has sliders for the H, S, and L parameters and displays a block of color corresponding to the settings. That will tell you your limits very quickly.

transparent colour being shown some of the time

I am using a LPDIRECT3DTEXTURE9 to hold my image.
This is the function used to display my picture.
int drawcharacter(SPRITE& person, LPDIRECT3DTEXTURE9& image)
{
position.x = (float)person.x;
position.y = (float)person.y;
sprite_handler->Draw(
image,
&srcRect,
NULL,
&position,
D3DCOLOR_XRGB(255,255,255));
return 0;
}
According to the book I have the RGB colour shown as the last parameter will not be displayed on screen, this is how you create transparency.
This works for the most part but leaves a pink line around my image and the edge of the picture. After trial and error I have found that if I go back into photoshop I can eliminate the pink box by drawing over it with the pink colour. This can be see with the ships on the left.
I am starting to think that photoshop is blending the edges of the image so that background is not all the same shade of pink though I have no proof.
Can anyone help fix this by programming or is the error in the image?
If anyone is good at photoshop can they tell me how to fix the image, I use png mostly but am willing to change if necessary.
edit: texture creation code as requested
character_image = LoadTexture("character.bmp", D3DCOLOR_XRGB(255,0,255));
if (character_image == NULL)
return 0;
You are loading a BMP image, which does not support transparency natively - the last parameter D3DCOLOR_XRGB(255,0,255) is being used to add transparency to an image which doesn't have any. The problem is that the color must match exactly, if it is off even by only one it will not be converted to transparent and you will see the near-magenta showing through.
Save your images as 24-bit PNG with transparency, and if you load them correctly there will be no problems. Also don't add the magenta background before you save them.
As you already use PNG, you can just store the alpha value there directly from Photoshop. PNG supports transparency out of the box, and it can give better appearance than what you get with transparent colour.
It's described in http://www.toymaker.info/Games/html/textures.html (for example).
Photoshop is anti-aliasing the edge of the image. If it determines that 30% of a pixel is inside the image and 70% is outside, it sets the alpha value for that pixel to 70%. This gives a much smoother result than using a pixel-based transparency mask. You seem to be throwing these alpha values away, is that right? The pink presumably comes from the way that Photoshop displays partially transparent pixels.