HTMLgenerator/ColGen/func.cs

758 lines
22 KiB
C#

/**
This is tutorial code that goes with the article http://devmag.org.za/2012/07/29/how-to-choose-colours-procedurally-algorithms/.
*/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using Christo.GFX.Conversion;
namespace ProceduralPalette
{
public static class RandomExtensions
{
public static int NextByte(this Random random)
{
return ProceduralPalette.FloatToByte(random.NextDouble());
}
public static float NextFloat(this Random random)
{
return (float) random.NextDouble();
}
}
class ProceduralPalette
{
private static Random random = new Random();
public static List<Color> GenerateColors_Uniform(int colorCount)
{
List<Color> colors = new List<Color>();
for (int i = 0; i < colorCount; i++)
{
Color newColor = Color.FromArgb(
255,
random.NextByte(),
random.NextByte(),
random.NextByte());
colors.Add(newColor);
}
return colors;
}
public static List<Color> GenerateColors_Harmony(
int colorCount,
float offsetAngle1,
float offsetAngle2,
float rangeAngle0,
float rangeAngle1,
float rangeAngle2,
float saturation, float luminance)
{
List<Color> colors = new List<Color>();
float referenceAngle = random.NextFloat() * 360;
for (int i = 0; i < colorCount; i++)
{
float randomAngle = random.NextFloat() * (rangeAngle0 + rangeAngle1 + rangeAngle2);
if (randomAngle > rangeAngle0)
{
if (randomAngle < rangeAngle0 + rangeAngle1)
{
randomAngle += offsetAngle1;
}
else
{
randomAngle += offsetAngle2;
}
}
HSL hslColor = new HSL(((referenceAngle + randomAngle) / 360.0f) % 1.0f, saturation, luminance);
colors.Add(hslColor.Color);
}
return colors;
}
public static List<Color> GenerateColors_Harmony2(
int colorCount,
float offsetAngle1,
float offsetAngle2,
float rangeAngle0,
float rangeAngle1,
float rangeAngle2,
float saturation, float saturationRange,
float luminance, float luminanceRange)
{
List<Color> colors = new List<Color>();
float referenceAngle = random.NextFloat() * 360;
for (int i = 0; i < colorCount; i++)
{
float randomAngle = random.NextFloat() * (rangeAngle0 + rangeAngle1 + rangeAngle2);
if (randomAngle > rangeAngle0)
{
if (randomAngle < rangeAngle0 + rangeAngle1)
{
randomAngle += offsetAngle1;
}
else
{
randomAngle += offsetAngle2;
}
}
float newSaturation = saturation + (random.NextFloat() - 0.5f) * saturationRange;
float newLuminance = luminance + +(random.NextFloat() - 0.5f) * luminanceRange;
HSL hslColor = new HSL(((referenceAngle + randomAngle) / 360.0f) % 1.0f, newSaturation, newLuminance);
colors.Add(hslColor.Color);
}
return colors;
}
public static List<Color> GenerateColors_RandomWalk(int colorCount, Color startColor, float min, float max)
{
List<Color> colors = new List<Color>();
Color newColor = startColor;
float range = max - min;
for (int i = 0; i < colorCount; i++)
{
int rSign = random.Next(2) % 2 == 0 ? 1 : -1;
int gSign = random.Next(2) % 2 == 0 ? 1 : -1;
int bSign = random.Next(2) % 2 == 0 ? 1 : -1;
newColor = Color.FromArgb(
255,
FloatToByte(ByteToFloat(newColor.R) + rSign * (min + random.NextDouble() * range)),
FloatToByte(ByteToFloat(newColor.G) + rSign * (min + random.NextDouble() * range)),
FloatToByte(ByteToFloat(newColor.B) + rSign * (min + random.NextDouble() * range)));
colors.Add(newColor);
}
return colors;
}
public static List<Color> GenerateColors_RandomMix(int colorCount, Color color1, Color color2, Color color3, float greyControl, bool paint)
{
List<Color> colors = new List<Color>();
for (int i = 0; i < colorCount; i++)
{
Color newColor;
if (paint)
{
newColor = RandomMixHSL(color1, color2, color3, greyControl);
}
else
{
newColor = RandomMix(color1, color2, color3, greyControl);
}
colors.Add(newColor);
}
return colors;
}
public static List<Color> GenerateColors_RandomAdd(int colorCount, Color color1, Color color2, Color color3, float nonGrayBias)
{
List<Color> colors = new List<Color>();
for (int i = 0; i < colorCount; i++)
{
Color newColor = RandomAdd(color1, color2, color3, nonGrayBias);
colors.Add(newColor);
}
return colors;
}
public static List<Color> GenerateColors_Offset(int colorCount, Color color, float maxRange)
{
List<Color> colors = new List<Color>();
for (int i = 0; i < colorCount; i++)
{
Color newColor = Color.FromArgb(
255,
FloatToByte((ByteToFloat(color.R) + random.NextDouble() * 2 * maxRange - maxRange)),
FloatToByte((ByteToFloat(color.G) + random.NextDouble() * 2 * maxRange - maxRange)),
FloatToByte((ByteToFloat(color.B) + random.NextDouble() * 2 * maxRange - maxRange)));
colors.Add(newColor);
}
return colors;
}
public static List<Color> GenerateColors_Hue(int colorCount, float saturation, float luminance)
{
List<Color> colors = new List<Color>();
for (int i = 0; i < colorCount; i++)
{
HSL hslColor = new HSL(random.NextDouble(), saturation, luminance);
colors.Add(hslColor.Color);
}
return colors;
}
public static List<Color> GenerateColors_Saturation(int colorCount, float hue, float luminance)
{
List<Color> colors = new List<Color>();
for (int i = 0; i < colorCount; i++)
{
HSL hslColor = new HSL(hue, random.NextDouble(), luminance);
colors.Add(hslColor.Color);
}
return colors;
}
public static List<Color> GenerateColors_Luminance(int colorCount, float hue, float saturation)
{
List<Color> colors = new List<Color>();
for (int i = 0; i < colorCount; i++)
{
HSL hslColor = new HSL(hue, saturation, random.NextDouble());
colors.Add(hslColor.Color);
}
return colors;
}
public static List<Color> GenerateColors_SaturationLuminance(int colorCount, float hue)
{
List<Color> colors = new List<Color>();
for (int i = 0; i < colorCount; i++)
{
HSL hslColor = new HSL(hue, random.NextDouble(), random.NextDouble());
colors.Add(hslColor.Color);
}
return colors;
}
public static List<Color> GenerateColors_GoldenRatioRainbow(int colorCount, float saturation, float luminance)
{
List<Color> colors = new List<Color>();
float goldenRatioConjugate = 0.618033988749895f;
float currentHue = (float) random.NextDouble();
for (int i = 0; i < colorCount; i++)
{
HSL hslColor = new HSL(currentHue, saturation, luminance);
colors.Add(hslColor.Color);
currentHue += goldenRatioConjugate;
currentHue %= 1.0f;
}
return colors;
}
public static List<Color> GenerateColors_GoldenRatioGradient(int colorCount, Color[] gradient, float saturation, float luminance)
{
List<Color> colors = new List<Color>();
float goldenRatioConjugate = 0.618033988749895f;
float currentHue = (float)random.NextDouble();
for (int i = 0; i < colorCount; i++)
{
HSL hslColor = new HSL(currentHue, saturation, luminance);
Color newColor = SampleLinearGradient(gradient, currentHue);
colors.Add(newColor);
currentHue += goldenRatioConjugate;
currentHue %= 1.0f;
}
return colors;
}
public static List<Color> GenerateColors_HueRange(int colorCount, float startHue, float endHue, float saturation, float luminance)
{
List<Color> colors = new List<Color>();
float hueRange = endHue - startHue;
if(hueRange < 0)
{
hueRange += 1.0f;
}
for (int i = 0; i < colorCount; i++)
{
float newHue = (float) (hueRange * random.NextDouble() + startHue);
if(newHue > 1.0)
{
newHue -= 1.0f;
}
HSL hslColor = new HSL(newHue, saturation, luminance);
colors.Add(hslColor.Color);
}
return colors;
}
public static List<Color> GenerateColors_JitteredRainbow(int colorCount, float startHue, float endHue, float saturation, float luminance, bool jitter)
{
List<Color> colors = new List<Color>();
float hueRange = endHue - startHue;
if (hueRange < 0)
{
hueRange = 1 + hueRange;
}
float cellRange = hueRange / colorCount;
float cellOffset = (float) (random.NextDouble() * cellRange);
for (int i = 0; i < colorCount; i++)
{
float newHue;
if (jitter)
{
newHue = (float)(cellRange * i + random.NextDouble() * cellRange + startHue);
}
else
{
newHue = (cellRange * i + cellOffset + startHue);
}
if(newHue > 1)
{
newHue -= 1.0f;
}
HSL hslColor = new HSL(newHue, saturation, luminance);
colors.Add(hslColor.Color);
}
return colors;
}
public static int FloatToByte(double value)
{
int byteValue = (int)(value * 256);
byteValue = SaturateByte(byteValue);
return byteValue;
}
private static int SaturateByte(int byteValue)
{
if (byteValue > 255)
{
byteValue = 255;
}
else if (byteValue < 0)
{
byteValue = 0;
}
return byteValue;
}
public static float ByteToFloat(int byteValue)
{
float floatValue = byteValue / 256.0f;
return floatValue;
}
public static Color RandomMix(Color color1, Color color2, Color color3, float greyControl)
{
int randomIndex = random.NextByte() % 3;
float mixRatio1 = (randomIndex == 0) ? random.NextFloat() * greyControl : random.NextFloat();
float mixRatio2 = (randomIndex == 1) ? random.NextFloat() * greyControl : random.NextFloat();
float mixRatio3 = (randomIndex == 2) ? random.NextFloat() * greyControl : random.NextFloat();
float sum = mixRatio1 + mixRatio2 + mixRatio3;
mixRatio1 /= sum;
mixRatio2 /= sum;
mixRatio3 /= sum;
return Color.FromArgb(
255,
(byte)(mixRatio1 * color1.R + mixRatio2 * color2.R + mixRatio3 * color3.R),
(byte)(mixRatio1 * color1.G + mixRatio2 * color2.G + mixRatio3 * color3.G),
(byte)(mixRatio1 * color1.B + mixRatio2 * color2.B + mixRatio3 * color3.B));
}
public static Color RandomMixHSL(Color color1, Color color2, Color color3, float greyControl)
{
int randomIndex = random.NextByte() % 3;
float mixRatio1 = (randomIndex == 0) ? random.NextFloat() * greyControl : random.NextFloat();
float mixRatio2 = (randomIndex == 1) ? random.NextFloat() * greyControl : random.NextFloat();
float mixRatio3 = (randomIndex == 2) ? random.NextFloat() * greyControl : random.NextFloat();
float sum = mixRatio1 + mixRatio2 + mixRatio3;
mixRatio1 /= sum;
mixRatio2 /= sum;
mixRatio3 /= sum;
HSL hsl1 = new HSL(color1);
HSL hsl2 = new HSL(color2);
HSL hsl3 = new HSL(color3);
return new HSL(
(mixRatio1 * hsl1.H + mixRatio2 * hsl2.H + mixRatio3 * hsl3.H),
(mixRatio1 * hsl1.S + mixRatio2 * hsl2.S + mixRatio3 * hsl3.S),
(mixRatio1 * hsl1.L + mixRatio2 * hsl2.L + mixRatio3 * hsl3.L)).Color;
}
public static Color RandomMixPaint(Color color1, Color color2, Color color3, float greyControl)
{
int randomIndex = random.NextByte() % 3;
float mixRatio1 = (randomIndex == 0) ? random.NextFloat() * greyControl : random.NextFloat();
float mixRatio2 = (randomIndex == 1) ? random.NextFloat() * greyControl : random.NextFloat();
float mixRatio3 = (randomIndex == 2) ? random.NextFloat() * greyControl : random.NextFloat();
float sum = mixRatio1 + mixRatio2 + mixRatio3;
mixRatio1 /= sum;
mixRatio2 /= sum;
mixRatio3 /= sum;
return Color.FromArgb(
255,
255 - (byte)(mixRatio1 * (255 - color1.R) + mixRatio2 * (255 - color2.R) + mixRatio3 * (255 - color3.R)),
255 - (byte)(mixRatio1 * (255 - color1.G) + mixRatio2 * (255 - color2.G) + mixRatio3 * (255 - color3.G)),
255 - (byte)(mixRatio1 * (255 - color1.B) + mixRatio2 * (255 - color2.B) + mixRatio3 * (255 - color3.B)));
}
public static Color RandomAdd(Color color1, Color color2, Color color3, float nonGrayBias)
{
int rIndex = random.NextByte() % 3;
float r1 = (rIndex == 0) ? random.NextFloat() * nonGrayBias : random.NextFloat();
float r2 = (rIndex == 1) ? random.NextFloat() * nonGrayBias : random.NextFloat();
float r3 = (rIndex == 2) ? random.NextFloat() * nonGrayBias : random.NextFloat();
float p = 20;
float sum = (float) Math.Pow(
Math.Pow(r1, p) +
Math.Pow(r2, p) +
Math.Pow(r3, p), 1 / p);
r1 /= sum;
r2 /= sum;
r3 /= sum;
return Color.FromArgb(
255,
SaturateToByte(r1 * color1.R + r2 * color2.R + r3 * color3.R),
SaturateToByte(r1 * color1.G + r2 * color2.G + r3 * color3.G),
SaturateToByte(r1 * color1.B + r2 * color2.B + r3 * color3.B));
}
public static int SaturateToByte(float floatValue)
{
int intValue = (int)floatValue;
if (intValue > 255)
{
intValue = 255;
}
else if( intValue < 0)
{
intValue = 0;
}
return intValue;
}
public static Color SampleLinearGradient(Color [] colors, float t)
{
int colorCount = colors.Length;
int leftIndex = (int) (t * colorCount);
float cellRange = 1.0f / colorCount;
float alpha = (t - leftIndex * cellRange) / cellRange;
Color leftColor = colors[leftIndex];
Color rightColor = colors[(leftIndex + 1) % colorCount];
return Color.FromArgb(
255,
(byte) (leftColor.R * (1 - alpha) + rightColor.R * (alpha)),
(byte) (leftColor.G * (1 - alpha) + rightColor.G * (alpha)),
(byte) (leftColor.B * (1 - alpha) + rightColor.B * (alpha)));
}
public static Bitmap GeneratePaletteImage(List<Color> colors, int width, int height, int spacing)
{
Bitmap image = new Bitmap(width, height);
int colorCount = colors.Count;
int blockWidth = (width - ((colorCount - 1) * spacing)) / colorCount;
for (int i = 0; i < colorCount; i++)
{
DrawBlock(image, i * (blockWidth + spacing), 0, blockWidth, height, colors[i]);
}
return image;
}
public static void DrawBlock(Bitmap image, int x, int y, int width, int height, Color color)
{
for (int i = x; i < x + width; i++)
{
for (int j = y; j < y + height; j++)
{
image.SetPixel(i, j, color);
}
}
}
//static void Main(string[] args)
//{
// //random = new Random(15);//15
// random = new Random(12);//15
// List<Color> colors;
// int versionCount = 3;
// int colorCount = 20;
// int imageWidth = 680;
// int imageHeight = 100;
// int spacing = 2;
// Color[] baseColors = {
// Color.FromArgb(255, 128, 0),
// Color.FromArgb(128, 255, 64),
// Color.FromArgb(64, 128, 255)};
// float[] saturation = {1.0f, 0.7f, 0.3f};
// float[] luminance = {0.45f, 0.7f, 0.4f};
// float[] hueStart = {0.9f, 0.2f, 0.6f };
// float[] hueEnd = { 0.1f, 0.5f, 0.9f };
// Color[] mixColor1 =
// {
// Color.FromArgb(255, 0, 33),
// Color.FromArgb(255, 100, 33),
// Color.FromArgb(128, 0, 33),
// };
// Color[] mixColor2 =
// {
// Color.FromArgb(255, 255, 0),
// Color.FromArgb(255, 255, 100),
// Color.FromArgb(255, 128, 0),
// };
// Color[] mixColor3 =
// {
// Color.FromArgb(0, 100, 255),
// Color.FromArgb(100, 150, 255),
// Color.FromArgb(0, 80, 128),
// };
// Color[] addColor1 =
// {
// Color.FromArgb(150, 0, 0),
// Color.FromArgb(200, 20, 0),
// Color.FromArgb(128, 0, 33),
// };
// Color[] addColor2 =
// {
// Color.FromArgb(0, 150, 0),
// Color.FromArgb(200, 200, 20),
// Color.FromArgb(255, 128, 0),
// };
// Color[] addColor3 =
// {
// Color.FromArgb(0, 0, 150),
// Color.FromArgb(20, 20, 200),
// Color.FromArgb(0, 80, 128),
// };
// Color[][] gradients =
// {
// new Color[]
// {
// Color.FromArgb(255, 0, 128),
// Color.FromArgb(255, 255, 0),
// Color.FromArgb(0, 255, 255),
// },
// new Color[]
// {
// Color.FromArgb(200, 0, 33),
// Color.FromArgb(255, 200, 0),
// Color.FromArgb(0, 100, 200),
// },
// new Color[]
// {
// Color.FromArgb(255, 0, 33),
// Color.FromArgb(255, 255, 0),
// Color.FromArgb(0, 255, 0),
// Color.FromArgb(255, 255, 0),
// }
// };
// float[] offsetAngles1 =
// {
// 15, 180, 120
// };
// float[] offsetAngles2 =
// {
// 30, 0, 240
// };
// float[] angleRanges1 =
// {
// 15, 40f, 40
// };
// float[] angleRanges2 =
// {
// 15, 40f, 40
// };
// float[] angleRanges3 =
// {
// 15, 0, 40
// };
// for (int version = 0; version < versionCount; version++)
// {
// colors = GenerateColors_Uniform(colorCount);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Uniform_5_" + version + ".png");
// colors = GenerateColors_RandomWalk(colorCount, baseColors[version], 0.2f, 0.4f);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("RandomWalk_5_" + version + ".png");
// colors = GenerateColors_RandomMix(colorCount, mixColor1[version], mixColor2[version], mixColor3[version], 0.1f, true);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("MixPaint1_5_" + version + ".png");
// colors = GenerateColors_RandomMix(colorCount, mixColor1[version], mixColor2[version], mixColor3[version], 0.5f, true);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("MixPaint5_5_" + version + ".png");
// colors = GenerateColors_RandomMix(colorCount, mixColor1[version], mixColor2[version], mixColor3[version], 0.9f, true);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("MixPaint9_5_" + version + ".png");
// colors = GenerateColors_RandomMix(colorCount, mixColor1[version], mixColor2[version], mixColor3[version], 0.1f, false);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Mix1_5_" + version + ".png");
// colors = GenerateColors_RandomMix(colorCount, mixColor1[version], mixColor2[version], mixColor3[version], 0.5f, false);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Mix5_5_" + version + ".png");
// colors = GenerateColors_RandomMix(colorCount, mixColor1[version], mixColor2[version], mixColor3[version], 0.9f, false);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Mix9_5_" + version + ".png");
// colors = GenerateColors_RandomAdd(colorCount, addColor1[version], addColor2[version], addColor3[version], 0.1f);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Add1_5_" + version + ".png");
// colors = GenerateColors_RandomAdd(colorCount, addColor1[version], addColor2[version], addColor3[version], 0.5f);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Add5_5_" + version + ".png");
// colors = GenerateColors_RandomAdd(colorCount, addColor1[version], addColor2[version], addColor3[version], 0.9f);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Add9_5_" + version + ".png");
// colors = GenerateColors_Offset(colorCount, baseColors[version], 0.4f);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Offset_5_" + version + ".png");
// colors = GenerateColors_Hue(colorCount, saturation[version], luminance[version]);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Hue_5_" + version + ".png");
// colors = GenerateColors_Saturation(colorCount, hueStart[version], luminance[version]);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Saturation_5_" + version + ".png");
// colors = GenerateColors_Luminance(colorCount, hueStart[version], saturation[version]);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Luminance_5_" + version + ".png");
// colors = GenerateColors_SaturationLuminance(colorCount, hueStart[version]);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Saturation_Luminance_5_" + version + ".png");
// colors = GenerateColors_GoldenRatioRainbow(colorCount, saturation[version], luminance[version]);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("GoldenRatioRainbow_5_" + version + ".png");
// colors = GenerateColors_GoldenRatioGradient(colorCount, gradients[version], saturation[version], luminance[version]);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("GoldenRatioGradient_5_" + version + ".png");
// colors = GenerateColors_JitteredRainbow(colorCount, 0, 1, saturation[version], luminance[version], true);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("JitteredRainbow_5_" + version + ".png");
// colors = GenerateColors_JitteredRainbow(colorCount, hueStart[version], hueEnd[version], saturation[version], luminance[version], true);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("JitteredRainbowRange_5_" + version + ".png");
// colors = GenerateColors_JitteredRainbow(colorCount, 0, 1, saturation[version], luminance[version], false);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Grid_Rainbow_5_" + version + ".png");
// colors = GenerateColors_HueRange(colorCount, hueStart[version], hueEnd[version], saturation[version], luminance[version]);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("HueRange_5_" + version + ".png");
// colors = GenerateColors_Harmony(colorCount,
// offsetAngles1[version], offsetAngles2[version],
// angleRanges1[version], angleRanges2[version], angleRanges3[version],
// saturation[version], luminance[version]);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Harmony_5_" + version + ".png");
// colors = GenerateColors_Harmony2(colorCount,
// offsetAngles1[version], offsetAngles2[version],
// angleRanges1[version], angleRanges2[version], angleRanges3[version],
// saturation[version], 0.2f,
// luminance[version], 0.5f);
// GeneratePaletteImage(colors, imageWidth, imageHeight, spacing).Save("Harmony2_5_" + version + ".png");
// }
//}
}
}