relation between light intensity and R,G,B - c

I have a one ambient light with intesity ( 10000,10000, 5000 ). I am trying to color the primitive.
As you know, color values for R,G, and B are between 0 and 255. How can I find color of the pixel according to light intesity ?
platform : linux and programming language c
EDIT :
In ray tracer, we are calculating
for each ambient light in the environment
color . R += Intensity of the light * ambient coefficient for color R
color . G += Intensity of the light * ambient coefficient for color G
color . B += Intensity of the light * ambient coefficient for color B
However, whenever I have tried to emit this pixel color value on the screen with openGL.
set pixel color ( color )
I have taken wrong color because of intensity is high and maximum color value is low.

The question is unclear, as written, so here's some general advice.
Colours in renderers are typically held as values with a nominal range of [0..1] for each of the RGB components.
When those colours are rendered to pixels, they're usually just multiplied by 255 to give a 24-bit colour value (8 bits per component).
If the original values are outside of the [0..1] range they must be "clamped" so that the resulting pixel values fall in the [0..255] range.
That clamping can either be done "per component", which in your case would result in (255, 255, 255), or each component could be divided by the maximum component, giving (255, 255, 127) - i.e. preserving their relative intensities in pseudo-code:
float scale = max(r, g, b);
if (scale < 1) {
scale = 1; // don't normalise colours that are "in range"
}
byte R = 255 * (r < 0 ? 0 : r / scale);
byte G = 255 * (g < 0 ? 0 : g / scale);
byte B = 255 * (b < 0 ? 0 : b / scale);
It's usual for all intermediate calculations to preserve the full dynamic range of intensities. For example, it wouldn't make sense for the Sun to have a brightness of "1", since every other object in the scene would by comparison have an almost infinitesimally small value.
The net result of the clamping will therefore be that light sources which contribute too much light to the scene will produce "saturation" of the image - i.e. the same effect that you get if you leave the shutter open too long on a picture of a bright scene.

It's this one you want:
brightness = sqrt( .241*R*R + .691*G*G + .068*B*B )
Find more here: http://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx
or here: http://en.wikipedia.org/wiki/Luminance_(relative)

Related

Matlab: Plot array such that each value has random shape and a color map

