public void Init(Rgba32[,] avgsMaster, Size outputSize, List <Tile> tileImageList, Size tileSize, int tX, int tY) { _avgsMaster = avgsMaster; _tileImageList = tileImageList; _tileSize = tileSize; _tX = tX; _tY = tY; _outputImage = new Image <Rgba32>(tileSize.Width * _tX, tileSize.Height * _tY); }
/// <summary> /// Converts an array's RGB values into int lightness values /// </summary> /// <param name="pixelBuffer"></param> private static void ConvertRGBAToLightnessValues(Rgba32[,] pixelBuffer, Image <Rgba32> imageInput) { pixelLightnessBuffer = new int[imageInput.Width, imageInput.Height]; for (int y = 0; y < imageInput.Height; y++) { for (int x = 0; x < imageInput.Width; x++) { pixelLightnessBuffer[x, y] = (pixelBuffer[x, y].R + pixelBuffer[x, y].G + pixelBuffer[x, y].B) / 3; } } }
// TODO: Load Pixel Data public static Image <Rgba32> ToBitmap(Rgba32[,] colorArray) { var bitmap = new Image <Rgba32>(colorArray.GetLength(0), colorArray.GetLength(1)); for (var x = 0; x < bitmap.Width; x++) { for (var y = 0; y < bitmap.Height; y++) { bitmap[x, y] = colorArray[x, y]; } } return(bitmap); }
private static bool ProcessImage(string filePath, string newPath, Rgba32[,] colors, ref int colorsColumnIndex, ref int colorsRowIndex) { Console.WriteLine($"Processing file: {filePath}"); var bmp = Image.Load <Rgba32>(filePath); for (int y = 0; y < bmp.Height; y++) { for (int x = 0; x < bmp.Width; x++) { var pixel = bmp[x, y]; var lutPixel = new Rgba32(pixel.R, pixel.G, pixel.B); // Find existing color in LUT buffer GetColorIndexes(colors, lutPixel, out int foundColumn, out int foundRow); // Color does not exist in LUT buffer, add it if (foundColumn < 0 || foundRow < 0) { foundColumn = colorsColumnIndex; foundRow = colorsRowIndex; colors[foundColumn, foundRow] = lutPixel; // Increment index, wrapping onto next line if needed (2D LUT will be created) colorsColumnIndex++; if (colorsColumnIndex >= LUT_WIDTH) { colorsColumnIndex = 0; colorsRowIndex++; } } if (colorsRowIndex >= LUT_HEIGHT) { Console.WriteLine($"ERROR: More than {LUT_WIDTH * LUT_HEIGHT} colors found!"); return(false); } // Encode LUT UV coordinates for pixel into image bmp[x, y] = new Rgba32((float)foundColumn / LUT_WIDTH, (float)foundRow / LUT_HEIGHT, 0, pixel.A); } } bmp.Save(newPath); bmp.Dispose(); Console.WriteLine($"Saved {newPath}"); return(true); }
/// <summary> /// Create a 2D array of pixel RGBA32 values for the given image input /// </summary> private static void MapPixelsToArray(Image <Rgba32> imageInput) { pixelBuffer = new Rgba32[imageInput.Width, imageInput.Height]; for (int yHeight = 0; yHeight < imageInput.Height; yHeight++) { Span <Rgba32> pixelRowSpan = imageInput.GetPixelRowSpan(yHeight); for (int xWidth = 0; xWidth < imageInput.Width; xWidth++) { // get pixel data as a tuple (no need for a 3D array as tuple is self contained) pixelBuffer[xWidth, yHeight] = pixelRowSpan[xWidth]; // Console.WriteLine($"Value of pixel Y {yHeight}, X {xWidth} is {pixelBuffer[xWidth, yHeight]}"); } } }
private void Test(string name, Rgba32 background, IBrush <Rgba32> brush, Rgba32[,] expectedPattern) { string path = this.CreateOutputDirectory("Fill", "PatternBrush"); using (Image image = new Image(20, 20)) { image .Fill(background) .Fill(brush); using (FileStream output = File.OpenWrite($"{path}/{name}.png")) { image.Save(output); } using (PixelAccessor <Rgba32> sourcePixels = image.Lock()) { // lets pick random spots to start checking Random r = new Random(); Fast2DArray <Rgba32> expectedPatternFast = new Fast2DArray <Rgba32>(expectedPattern); int xStride = expectedPatternFast.Width; int yStride = expectedPatternFast.Height; int offsetX = r.Next(image.Width / xStride) * xStride; int offsetY = r.Next(image.Height / yStride) * yStride; for (int x = 0; x < xStride; x++) { for (int y = 0; y < yStride; y++) { int actualX = x + offsetX; int actualY = y + offsetY; Rgba32 expected = expectedPatternFast[y, x]; // inverted pattern Rgba32 actual = sourcePixels[actualX, actualY]; if (expected != actual) { Assert.True(false, $"Expected {expected} but found {actual} at ({actualX},{actualY})"); } } } } using (FileStream output = File.OpenWrite($"{path}/{name}x4.png")) { image.Resize(80, 80).Save(output); } } }
private static void SaveLUT(string lutPath, Rgba32[,] colors, int lastColumnIndex, int lastRowIndex) { // Only creat 1D LUT if we can, otherwise create a 2D LUT Image <Rgba32> lut; if (lastRowIndex <= 0) { lut = new Image <Rgba32>(LUT_WIDTH, 1); for (int i = 0; i < LUT_WIDTH; i++) { // Fill LUT with color palette, using black for extra pixels lut[i, 0] = i <= lastColumnIndex ? colors[i, 0] : Rgba32.Black; } } else { lut = new Image <Rgba32>(LUT_WIDTH, LUT_HEIGHT); for (int y = 0; y < LUT_WIDTH; y++) { for (int x = 0; x < LUT_HEIGHT; x++) { // Fill LUT with color palette, using black for extra pixels Rgba32 color; if (x > lastRowIndex || (x == lastRowIndex && y > lastColumnIndex)) { color = Rgba32.Black; } else { color = colors[y, x]; } lut[y, x] = color; } } } lut.Save(lutPath); lut.Dispose(); Console.WriteLine($"Saved {lutPath}"); }
private static void GetColorIndexes(Rgba32[,] colors, Rgba32 color, out int columnIndex, out int rowIndex) { // Find color in buffer for (int y = 0; y < colors.GetLength(0); y++) { for (int x = 0; x < colors.GetLength(1); x++) { if (colors[y, x] == color) { columnIndex = y; rowIndex = x; return; } } } // Color was not found columnIndex = -1; rowIndex = -1; return; }
public void Verify_DispatchAsPixelShader(Device device) { using ReadWriteTexture2D <Rgba32, float4> texture = device.Get().AllocateReadWriteTexture2D <Rgba32, float4>(256, 256); device.Get().ForEach <DispatchPixelShader, float4>(texture); Rgba32[,] data = texture.ToArray(); for (int y = 0; y < texture.Height; y++) { for (int x = 0; x < texture.Width; x++) { Rgba32 pixel = data[y, x]; Assert.AreEqual((float)pixel.R / 255, (float)x / texture.Width, 0.1f); Assert.AreEqual((float)pixel.G / 255, (float)y / texture.Height, 0.1f); Assert.AreEqual(pixel.B, 255); Assert.AreEqual(pixel.A, 255); } } }
private void Test(string name, Rgba32 background, IBrush <Rgba32> brush, Rgba32[,] expectedPattern) { string path = TestEnvironment.CreateOutputDirectory("Fill", "PatternBrush"); using (var image = new Image <Rgba32>(20, 20)) { image.Mutate(x => x .Fill(background) .Fill(brush)); image.Save($"{path}/{name}.png"); using (PixelAccessor <Rgba32> sourcePixels = image.Lock()) { // lets pick random spots to start checking var r = new Random(); var expectedPatternFast = new DenseMatrix <Rgba32>(expectedPattern); int xStride = expectedPatternFast.Columns; int yStride = expectedPatternFast.Rows; int offsetX = r.Next(image.Width / xStride) * xStride; int offsetY = r.Next(image.Height / yStride) * yStride; for (var x = 0; x < xStride; x++) { for (var y = 0; y < yStride; y++) { int actualX = x + offsetX; int actualY = y + offsetY; Rgba32 expected = expectedPatternFast[y, x]; // inverted pattern Rgba32 actual = sourcePixels[actualX, actualY]; if (expected != actual) { Assert.True(false, $"Expected {expected} but found {actual} at ({actualX},{actualY})"); } } } } image.Mutate(x => x.Resize(80, 80)); image.Save($"{path}/{name}x4.png"); } }
private async Task <Result <Image <Rgba32> > > GenerateMosaic(Size outputSize, Image <Rgba32> resizedMasterImage, Size tileSize, MosaicTypeEnum selectedMosaicType) { _tileSize = tileSize; _tX = resizedMasterImage.Width / tileSize.Width; _tY = resizedMasterImage.Height / tileSize.Height; _avgsMaster = new Rgba32[_tX, _tY]; GetTilesAverage(resizedMasterImage); if (selectedMosaicType != MosaicTypeEnum.PlainColor) { await LoadTilesAndResize(); } _searchAndReplaceService = _searchAndReplaceServiceFactory.Create(selectedMosaicType); _searchAndReplaceService.Init(_avgsMaster, outputSize, _tileImageList, tileSize, _tX, _tY); var finalImage = _searchAndReplaceService.SearchAndReplace(); Dispose(); return(Result.Ok(finalImage)); }
public unsafe void PixelShader_EarlyReturn(Device device) { using ReadWriteTexture2D <Rgba32, float4> texture = device.Get().AllocateReadWriteTexture2D <Rgba32, float4>(128, 128); device.Get().ForEach <EarlyReturnShader, float4>(texture); Rgba32[,] result = texture.ToArray(); for (int i = 0; i < texture.Height; i++) { for (int j = 0; j < texture.Width; j++) { if (j % 2 == 0) { Assert.AreEqual(result[i, j], new Rgba32(255, 0, 0, 0)); } else { Assert.AreEqual(result[i, j], new Rgba32(0, 255, 0, 0)); } } } }
private static bool ProcessImages(string rootPath, string outputDir, string[] files, Rgba32[,] colors, ref int colorsColumnIndex, ref int colorsRowIndex) { foreach (var file in files) { // Preserve folder structure when creating encoded copies string newPath = GetFilePathRelative(rootPath, file, outputDir); // Keep processing images unless and error is detected if (!ProcessImage(file, newPath, colors, ref colorsColumnIndex, ref colorsRowIndex)) { return(false); } } return(true); }
/// <summary> /// Generates a new <see cref="DrawablesOutput"/> for this <see cref="Image"/>, using all the set properties. /// </summary> /// <returns>DrawablesOutput containing the Drawables for this image.</returns> public DrawablesOutput Generate() { if (Image == null) { throw new DrawableException("Attempted to generate drawables for a disposed image object."); } Rgba32?ignore = IgnoreColor; Image <Rgba32> b = _image.Clone(); if (FlipY) { b.Mutate(x => x.Flip(SixLabors.ImageSharp.Processing.FlipType.Vertical)); } Point frameCount = new Point( (int)Math.Ceiling((decimal)b.Width / DrawableWidth), (int)Math.Ceiling((decimal)b.Height / DrawableHeight)); Drawable[,] drawables = new Drawable[frameCount.X, frameCount.Y]; Rgba32[,] template = GetTemplate(); Point imagePixel = new Point(0, 0); // Add a drawable for every signplaceholder needed. for (int frameWidth = 0; frameWidth < frameCount.X; frameWidth++) { for (int frameHeight = 0; frameHeight < frameCount.Y; frameHeight++) { imagePixel.X = frameWidth * DrawableWidth; imagePixel.Y = frameHeight * DrawableHeight; bool containsPixels = false; StringBuilder directives = new StringBuilder("?replace"); for (int i = 0; i < DrawableWidth; i++) { for (int j = 0; j < DrawableHeight; j++) { int x = imagePixel.X, y = imagePixel.Y++; // Pixel falls within template but is outside of the supplied image. if ((x > b.Width - 1 || y > b.Height - 1)) { continue; } Rgba32 imageColor = b[Convert.ToInt32(x), Convert.ToInt32(y)]; // Pixel color is invisible or ignored. if ((ignore.HasValue && imageColor.Equals(ignore)) || (imageColor.A == 0 && !ReplaceBlank)) { continue; } else if (ReplaceWhite && imageColor.ToRGBAHexString() == "FFFFFFFF") { imageColor = new Rgba32(254, 254, 254, 255); } Rgba32 templateColor = template[i, j]; directives.AppendFormat(";{0}={1}", templateColor.ToRGBAHexString(), imageColor.ToRGBAHexString()); if (imageColor.A > 1) { containsPixels = true; } } imagePixel.X++; imagePixel.Y = frameHeight * DrawableHeight; } int xb = Convert.ToInt32(frameWidth * DrawableWidth), yb = Convert.ToInt32(frameHeight * DrawableHeight); if (containsPixels) { drawables[frameWidth, frameHeight] = new Drawable(directives.ToString(), xb, yb, DrawableTexture); } } } return(new DrawablesOutput(drawables, Image.Width, Image.Height, OffsetX, OffsetY)); }