I was trying to change the color of my button through scripting. I'm facing a weird problem.
if I write
button1.color = new Color(255, 0, 0);
It colors the button correctly. But if I change the color something like:
button1.color = new Color(237, 85, 59);
this, then it turns to ash or no color.
I'm new in unity and don't know where is the actual problem.
The Color constructor takes in 4 values: red, green, blue and alpha. The values are between 0.0f and 1.0f, instead of
button1.color = new Color(237, 85, 59);
write something like
button1.color = new Color(0.93f, 0.33f, 0.23f, 1.0f)
The way to get the 0.0 - 1.1 values from the RGB 0 - 255 values is by dividing the color values by 255. Hope this answered your question.
Is it possible(Without looping through all texturecoordinates) to set them as 0 as default?
I am creating a linear gradient ImageBrush
var colorBitmap = GetColorsBitmap(gradient.ToList()); // Create Colors from gray to my selected color
ImageBrush ib = new ImageBrush(colorBitmap)
{
ViewportUnits = BrushMappingMode.Absolute,
Viewport = new Rect(0, 0, 1, 1) // Matches the pixels in the bitmap.
};
myModel.Material = new DiffuseMaterial(ib);
Then depending on a condition I customize some of the Texturecoordinates like this, where colorvalue is the distance from an object:
var mesh = (MeshGeometry3D) myModel.Geometry;
//In a loop, depending on the distance I set a colorValue
mesh.TextureCoordinates[count] = new Point(colorValue, 0);
I want every texturecoordinate to default to a Point(0,0) but if I have to loop through all 1.2 million of them takes too much time. So is there a way to setup my ImageBrush so that they default to 0,0 or something similiar?
I have this method that picks a random color from a preset array of colors.
public Color GetRandomColor()
{
return colors[rand.Next(0, colors.Length)];
}
Then I use it in this method in another class
public void RandomizeColors()
{
for(int i = 0; i< spriteRenderers.Length; i++)
{
spriteRenderers[i].color = rColors.GetRandomColor();
}
}
The problem is that the colors of the sprite renderers all get set to some strange values. The RGB gets set to something in the thousands.
if I use spriteRenderers[i].color = Color.black for example it works fine.
I have checked the return values of GetRandomColor() and they are all correct. Where am I doing this wrong ?
Edit:
The array of colors. This is part of a constructor:
colors = new Color[7];
colors[0] = new Color(87f,72f,161f) ;
colors[1] = new Color(39f,145f,221f);
colors[2] = new Color(233f,191f,57f);
colors[3] = new Color(238f,133f,57f);
colors[4] = new Color(238f,71f,46f);
colors[5] = new Color(193f,57f,235f);
colors[6] = new Color(104f,176f,58f);
Unity Documentation says you need to have the r, g and b arguments in the range of 0f to 1f. So you can basically divide your r, g and b by 256.
Directly extracted from the Unity Scripting API:
Color
struct in UnityEngine
Description
Representation of RGBA colors.
This structure is used throughout Unity to pass colors around. Each color component is a floating point value with a range from 0 to 1.
Here is the Link to the Documentation:
Unity Scripting API
As a follow up to this question: (How can I draw legible text on a bitmap (Winforms)?), I'm drawing legible but small text on top of a bitmap by calculating the "average" color beneath the text, and choosing an appropriately contrasting color for the text.
I've stolen Till's code from https://stackoverflow.com/a/6185448/3784949 for calculating "average" bmp color. Now I'm looking at the "color difference" algorithm suggested by http://www.w3.org/TR/AERT#color-contrast.
This suggests that I need to make my color brightness at least 125 "units" greater, and my color difference at least 500 units greater, where brightness and difference are calculated like this:
Color brightness is determined by the following formula:
((Red value X 299) + (Green value X 587) + (Blue value X 114)) / 1000
Color difference is determined by the following formula:
(maximum (Red value 1, Red value 2) - minimum (Red value 1, Red value 2)) + (maximum (Green value 1, Green value 2) - minimum (Green value 1, Green value 2)) + (maximum (Blue value 1, Blue value 2) - minimum (Blue value 1, Blue value 2))
How do I implement this? I can set my color by ARGB (I believe, it's a label foreground color); but how do I calculate how much to change each individual value to achieve the difference being required here? I'm not familiar with the math required to break the "difference" units down into their component parts.
As an example, my "average" for one bitmap is: Color [A=255, R=152, G=138, B=129]. How do I "add" enough to each part to achieve the two differences?
EDIT: To be specific, my confusion lies here:
it looks like I need to add to three separate values (R,G,B) to achieve two different goals (new RGB adds up to original plus 125, new RGB adds up to original plus 500
it looks like I may need to "weight" my added brighness values to add more to G than R than B.
I have no idea how to address #1. And I'm not positive I'm correct about #2.
EDIT: Proposed solution
I'm currently experimenting with this:
private Color GetContrastingFontColor(Color AverageColorOfBitmap,
List<Color> FavoriteColors)
{
IEnumerable<Color> AcceptableColors =
(IEnumerable<Color>)FavoriteColors.Where(clr =>
(GetColorDifferenceAboveTarget(AverageColorOfBitmap, clr, (float)200) > 0)
&& (GetBrightnessAboveTarget(AverageColorOfBitmap, clr, (float).125) > 0))
.OrderBy(clr => GetColorDifferenceAboveTarget(
AverageColorOfBitmap, clr, (float)200));
return AcceptableColors.DefaultIfEmpty(Color.Aqua).First();
}
It's a good framework, but I need to work on selecting the "best" candidate from the list. Right now it's just returning "the qualifying color with the greatest color difference that meets the brightness criteria". However, this allows me to modify the float values (W3's "500 color difference required" is complete crap, zero KnownColors qualify) and experiment.
Support code:
private float GetBrightnessAboveTarget(Color AverageColorOfBitmap,
Color proposed, float desiredDifference)
{
float result = proposed.GetBrightness() - AverageColorOfBitmap.GetBrightness();
return result - desiredDifference;
}
private float GetColorDifferenceAboveTarget(Color avg, Color proposed,
float desiredDifference)
{
float r1 = Convert.ToSingle(MaxByte(Color.Red, avg, proposed));
float r2 = Convert.ToSingle(MinByte(Color.Red, avg, proposed));
float r3 = Convert.ToSingle(MaxByte(Color.Green, avg, proposed));
float r4 = Convert.ToSingle(MinByte(Color.Green, avg, proposed));
float r5 = Convert.ToSingle(MaxByte(Color.Blue, avg, proposed));
float r6 = Convert.ToSingle(MinByte(Color.Blue, avg, proposed));
float result = (r1 - r2) + (r3 - r4) + (r5 - r6);
return result - desiredDifference;
}
private byte MaxByte(Color rgb, Color x, Color y)
{
if (rgb == Color.Red) return (x.R >= y.R) ? x.R : y.R;
if (rgb == Color.Green) return (x.G >= y.G) ? x.G : y.G;
if (rgb == Color.Blue) return (x.B >= y.B) ? x.B : y.B;
return byte.MinValue;
}
private byte MinByte(Color rgb, Color x, Color y)
{
if (rgb == Color.Red) return (x.R <= y.R) ? x.R : y.R;
if (rgb == Color.Green) return (x.G <= y.G) ? x.G : y.G;
if (rgb == Color.Blue) return (x.B <= y.B) ? x.B : y.B;
return byte.MinValue;
}
This is more an answer to the original question. I call it a homemeade outline.
Using transparency plus the maximum and minimum brightness you can get (white&black) it creates good contrast, at least it looks pretty good on my screen.
It is a mixture of shadowing and transparency. I have subtracted a little from the red component to get the aqua you thought about..
It is creating first a darker version of the background by printing the text 1 pixel up left and the 1 pixel down right. Finally it prints a bright version on top of that. Note that it is not really using black and white because with its semi-transparent pixels the hue really it that of each background pixel.
For an actual printout you will have to experiment, especially with the font but also with the two transparencies!
Also you should maybe switch between white on a black shadow and black on a white highlight, depending on the brightness of the spot you print on. But with this homemeade outline it really will work on both dark and bright backgrounds, it'll just look a little less elegant on a bright background.
using (Graphics G = Graphics.FromImage(pictureBox1.Image) )
{
Font F = new Font("Arial", 8);
SolidBrush brush0 = new SolidBrush(Color.FromArgb(150, 0, 0, 0))
SolidBrush brush1 = new SolidBrush(Color.FromArgb(200, 255, 255, 222))
G.DrawString(textBox1.Text, F, brush0 , new Point(x-1, y-1));
G.DrawString(textBox1.Text, F, brush0 , new Point(x+1, y+1));
G.DrawString(textBox1.Text, F, brush1, new Point(x, y));
}
Edit: This is called from a button click but really should be in the paint event.
There the Graphics object and its using block G would be replaced by simply the e.Graphics event parameter..
I noticed that you are using a 'transparent' label to display the data to avoid the details of Graphics.DrawString and the Paint event.
Well that can be done and the result looks rather similar:
string theText ="123 - The quick brown fox..";
Label L1, L2, L3;
pictureBox1.Controls.Add(new trLabel());
L1 = (trLabel)pictureBox1.Controls[pictureBox1.Controls.Count - 1];
L1.Text = theText;
L1.ForeColor = Color.FromArgb(150, 0, 0, 0);
L1.Location = new Point(231, 31); // <- position in the image, change!
L1.Controls.Add(new trLabel());
L2 = (trLabel)L1.Controls[pictureBox1.Controls.Count - 1];
L2.Text = theText;
L2.ForeColor = Color.FromArgb(150, 0, 0, 0);
L2.Location = new Point(2, 2); // do not change relative postion in the 1st label!
L2.Controls.Add(new trLabel());
L3 = (trLabel)L2.Controls[pictureBox1.Controls.Count - 1];
L3.Text = theText;
L3.ForeColor = Color.FromArgb(200, 255, 255, 234);
L3.Location = new Point(-1,-1); // do not change relative postion in the 2nd label!
However you will note that due to the impossiblity of having really transparent controls in Winforms we need a little extra effort. You probably use a label subclass like this:
public partial class trLabel : Label
{
public trLabel()
{
SetStyle(ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
BackColor = Color.Transparent;
Visible = true;
AutoSize = true;
}
}
This seems to work. But in reality it only seems that way, because upon creation each label gets a copy of its current background from its parent. Which never gets updated. Which is why I have to add the 2nd & 3rd label not to the picturebox I display the image in, but to the 1st and 2nd
'transparent' label respectively.
There simply is not real transparency between Winforms controls unless you draw things yourself.
So the DrawString solution is not really complicated. And it gives you the bonus of allowing you to twist several properties of the Graphics object like Smoothingmode, TextContrast or InterpolationMode
Short suggestion: Just use black or white.
The algorithms are giving you a passing criteria, but not an algorithm for determining what colors meet that criteria. So, you will have to create such an algorithm. A naive algorithm would be to loop through every possible color, and calculate the color difference, then see if the difference is greater than 125, and if so you have a good color to use. Better, you could search for the color with the maximum difference.
But that's foolish - if I gave you the color R=152, G=138, B=129 - what do YOU think is a very good color to contrast that with? Just by gut, I'm gonna guess 0,0,0. I picked a color with the farthest possible R value, G value, and B value. If you gave me the color 50,200,75 I'd pick R=255, G=0, B=255. Same logic. So my algorithm is if R<128 choose R = 255, else choose R = 0. Same thing for G, and B.
Now that algorithm only picks RGB values that are 0 or 255. But if you don't like that, now you need a mathematical definition for what is "pretty" and I'll leave you to figure that out on your own. :-)
How do I set every non transparent pixel in an arbitrary Texture2D to let's say Color.White temporarily?
Just a conditional loop? This won't be exact syntax for it, but something among the lines of:
Texture2D texture = /*copy the texture you want to change*/;
Pixel pixel;/*note it's really inexact, so don't mind it, the idea is to show how it would be done*/
for(int i=0; i<texture.width; i++)
{
for(int j=0; j<texture.height; j++)
{
pixel = texture.GetPixel(i, j);
if(pixel.Color.A==1)
pixel.Color = Color.White;
}
}
I cannot stress this enough: do NOT just copy paste this in, this is similar to pseudocode, just there to show how it would be done.
Haven't tested this, but out of my head, you could do something like this:
Color[] az = Enumerable.Range(0, 100).Select(i => Color.White).ToArray();
Texture2D texture = new Texture2D(GameRef.GraphicsDevice, 10, 10, false, SurfaceFormat.Color);
texture.SetData(az);
This first creates an array with 100 elements, and fills it with Color.White
Then using the SetData, we fill it with the colorarray.
Just make sure the array is the same size as the texture size (height*width)