public void Indexer() { var block = default(GenericBlock8x8 <Rgb24>); Span <Rgb24> span = block.AsSpanUnsafe(); Assert.Equal(64, span.Length); for (int i = 0; i < 64; i++) { span[i] = new Rgb24((byte)i, (byte)(2 * i), (byte)(3 * i)); } var expected00 = new Rgb24(0, 0, 0); var expected07 = new Rgb24(7, 14, 21); var expected11 = new Rgb24(9, 18, 27); var expected77 = new Rgb24(63, 126, 189); var expected67 = new Rgb24(62, 124, 186); Assert.Equal(expected00, block[0, 0]); Assert.Equal(expected07, block[7, 0]); Assert.Equal(expected11, block[1, 1]); Assert.Equal(expected67, block[6, 7]); Assert.Equal(expected77, block[7, 7]); }
public void ToRgb24(ref Rgb24 dest) { dest.R = (byte)(byte.MaxValue * R); dest.G = (byte)(byte.MaxValue * G); dest.B = (byte)(byte.MaxValue * B); }
public void FromRgb24(Rgb24 source) => this.FromScaledVector4(source.ToScaledVector4());
public async Task ChangeLightColorBasic(Rgb24 c) { if (_sendingCommand) { return; } var dt = DateTime.UtcNow - _lastHueChangeTime; //Hue bridge can only take so many updates at a time (7-10 a second) so this needs to be throttled if (dt.TotalMilliseconds < _frameTimeSpan.TotalMilliseconds) { return; } //If the last colors set are close enough to the current color keep the current color. //This is to prevent a lot of color jittering that can happen otherwise. var min = _config.Model.hueSettings.minColorValue; var max = _config.Model.hueSettings.maxColorValue; var r = Math.Floor(c.R * _config.Model.hueSettings.colorMultiplier); var g = Math.Floor(c.G * _config.Model.hueSettings.colorMultiplier); var b = Math.Floor(c.B * _config.Model.hueSettings.colorMultiplier); r = Math.Clamp(r, min, max); g = Math.Clamp(g, min, max); b = Math.Clamp(b, min, max); if (_lastColor.R >= c.R - _colorChangeThreshold && _lastColor.R <= c.R + _colorChangeThreshold) { r = _lastColor.R; } if (_lastColor.G >= c.G - _colorChangeThreshold && _lastColor.G <= c.G + _colorChangeThreshold) { g = _lastColor.G; } if (_lastColor.B >= c.B - _colorChangeThreshold && _lastColor.B <= c.B + _colorChangeThreshold) { b = _lastColor.B; } if (c == _lastColor) { return; } _lastColor = c; var command = new LightCommand { TransitionTime = _frameTimeSpan }; command.SetColor(new RGBColor(ColorHelper.ColorToHex(c))); _sendingCommand = true; try { await _client.SendCommandAsync(command, UseRoom.Lights); } catch (Exception ex) { _ = Task.Run(() => _logger?.WriteLog(ex.ToString())); } _lastHueChangeTime = DateTime.UtcNow; _sendingCommand = false; }
public static void SetGray2Palette(Rgb24 color0, Rgb24 color33, Rgb24 color66, Rgb24 color100) { Logger.Info("[vpm] Set_4_Colors_Palette()"); _dmdDevice.SetPalette(new[] { ConvertColor(color0), ConvertColor(color33), ConvertColor(color66), ConvertColor(color100) }); }
public void FromRgb24(Rgb24 source) { }
public Color(Rgb24 pixel) { this.data = new Rgba64(pixel); this.boxedHighPrecisionPixel = null; }
// top, right, bottom, left private static Tuple <int, int, int, int> DetermineSomeBox(Image <Rgb24> image, long maximumDeviation) { int topY = -1; int bottomY = -1; int leftX = -1; int rightX = -1; long maxDevX = maximumDeviation; long maxDevY = maximumDeviation; // no maximum deviation given; try to find word core if (maximumDeviation == -1) { maxDevX = (image.Height / 2) * (3 * 255) / 2; maxDevY = (image.Width / 2) * (3 * 255) / 2; } // top border for (int y = 0; y < image.Height; y++) { long rowSum = 0; for (int x = 0; x < image.Width; x++) { Rgb24 pixel = image[x, y]; rowSum += pixel.R + pixel.G + pixel.B; } if (rowSum > maxDevY) { topY = y; break; } } // bottom border for (int y = image.Height - 1; y > -1; y--) { long rowSum = 0; for (int x = 0; x < image.Width; x++) { Rgb24 pixel = image[x, y]; rowSum += pixel.R + pixel.G + pixel.B; } if (rowSum > maxDevY) { bottomY = y; break; } } // left border for (int x = 0; x < image.Width; x++) { long columnSum = 0; for (int y = 0; y < image.Height; y++) { Rgb24 pixel = image[x, y]; columnSum += pixel.R + pixel.G + pixel.B; } if (columnSum > maxDevX) { leftX = x; break; } } // right border for (int x = image.Width - 1; x > -1; x--) { long columnSum = 0; for (int y = 0; y < image.Height; y++) { Rgb24 pixel = image[x, y]; columnSum += pixel.R + pixel.G + pixel.B; } if (columnSum > maxDevX) { rightX = x; break; } } return(new Tuple <int, int, int, int>(topY, rightX, bottomY, leftX)); }
static void GenerateImages( Maze maze, IDictionary <Point32, MazeEdge[]> edges, int wallThickness, int openSpace) { var cellSize = wallThickness + openSpace; using var image = new Image <Rgb24>( maze.Width * cellSize + wallThickness, maze.Height * cellSize + wallThickness, new Rgb24(255, 255, 255)); var black = new Rgb24(); var lastCellX = maze.Width * cellSize; var lastCellY = maze.Height * cellSize; var lastX = maze.Width - 1; var lastY = maze.Height - 1; for (int y = 0; y < maze.Height; ++y) { var imageY = y * cellSize; for (int x = 0; x < maze.Width; ++x) { var imageX = x * cellSize; image.PaintBox( imageX, imageY, wallThickness, wallThickness, black); if (!maze.CanGoUp(x, y)) { image.PaintBox( imageX + wallThickness, imageY, openSpace, wallThickness, black); } if (!maze.CanGoLeft(x, y)) { image.PaintBox( imageX, imageY + wallThickness, wallThickness, openSpace, black); } } if (!maze.CanGoRight(lastX, y)) { image.PaintBox( lastCellX, imageY, wallThickness, cellSize, black); } } for (int x = 0; x < maze.Width; ++x) { if (!maze.CanGoDown(x, lastY)) { image.PaintBox( cellSize * x, lastCellY, cellSize, wallThickness, black); } } image.PaintBox( lastCellX, lastCellY, wallThickness, wallThickness, black); var encoder = new PngEncoder { BitDepth = PngBitDepth.Bit1 }; image.SaveAsPng("maze.original.png"); foreach (var position in edges.Keys) { image.PaintBox( position.X * cellSize + wallThickness, position.Y * cellSize + wallThickness, openSpace, openSpace, new Rgb24(255, 0, 0)); } image.SaveAsPng("maze.nodes.png"); }
public static string ToHex(this Rgb24 p) { return(((uint)(p.B | (p.G << 8) | (p.R << 16))).ToString("X6")); }
public Colors(Rgb24 localMasheePixel, Rgb24 masherPixel, Rgb24 remoteMasheePixel) { LocalMasheeColor = $"rgb({localMasheePixel.R}, {localMasheePixel.G}, {localMasheePixel.B})"; MasherColor = $"rgb({masherPixel.R}, {masherPixel.G}, {masherPixel.B})"; RemoteMasheeColor = $"rgb({remoteMasheePixel.R}, {remoteMasheePixel.G}, {remoteMasheePixel.B})"; }
public static void ImageRegionIsColor(this Assert assert, SixLabors.ImageSharp.Rectangle region, Rgb24 expectedColor, Image <Rgb24> actualImage, double tolerance = 0.0) { //var width = region.Width; var area = region.Width * region.Height; var red = new int[area]; var green = new int[area]; var blue = new int[area]; var indices = new HashSet <int>(); for (var x = region.Left; x < region.Right; x++) { for (var y = region.Top; y < region.Bottom; y++) { var color = actualImage[x, y]; var i = x - region.Left; var j = y - region.Top; var index0 = (i * region.Height) + j; if (indices.Contains(index0)) { Debugger.Break(); } indices.Add(index0); red[index0] = color.R; green[index0] = color.G; blue[index0] = color.B; } } var averageRed = red.Average(); var averageBlue = blue.Average(); var averageGreen = green.Average(); Assert.IsTrue( Math.Abs(averageRed - expectedColor.R) <= tolerance && Math.Abs(averageGreen - expectedColor.G) <= tolerance && Math.Abs(averageBlue - expectedColor.B) <= tolerance, $"Region {region} is not expected color {expectedColor} - actual averages: R={averageRed:F20}, G={averageGreen:F20}, B={averageBlue:F20}"); }
static void Main(string[] args) { Directory.CreateDirectory("data"); var data = File.ReadAllBytes("data/input.txt"); //Get necessary size to make it square var pixelsNeeded = (int)Math.Ceiling((double)data.Length / 3); var pixelCount = Util.getClosestPerfectSquare(pixelsNeeded); var emptyBytes = (pixelCount * 3) - data.Length; var temp = data.ToList(); //We use byte 255 to specify a null item temp.AddRange(Enumerable.Repeat((byte)255, emptyBytes)); data = temp.ToArray(); var sqrt = (int)Math.Sqrt(pixelCount); var xSize = sqrt; var ySize = sqrt; using (Image <Rgb24> image = new Image <Rgb24>(xSize, ySize)) { var x = 0; var y = 0; for (int i = 0; i < data.Length; i += 3) { var r = (byte)data[i]; var g = (i + 1 < data.Length) ? data[i + 1] : (byte)255; var b = (i + 2 < data.Length) ? data[i + 2] : (byte)255; image[x, y] = new Rgb24(r, g, b); if (x == (xSize - 1)) { x = 0; y++; } else { x++; } } image.Save("data/output.png"); } //READ THE IMAGE FILE using (Image <Rgb24> image = Image.Load <Rgb24>("data/output.png")) { byte[] decoded = new byte[image.Width * image.Height * 3]; long pointer = 0; for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { var pixel = image[x, y]; decoded[pointer] = (byte)pixel.R; pointer++; decoded[pointer] = (byte)pixel.G; pointer++; decoded[pointer] = (byte)pixel.B; pointer++; } } //Clear empty bytes decoded = decoded.Where(c => c != (byte)255).ToArray(); var text = Encoding.UTF8.GetString(decoded); Console.WriteLine(text); } }
public static double ColorDistance(Rgb24 a, Rgb24 b) => Math.Sqrt(((a.R - b.R) * (a.R - b.R)) + ((a.G - b.G) * (a.G - b.G)) + ((a.B - b.B) * (a.B - b.B)));
protected void SetColor(Rgb24 clr) { RGB = (new byte[] { clr.R, clr.G, clr.B }); }
public void ToRgb24(ref Rgb24 dest) { throw new NotImplementedException(); }
private float FromColorRGBToHeight(Rgb24 color) { float height = height = -10000 + ((color.R * 256 * 256 + color.G * 256 + color.B) * 0.1f); return(height); }
public XSSFColor(Rgb24 clr) : this() { ctColor.SetRgb(clr.R, clr.G, clr.B); }
static int Main(string[] args) { CommandLineParser.CommandLineParser parser = new() { IgnoreCase = true, AcceptEqualSignSyntaxForValueArguments = true, AcceptHyphen = true, ShowUsageOnEmptyCommandline = true, }; Arguments arguments = new(); try { parser.ExtractArgumentAttributes(arguments); parser.ParseCommandLine(args); } catch (CommandLineArgumentException e) { Console.WriteLine($"Error parsing argument \"{e.Argument}\": {e.Message}"); return(-1); } if (!args.Any()) { return(0); } Font font = new(SystemFonts.Find("consolas"), 55, FontStyle.BoldItalic); ImageOptions imageOptions = new() { InitialWidth = 1920, InitialHeight = 1080, BackgroundColor = new Rgba32(30, 30, 30, 255), CanResize = true, MinimumHorizontalClearance = 20, MinimumVerticalClearance = 200, ScaleValuesOnResize = true, ScaleImageAxesIndepentently = true }; TitleOptions titleOptions = new(font) { Color = new Rgb24(170, 170, 170), Position = TitleOptions.Location.BottomRight, XOffset = 50, YOffset = 50 }; Arguments.ApplyCustomizations(arguments, ref imageOptions, ref titleOptions); string sourceFile = arguments.FilePathToReadFrom?.FullName ?? string.Empty; List <Point> points = GetPointsFromLog(sourceFile); points.Reverse(); string title = arguments.ImageTitle ?? string.Empty; string colorChoice = arguments.ColorPalette ?? string.Empty; if (colorChoice.IsNumeric()) { imageOptions.Colors = ColorManager.GetPreset(int.Parse(colorChoice)); } else { using FileStream fs = new(colorChoice, FileMode.Open, FileAccess.Read); using StreamReader reader = new(fs); imageOptions.Colors = ColorManager.GetColors(reader); } ImageGenerator generator = new ImageGenerator(imageOptions, titleOptions); Image image = generator.GetImage(points, title); string outFilePath = string.Empty; if (!string.IsNullOrEmpty(arguments.OutputDirectory)) { outFilePath = arguments.OutputDirectory; } string fileName = $"{DateTime.Now:yyyy_MM_dd_HHmmss}"; if (!string.IsNullOrEmpty(title)) { fileName = title; } image.SaveAsPng(Path.Combine(outFilePath, fileName) + ".png"); return(0); }
public static void SetGray2PaletteDevice(int id, Rgb24 color0, Rgb24 color33, Rgb24 color66, Rgb24 color100) => InternalSetGray2PaletteDevice(GetDevice(id), color0, color33, color66, color100);
/// <summary> /// Processes the de-filtered scanline filling the image pixel data /// </summary> /// <typeparam name="TPixel">The pixel format.</typeparam> /// <param name="defilteredScanline">The de-filtered scanline</param> /// <param name="pixels">The image</param> private void ProcessDefilteredScanline <TPixel>(byte[] defilteredScanline, ImageFrame <TPixel> pixels) where TPixel : struct, IPixel <TPixel> { var color = default(TPixel); Span <TPixel> rowSpan = pixels.GetPixelRowSpan(this.currentRow); // Trim the first marker byte from the buffer var scanlineBuffer = new Span <byte>(defilteredScanline, 1); switch (this.pngColorType) { case PngColorType.Grayscale: int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1); Span <byte> newScanline1 = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth); for (int x = 0; x < this.header.Width; x++) { byte intensity = (byte)(newScanline1[x] * factor); if (this.hasTrans && intensity == this.intensityTrans) { color.PackFromRgba32(new Rgba32(intensity, intensity, intensity, 0)); } else { color.PackFromRgba32(new Rgba32(intensity, intensity, intensity)); } rowSpan[x] = color; } break; case PngColorType.GrayscaleWithAlpha: for (int x = 0; x < this.header.Width; x++) { int offset = x * this.bytesPerPixel; byte intensity = scanlineBuffer[offset]; byte alpha = scanlineBuffer[offset + this.bytesPerSample]; color.PackFromRgba32(new Rgba32(intensity, intensity, intensity, alpha)); rowSpan[x] = color; } break; case PngColorType.Palette: this.ProcessScanlineFromPalette(scanlineBuffer, rowSpan); break; case PngColorType.Rgb: if (!this.hasTrans) { if (this.header.BitDepth == 16) { int length = this.header.Width * 3; using (var compressed = new Buffer <byte>(length)) { // TODO: Should we use pack from vector here instead? this.From16BitTo8Bit(scanlineBuffer, compressed, length); PixelOperations <TPixel> .Instance.PackFromRgb24Bytes(compressed, rowSpan, this.header.Width); } } else { PixelOperations <TPixel> .Instance.PackFromRgb24Bytes(scanlineBuffer, rowSpan, this.header.Width); } } else { if (this.header.BitDepth == 16) { int length = this.header.Width * 3; using (var compressed = new Buffer <byte>(length)) { // TODO: Should we use pack from vector here instead? this.From16BitTo8Bit(scanlineBuffer, compressed, length); Span <Rgb24> rgb24Span = compressed.Span.NonPortableCast <byte, Rgb24>(); for (int x = 0; x < this.header.Width; x++) { ref Rgb24 rgb24 = ref rgb24Span[x]; var rgba32 = default(Rgba32); rgba32.Rgb = rgb24; rgba32.A = (byte)(rgb24.Equals(this.rgb24Trans) ? 0 : 255); color.PackFromRgba32(rgba32); rowSpan[x] = color; } } } else { Span <Rgb24> rgb24Span = scanlineBuffer.NonPortableCast <byte, Rgb24>(); for (int x = 0; x < this.header.Width; x++) { ref Rgb24 rgb24 = ref rgb24Span[x]; var rgba32 = default(Rgba32); rgba32.Rgb = rgb24; rgba32.A = (byte)(rgb24.Equals(this.rgb24Trans) ? 0 : 255); color.PackFromRgba32(rgba32); rowSpan[x] = color; } }
public static void SetGray2Palette(Rgb24 color0, Rgb24 color33, Rgb24 color66, Rgb24 color100) => InternalSetGray2PaletteDevice(DefaultDevice, color0, color33, color66, color100);
/// <summary> /// Collects a row of grayscale pixels. /// </summary> /// <typeparam name="TPixel">The pixel format.</typeparam> /// <param name="rowSpan">The image row span.</param> private void CollectGrayscaleBytes <TPixel>(ReadOnlySpan <TPixel> rowSpan) where TPixel : struct, IPixel <TPixel> { // Use ITU-R recommendation 709 to match libpng. const float RX = .2126F; const float GX = .7152F; const float BX = .0722F; Span <byte> rawScanlineSpan = this.rawScanline.GetSpan(); if (this.pngColorType.Equals(PngColorType.Grayscale)) { // TODO: Realistically we should support 1, 2, 4, 8, and 16 bit grayscale images. // we currently do the other types via palette. Maybe RC as I don't understand how the data is packed yet // for 1, 2, and 4 bit grayscale images. if (this.use16Bit) { // 16 bit grayscale Rgb48 rgb = default; for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 2) { rowSpan[x].ToRgb48(ref rgb); ushort luminance = (ushort)((RX * rgb.R) + (GX * rgb.G) + (BX * rgb.B)); BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance); } } else { // 8 bit grayscale Rgb24 rgb = default; for (int x = 0; x < rowSpan.Length; x++) { rowSpan[x].ToRgb24(ref rgb); rawScanlineSpan[x] = (byte)((RX * rgb.R) + (GX * rgb.G) + (BX * rgb.B)); } } } else { if (this.use16Bit) { // 16 bit grayscale + alpha Rgba64 rgba = default; for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 4) { rowSpan[x].ToRgba64(ref rgba); ushort luminance = (ushort)((RX * rgba.R) + (GX * rgba.G) + (BX * rgba.B)); BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance); BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.A); } } else { // 8 bit grayscale + alpha Rgba32 rgba = default; for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 2) { rowSpan[x].ToRgba32(ref rgba); rawScanlineSpan[o] = (byte)((RX * rgba.R) + (GX * rgba.G) + (BX * rgba.B)); rawScanlineSpan[o + 1] = rgba.A; } } } }
private static void InternalSetGray2PaletteDevice(DeviceInstance device, Rgb24 color0, Rgb24 color33, Rgb24 color66, Rgb24 color100) { Logger.Info("[vpm] Set_4_Colors_Palette({0},...)", device.Id); device.DmdDevice.SetPalette(new[] { ConvertColor(color0), ConvertColor(color33), ConvertColor(color66), ConvertColor(color100) }); }
private static Color ConvertColor(Rgb24 color) { return(Color.FromRgb((byte)color.Red, (byte)color.Green, (byte)color.Blue)); }
/// <summary> /// Sets pixel at specific position /// </summary> /// <param name="x">X coordinate of the pixel</param> /// <param name="y">Y coordinate of the pixel</param> /// <param name="color">Color to set the pixel to</param> public abstract void SetPixel(int x, int y, Rgb24 color);
public void UpdateEntertainmentGroupFromImage(MemoryStream image, int width, int height) { try { if (_sendingCommand || _cancelToken.IsCancellationRequested) { return; } if ((DateTime.UtcNow - _lastHueChangeTime).TotalMilliseconds < _frameTimeSpan.TotalMilliseconds) { return; } _sendingCommand = true; var start = DateTime.UtcNow; var(x, y) = (0, 0); Rgb24 c; foreach (var light in _streamBaseLayer) { (x, y) = MapLightLocationToImage(light.LightLocation, width, height); image.Seek(Helpers.GetImageCoordinate(width * 3, x, y), SeekOrigin.Begin); var min = _config.Model.hueSettings.minColorValue; var max = _config.Model.hueSettings.maxColorValue; var r = Math.Floor(image.ReadByte() * _config.Model.hueSettings.colorMultiplier); var g = Math.Floor(image.ReadByte() * _config.Model.hueSettings.colorMultiplier); var b = Math.Floor(image.ReadByte() * _config.Model.hueSettings.colorMultiplier); if (_lastLightColors.ContainsKey(light.Id)) { var lastColor = _lastLightColors[light.Id]; var blendAmount = 1.0f - _config.Model.hueSettings.blendLastColorAmount; if (blendAmount != 0.0f) { r = Math.Sqrt((1 - blendAmount) * Math.Pow(lastColor.R, 2) + blendAmount * Math.Pow(r, 2)); g = Math.Sqrt((1 - blendAmount) * Math.Pow(lastColor.G, 2) + blendAmount * Math.Pow(g, 2)); b = Math.Sqrt((1 - blendAmount) * Math.Pow(lastColor.B, 2) + blendAmount * Math.Pow(b, 2)); } if (lastColor.R >= r - _colorChangeThreshold && lastColor.R <= r + _colorChangeThreshold) { r = lastColor.R; } if (lastColor.G >= g - _colorChangeThreshold && lastColor.G <= g + _colorChangeThreshold) { g = lastColor.G; } if (lastColor.B >= b - _colorChangeThreshold && lastColor.B <= b + _colorChangeThreshold) { b = lastColor.B; } c = new Rgb24((byte)Math.Clamp(r, min, max), (byte)Math.Clamp(g, min, max), (byte)Math.Clamp(b, min, max)); _lastLightColors[light.Id] = c; } else { c = new Rgb24((byte)Math.Clamp(r, min, max), (byte)Math.Clamp(g, min, max), (byte)Math.Clamp(b, min, max)); _lastLightColors.Add(light.Id, c); } light.SetState(_cancelToken, new RGBColor(ColorHelper.ColorToHex(c)), 1.0); } _streamClient.ManualUpdate(_streamGroup); //Console.WriteLine($"UpdateEntertainmentGroupFromImage Time: {(DateTime.UtcNow - start).TotalMilliseconds}"); } catch (Exception ex) { _ = Task.Run(() => _logger?.WriteLog(ex.ToString())); } _lastHueChangeTime = DateTime.UtcNow; _sendingCommand = false; }
/// <inheritdoc /> public void FromRgb24(Rgb24 source) { throw new NotImplementedException(); }
public void ToVector4() { var rgb = new Rgb24(1, 2, 3); Assert.Equal(Vec(1, 2, 3), rgb.ToVector4()); }
public void SetColor(Color color) { foreground = color; }