/// <summary> /// Subtracts another ARGB instance. /// </summary> /// <param name="other">The other instance.</param> public void Substract(ARGB other) { Alpha = (byte)Math.Max(0, Alpha - other.Alpha); Red = (byte)Math.Max(0, Red - other.Red); Green = (byte)Math.Max(0, Green - other.Green); Blue = (byte)Math.Max(0, Blue - other.Blue); }
/// <summary> /// Creates a new bitmap instance /// </summary> /// <param name="fontName">Name of the font</param> /// <param name="fontSize">Size in points</param> /// <param name="foreColor">ForeColor</param> /// <param name="backColor">BackColor</param> /// <param name="text">text to draw</param> public Bitmap32 Create(string fontName, float fontSize, ARGB foreColor, ARGB backColor, string text) { SizeF size; using (var b = new Bitmap(1, 1)) { float emSize = fontSize / 4f * 3f; var font = fontName == null ? new Font(FontFamily.GenericSansSerif, fontSize, GraphicsUnit.Point) : new Font(fontName, fontSize, GraphicsUnit.Point); using (font) { using (var g = Graphics.FromImage(b)) { size = g.MeasureString(text, font); } var result = new Bitmap((int)size.Width + 1, (int)size.Height + 1, PixelFormat.Format32bppArgb); using (var g = Graphics.FromImage(result)) { g.TextRenderingHint = TextRenderingHint.AntiAlias; g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.CompositingMode = CompositingMode.SourceOver; g.CompositingQuality = CompositingQuality.HighQuality; g.SmoothingMode = SmoothingMode.HighQuality; g.Clear(backColor); g.DrawString(text, font, new SolidBrush(foreColor), 0, 0); } return(new GdiBitmap32(result)); } } }
/// <summary>Adds values of the specified other instance.</summary> /// <param name="other">The other instance.</param> public void Add(ARGB other) { Alpha = (byte)Math.Min(255, Alpha + other.Alpha); Red = (byte)Math.Min(255, Red + other.Red); Green = (byte)Math.Min(255, Green + other.Green); Blue = (byte)Math.Min(255, Blue + other.Blue); }
/// <summary>Gets the RGB distance.</summary> /// <param name="other">The other.</param> /// <returns>distance as <see cref="float"/>.</returns> public float GetDistance(ARGB other) { float r = (Red - other.Red) / 255f; float g = (Green - other.Green) / 255f; float b = (Blue - other.Blue) / 255f; return(Math.Min(1, Math.Max(-1, r * g * b))); }
/// <summary>Creates a bitmap instance from the specified data.</summary> public static Bitmap32 Create(string fontName, float fontSize, ARGB foreColor, ARGB backColor, string text) { if (Loader == null) { throw new Exception("No valid IBitmap32Loader found!"); } return(Loader.Create(fontName, fontSize, foreColor, backColor, text)); }
/// <summary> /// Loads (copies) the struct from a color. /// </summary> /// <param name="color">color value.</param> /// <returns>new argb color.</returns> public static ARGB FromColor(Color color) { var result = new ARGB { AsInt32 = color.ToArgb(), }; return(result); }
/// <summary> /// Loads (copies) the struct from a specified value. /// </summary> /// <param name="value">color value.</param> /// <returns>new argb color.</returns> public static ARGB FromValue(int value) { var result = new ARGB { AsInt32 = value, }; return(result); }
/// <summary> /// Retrieves a ARGB struct for the specified index. /// </summary> public ARGB this[int x, int y] { get { return(ARGB.FromValue(Data[PositionToIndex(x, y)])); } set { Data[PositionToIndex(x, y)] = value.AsInt32; } }
/// <summary> /// Retrieves a ARGB struct for the specified index. /// </summary> public ARGB this[int index] { get { return(ARGB.FromValue(Data[index])); } set { Data[index] = value.AsInt32; } }
/// <summary> /// Retrieves a ARGB struct for the specified index. /// </summary> public ARGB this[int X, int Y] { get { return(ARGB.FromValue(Data[PositionToIndex(X, Y)])); } set { Data[PositionToIndex(X, Y)] = value.AsInt32; } }
/// <summary>Detects the most common colors.</summary> /// <param name="max">The maximum number of colors to retrieve.</param> /// <returns>Returns an array of <see cref="T:Cave.Media.ARGB" /> values.</returns> public IList <ARGB> DetectColors(int max) { if ((Width + Height) / 2 > max) { using (var bmp = Resize(max, max, ResizeMode.None)) { return(bmp.DetectColors(max)); } } var colorCounters = new List <ColorCounter>(); for (int y = 0; y < Height; y++) { var data = Data.Data; var colorDict = new Dictionary <ARGB, ColorCounter>(); unsafe { fixed(int *p = &data[0]) { for (int i = 0; i < data.Length; i++) { ARGB color = p[i]; if (!colorDict.ContainsKey(color)) { colorDict.Add(color, new ColorCounter(color, 1)); } else { colorDict[color].Count++; } } } } colorCounters.AddRange(colorDict.Values); } uint distance = 255; while (colorCounters.Count > max) { colorCounters.Sort(); colorCounters = ColorCounter.Reduce(colorCounters, ref distance); distance += 255; } colorCounters.Sort(); var colors = new List <ARGB>(colorCounters.Count); for (int i = 0; i < colorCounters.Count; i++) { colors.Add(colorCounters[i].Color); } return(colors); }
/// <summary> /// Loads (copies) the struct from specified gray value. /// </summary> /// <param name="gray">gray color value.</param> /// <returns>new argb color.</returns> public static ARGB FromGrayScale(byte gray) { var result = new ARGB { Alpha = 255, Red = gray, Green = gray, Blue = gray, }; return(result); }
/// <summary> /// Subtracts two ARGB instances. /// </summary> /// <param name="v1">first color.</param> /// <param name="v2">second color.</param> /// <returns>difference of the colors.</returns> public static ARGB operator -(ARGB v1, ARGB v2) { var result = new ARGB { Alpha = (byte)Math.Max(0, v1.Alpha - v2.Alpha), Red = (byte)Math.Max(0, v1.Red - v2.Red), Green = (byte)Math.Max(0, v1.Green - v2.Green), Blue = (byte)Math.Max(0, v1.Blue - v2.Blue), }; return(result); }
/// <summary> /// Adds two ARGB instances. /// </summary> /// <param name="v1">first color.</param> /// <param name="v2">second color.</param> /// <returns>sum of the colors.</returns> public static ARGB operator +(ARGB v1, ARGB v2) { var result = new ARGB { Alpha = (byte)Math.Min(255, v1.Alpha + v2.Alpha), Red = (byte)Math.Min(255, v1.Red + v2.Red), Green = (byte)Math.Min(255, v1.Green + v2.Green), Blue = (byte)Math.Min(255, v1.Blue + v2.Blue), }; return(result); }
/// <summary> /// Loads (copies) the struct from specified alpha, red, green and blue values. /// </summary> /// <param name="alpha">Alpha.</param> /// <param name="red">Red.</param> /// <param name="green">Green.</param> /// <param name="blue">Blue.</param> /// <returns>new argb color struct.</returns> public static ARGB FromColor(byte alpha, byte red, byte green, byte blue) { var result = new ARGB { Alpha = alpha, Red = red, Green = green, Blue = blue, }; return(result); }
/// <summary> /// gets the contrast ratio ranging from 0 for no contrast to 1 for highest contrast. /// </summary> /// <param name="other">the other color.</param> /// <returns>contrast ratio of the two colors.</returns> /// <remarks> /// smaller than 0.143 -> fail, /// between 0.143 and 0.214 -> minimum, /// between 0.214 and 0.333 -> good, /// greater than 0.333 -> perfect. /// </remarks> public float GetContrastRatio(ARGB other) { float l1 = Brightness; float l2 = other.Brightness; if (l2 > l1) { float t = l1; l1 = l2; l2 = t; } return((l1 + 0.05f) / (l2 + 0.05f) / 21f); }
/// <summary> /// Loads (copies) the struct from a specified pointer. /// </summary> /// <param name="value">pointer with color data.</param> /// <returns>argb color.</returns> public static unsafe ARGB FromPointer(void *value) { if (value == null) { throw new ArgumentNullException("Value"); } var result = new ARGB { AsUInt32 = *((uint *)value), }; return(result); }
/// <summary> /// Returns a light color r,g,b = 0..127 for the specified index shaded with the specified number of steps. /// </summary> /// <param name="index">Index of the color.</param> /// <param name="steps">Steps to go from dark to light colors.</param> /// <returns>the light color.</returns> public static ARGB GetDarkColor(int index, int steps) { // 2 bits per color int r = 0; int b = 0; int g = 0; int v = index; while (v > 0) { r = (r << 1) | (v & 1); v >>= 1; g = (g << 1) | (v & 1); v >>= 1; b = (b << 1) | (v & 1); v >>= 1; } while (true) { if (r > steps) { g += r % steps; } if (g > steps) { b += g % steps; } if (b > steps) { r += b % steps; } else { break; } } var result = new ARGB { Alpha = 0xFF, RedFloat = (r % steps) / (3f * steps), GreenFloat = (g % steps) / (3f * steps), BlueFloat = (b % steps) / (3f * steps), }; return(result); }
/// <summary> /// Reduces the the colors of the image to the specified color count. /// </summary> /// <param name="colorCount">Number of colors to keep.</param> /// <returns>Returns the resulting color palette.</returns> public ARGB[] GetColors(uint colorCount) { var colorCounters = new List <ColorCounter>(); { var colorDict = new Dictionary <int, ColorCounter>(); for (var i = 0; i < Data.Length; i++) { var color = Data[i]; if (!colorDict.ContainsKey(color)) { colorDict.Add(color, new ColorCounter(color, 1)); } else { colorDict[color].Count++; } } colorCounters.AddRange(colorDict.Values); } var distance = 255000 / colorCount; while (colorCounters.Count > colorCount) { colorCounters.Sort(); colorCounters = ColorCounter.Reduce(colorCounters, ref distance); distance *= 2; } colorCounters.Sort(); var colors = new ARGB[colorCounters.Count]; for (var i = 0; i < colors.Length; i++) { colors[i] = colorCounters[i].Color; } return(colors); }
/// <summary> /// Creates a new bitmap instance /// </summary> /// <param name="fontName">Name of the font</param> /// <param name="fontSize">Size in points</param> /// <param name="foreColor">ForeColor</param> /// <param name="backColor">BackColor</param> /// <param name="text">text to draw</param> public Bitmap32 Create(string fontName, float fontSize, ARGB foreColor, ARGB backColor, string text) { var paint = new SKPaint(); float emSize = fontSize / 4f * 3f; paint.TextSize = emSize; paint.TextEncoding = SKTextEncoding.Utf8; paint.Color = foreColor.AsUInt32; if (fontName != null) { paint.Typeface = SKTypeface.FromFamilyName(fontName); } paint.IsAntialias = true; float height = paint.GetFontMetrics(out SKFontMetrics metrics); float width = paint.MeasureText(text); var bitmap = new SKBitmap(1 + (int)width, 1 + (int)height, SKImageInfo.PlatformColorType, SKAlphaType.Unpremul); using (var canvas = new SKCanvas(bitmap)) { canvas.Clear(new SKColor(backColor.AsUInt32)); canvas.DrawText(Encoding.UTF8.GetBytes(text), 0, -metrics.Ascent, paint); } return(new SkiaBitmap32(bitmap)); }
/// <summary>Initializes a new instance of the <see cref="ColorCounter"/> class.</summary> /// <param name="color">The color.</param> /// <param name="count">The count.</param> public ColorCounter(ARGB color, int count) { Color = color; Count = count; }
/// <summary> /// Compares two ARGB instances. /// </summary> /// <param name="other">other argb color.</param> /// <returns>compare value.</returns> public int CompareTo(ARGB other) { return((299 * (Red - other.Red)) + (587 * (Green - other.Green)) + (114 * (Blue - other.Blue))); }
/// <summary> /// Clear the image with the specified color. /// </summary> /// <param name="color"></param> public override void Clear(ARGB color) { graphics.Clear(color); }
/// <summary> /// Clear the image with the specified color /// </summary> /// <param name="color"></param> public override void Clear(ARGB color) { canvas.Clear(new SKColor(color.AsUInt32)); }
/// <summary> /// Clears the bitmap with a specific color. /// </summary> public void Clear(ARGB color) { Clear(color.AsInt32); }
/// <summary> /// Creates a 32x32 fingerprint for the specified bitmap. /// </summary> /// <param name="bitmap">The bitmap.</param> /// <returns>Returns a fingerprint with 6 bits per pixel (32 px = 6144 bit = 768 byte = 1024 base32 chars).</returns> public static FingerPrint Create(IBitmap32 bitmap) { using (Bitmap32 thumb = bitmap.Resize(32, 32, ResizeMode.TouchFromInside)) { ARGBImageData data = thumb.Data; using (var ms = new MemoryStream()) { // calculate fingerprint and distance matrix var writer = new BitStreamWriter(ms); float[] distanceMatrix = new float[16]; { int x = 0, y = 0; ARGB last = 0; foreach (ARGB pixel in data.Data) { if (++x > 15) { x = 0; ++y; } int r = pixel.Red >> 6; int g = pixel.Green >> 6; int b = pixel.Blue >> 6; writer.WriteBits(r, 2); writer.WriteBits(g, 2); writer.WriteBits(b, 2); unchecked { int i = ((y << 1) & 0xC) + (x >> 2); float distance = Math.Abs(pixel.GetDistance(last)); distanceMatrix[i] += distance; last = pixel; } } } // normalize matrix float maxDistance = distanceMatrix.Max(); for (int i = 0; i < distanceMatrix.Length; i++) { distanceMatrix[i] /= maxDistance; } // calculate blocks uint[] blocks = new uint[4]; int[] index = new int[] { 0, 2, 8, 10 }; for (int i = 0; i < 4; i++) { int idx = index[i]; uint blockValue = (uint)(255 * distanceMatrix[idx]) << 24; blockValue |= (uint)(255 * distanceMatrix[idx + 1]) << 16; blockValue |= (uint)(255 * distanceMatrix[idx + 4]) << 8; blockValue |= (uint)(255 * distanceMatrix[idx + 5]); blocks[i] = blockValue; } /* * uint b1 = (uint)(uint.MaxValue * (distanceMatrix[0] + distanceMatrix[1] + distanceMatrix[4] + distanceMatrix[5]) /4); * uint b2 = (uint)(uint.MaxValue * (distanceMatrix[3] + distanceMatrix[2] + distanceMatrix[7] + distanceMatrix[6]) / 4); * uint b3 = (uint)(uint.MaxValue * (distanceMatrix[12] + distanceMatrix[13] + distanceMatrix[8] + distanceMatrix[9]) / 4); * uint b4 = (uint)(uint.MaxValue * (distanceMatrix[15] + distanceMatrix[14] + distanceMatrix[11] + distanceMatrix[10]) / 4); */ return(new FingerPrint(32, blocks, ms.ToArray())); } } }
/// <summary> /// Clear the image with the specified color. /// </summary> /// <param name="color">The color.</param> public virtual void Clear(ARGB color) { bitmap.Clear(color); }