In Matlab:
How do I modify plot(x,y,'o'), where x=1:10 and y=ones(1,10), such that each point in the plot will have a random shape?
And how can I give it colors chosen from a scheme where the value at x=1 is the darkest blue, and x=10 is red (namely some sort of heat map)?
Can this be done without using loops? Perhaps I should replace "plot" with a different function for this purpose (like "scatter"? I don't know...)? The reason is that I am plotting this inside another loop, which is already very long, so I am interested in keeping the running-time short.
Thanks!
First, the plain code:
x = 1:20;
nx = numel(x);
y = ones(1, nx);
% Color map
cm = [linspace(0, 1, nx).' zeros(nx, 1) linspace(1, 0, nx).'];
% Possible markers
m = 'o+*.xsd^vph<>';
nm = numel(m);
figure(1);
hold on;
for k = 1:nx
plot(x(k), y(k), ...
'MarkerSize', 12, ...
'Marker', m(ceil(nm * (rand()))), ...
'MarkerFaceColor', cm(k, :), ...
'MarkerEdgeColor', cm(k, :) ...
);
end
hold off;
And, the output:
Most of this can be found in the MATLAB help for the plot command, at the Specify Line Width, Marker Size, and Marker Color section. Colormaps are simply n x 3 matrices with RGB values ranging from 0 to 1. So, I interpreted the darkest blue as [0 0 1], whereas plain red is [1 0 0]. Now, you just need a linear "interpolation" between those two for n values. Shuffling the marker type is done by simple rand. (One could generate some rand vector with size n beforehand, of course.) I'm not totally sure, if one can put all of these in one single plot command, but I'm highly sceptical. Thus, using a loop was the easiest way right now.

How to plot an NxN array of circles?

I want to plot an NxN array of circles. Just to visualize, I attached an image of what I want to achieve. I'm new in MatlLab so I tried to plot a single circle first, and here is the sample code below:
n = 2^10; % size of mask
M = zeros(n);
I = 1:n;
x = I - n/2; % mask x - coordinates
y = n/2 - I; % mask y - coordinates
[X,Y] = meshgrid(x,y); % create 2-D mask grid
R = 200; % aperture radius
A = (X.^2 + Y.^2 <= R^2); % Circular aperture of radius R
M(A) = 1; % set mask elements inside aperture to 1
imagesc(M) % plot mask
axis image
I really don't have any idea on how to plot a 2D-array of circles. The distance between two circles is two radii. I need this for my research. Hoping anyone can help.A 4 x 4 array of circles.
If you just want to plot a set of circles, you can use the rectangle function within a loop
If in the call to rectangleyou set the Curvature property to 1 it will be drawn as circle (ref. to the documentation).
In the loop you hav to properly set the position of each rectangle (circle) by defining its lower left coordinates along with its width and height.
Having defined with n the number of circles and with d their diameter, you can compute the set of lower left coordinates as:
px=linspace(0,d*(nc-1),nc)
py=linspace(0,d*(nr-1),nr)
The black background can be either obtained by setting the color of the axes or by plotting another rectangle.
Then you can set the xlim and ylim to fit with the external rectangle.
You can also make the axex invisible, by setting its â—‹Visibleproperty tooff`.
Edit #1
Code updated to allow drawing a user-defined number of circles (set the number of rows and the number of columns)
% Define the number of circles
% Number of rows
nr=8
% NUmber of column
nc=8
% Define the diameter of the circle
d=6
% Create an axex and set hold to on
ax=axes
hold on
% Evalaute the lower left position of each circle
px=linspace(0,d*(nc-1),nc)
py=linspace(0,d*(nr-1),nr)
% Plot the background rectangle
rectangle('Position',[px(1),py(1),d*nc,d*nr],'Curvature',[0 0],'facecolor','k')
% Plot all the circles
for i=1:length(px)
for j=1:length(py)
rectangle('Position',[px(i) py(j) d d],'Curvature',1,'facecolor','w')
end
end
% Set the aspect ratio of the axes
daspect([1 1 1])
% Set the XLim and YLim
xlim([px(1) d*nc])
ylim([py(1) d*nr])
% Make the axes invisible
ax.Visible='off'
Edit #2
Aternative solution to address the OP comment:
If I want to make the axes fixed, say I want a meshgrid of 1024 by 1024, (the image size is independent of the circle radius) how do I incorporate it in the code?
If you want to use a fixed (1024 x 1024) mask on which to plot the circles, starting from the cde you've posted in the question, you can simply do the following:
define the number of circles you want to plot, on a (1024 x 1024) mask they can be 2, 4, 8, ...
define a basic mask holding just one circle
identify the points inside that circle and set them to 1
Replicate (using the function repmat the basic mask accoding to the numner of circles to be plotted
The implemntation, based on your code could be:
% Define the number of circles to be plotted
% on a (1024 x 1024) mask they can be 2, 4, 8, ...
n_circles=4
% Define the size of the basic mask
n0 = (2^10)/n_circles;
% Initialize the basic mask
M0 = zeros(n0);
% Define the x and y coordinates of the basic mask
I = 1:n0;
x = I - n0/2;
y = n0/2 - I;
% Create the mask
[X,Y] = meshgrid(x,y);
% Define the radius of the basic circle
R = n0/2;
% Get the indices of the points insiede the basic circle
A = (X.^2 + Y.^2 <= R^2);
% Set basic mask
M0(A) = 1;
% Open a FIgure
figure
% Replicate the basic mask accoding to the numner of circles to be plotted
M=repmat(M0,n_circles,n_circles);
% Display the mask
imagesc(M)
% Set the axes aspect ratio
daspect([1 1 1])

Calculating the Hue of a Color as a 0 - 255 range

I am trying to write a method which will work on WPF's Color struct to return a byte representing the Hue of the Color. I am struggling with the formula, I have written unit tests for the hues of Black (255, 255, 255), Red (255, 0, 0), Green (0, 255, 0), Blue (0, 0, 255), Yellow (255, 255, 0), Cyan (0, 255, 255), Magenta (255, 0, 255) and White (255, 255, 255) - they all pass except Yellow (which returns 1 instead of 42) and Magenta (which tries to return -1 instead of 212 but fails as -1 won't cast into a byte).
My extension methods for GetHue appear as follows:
public static byte GetHue(this Color color)
=> GetHue(color.ToRgbDictionary(), color.GetMinComponent(), color.GetMaxComponent());
private static byte GetHue(Dictionary<ColorComponent, byte> rgbDictionary, ColorComponent minimumRgbComponent, ColorComponent maximumRgbComponent)
{
decimal chroma = rgbDictionary[maximumRgbComponent] - rgbDictionary[minimumRgbComponent];
return (byte)
(
chroma == 0
? 0
: thirdOfByte
* (byte)maximumRgbComponent
+
(
rgbDictionary[MathHelper.Wrap(maximumRgbComponent + 1)]
- rgbDictionary[MathHelper.Wrap(maximumRgbComponent - 1)]
)
/ chroma
);
}
ToRgbDictionary simply turns the Color into a dictionary of its red, green and blue components; ColorComponent is an enum used as the key for those components. MathHelper.Wrap is a method which wraps an enum back into its declared range if it overflows or underflows. GetMinComponent and GetMaxComponent are two other extension methods on Color which return the first lowest and first highest ColorComponents of the Color (where the ColorComponent order is: Red, Green, Blue). thirdOfByte is a constant equal to the byte.MaxValue / 3.
I have based this formula on another I found here (http://www.blackwasp.co.uk/rgbhsl_2.aspx) which looks like this:
private decimal GetH(RGB rgb, decimal max, decimal chroma)
{
decimal h;
if (rgb.R == max)
h = ((rgb.G - rgb.B) / chroma);
else if (rgb.G == max)
h = ((rgb.B - rgb.R) / chroma) + 2M;
else
h = ((rgb.R - rgb.G) / chroma) + 4M;
return 60M * ((h + 6M) % 6M);
}
The problem with that formula is it's mapped to a 0 - 360 hue range, not a 0 - 255 range which is what I need. I'm not sure what the constant numbers in this formula do but I'm guessing the 60 has something to do with 360 / 3 = 120 hence my third of byte constant to try to do something similar. As for the 6Ms I have no idea where they come from nor why they are added to and modulused with the hue value at that stage. Could anyone with a mind for maths help me out here?
UPDATE
The reason for the 0 - 255 range was that I thought that was all that was required having seen it used in another piece of software (as shown) for Hue, Saturation and Lightness. It is also where I obtained the 42 Hue value for Yellow. I am now trying to find the correct range for Hues to cover all possible different hues in a 16777216 (256 * 256 * 256) colour range.
Your "...except Yellow (which returns 1 instead of 42)" what's the logic behind expecting a 42?
It's "mapped to a 0 - 360 hue range" because there are 360 hues in the colour wheel. Even if you had an unsigned byte (holding 256 values), you'd be cropping off the other 104 possible hues. It won't be an accurate representation.
Why not just use a 2-byte short to hold the possible 360 hues instead of using 1 byte?
If you still want to fit 360 inside a 255 range, just do simple math :
byte_value = hue_value / (360/255); //where hue_value is the 0-360 amount.
Try involving Math methods like Math.round to get none fractions as final byte value.
Example 180 hue :
byte_value = Math.round( 180 / (360/255) ); //gives 127

How to interpolate a HSV color?

I am creating an application in win32 api, which will use a progress bar. This progress bar, should change its color. From red (left end) to green(right), and in the middle some yellow.
I searched a little, and found out, that I should use HSV to achieve this. I just don't know how? I found in this link, two functions, to convert the color, from RGB to HSV and back.
But what should I do if the color has been converted to HSV?
Like RGB coordinates, HSV coordinates define a point in a three dimensional space.
You may find a trajectory form one point (x0, one color) to the second (x1) with a formula like:
x = x0 + alpha * (x1-x0)
with alpha varying form 0.0 to 1.0
You can do this for all three components simultaneaously.
With a trajectory from green to red in HSV space you will mainly modify the H (Hue) value. If you want to see some yellow in the middle of your path (and not violett) you need to define a second or even third color and walk
green -> yellow -> red
Edit: Example
int hue0 = 0; // red
int hue2 = 120; // green
// find 100 colors between red and green
for(double alpha = 0; alpha <= 1.0; alpha += 0.01)
{
hueX = hue0 + alpha * (hue1 - hue0);
// same for value, saturation:
// valX = val0 + alpha * (val1 - val0)
// ...
// plot this color
}

Formula to determine transparancy

Say you want to put pixel with a color (R0 G200 B255) in a BMP picture and you have transp option in percents.
How do I determine the new pixel color, considering the transp and the background color?
I actually could figure out a formula that looks promising:
newpixel = newpixel + (bgpixel * transp) / %(transp of 255)
I created it by analyzing the pixel color change in GIMP. Not sure if that is the correct formula. I think it is also rounded up.
The standard formula is pixel = new_pixel * alpha + pixel * (1 - alpha), where alpha is a number between 0 and 1 that describes the opacity of the new (foreground) pixel.
You'll note that if the new pixel is fully transparent (alpha = 0) the pixel is unchanged and that if the new pixel is fully opaque (alpha = 1) the new pixel replaces the old one.
This formula must be applied separately for each pixel components (red, green and blue).
the code needs to change to 24 bit pixels.
where the 4th byte is the transparency factor.
The actual color values do not change

Resources