public void CopyToThenCopyFromWithOffset <TPixel>(TestImageProvider <TPixel> provider, ComponentOrder order) where TPixel : struct, IPixel <TPixel> { using (Image <TPixel> destImage = new Image <TPixel>(8, 8)) { using (Image <TPixel> srcImage = provider.GetImage()) { Fill(srcImage, new Rectangle(4, 4, 8, 8), NamedColors <TPixel> .Red); using (PixelAccessor <TPixel> srcPixels = srcImage.Lock()) { using (PixelArea <TPixel> area = new PixelArea <TPixel>(8, 8, order)) { srcPixels.CopyTo(area, 4, 4); using (PixelAccessor <TPixel> destPixels = destImage.Lock()) { destPixels.CopyFrom(area, 0, 0); } } } } provider.Utility.SourceFileOrDescription = order.ToString(); provider.Utility.SaveTestOutputFile(destImage, "bmp"); using (Image <TPixel> expectedImage = new Image <TPixel>(8, 8).Fill(NamedColors <TPixel> .Red)) { Assert.True(destImage.IsEquivalentTo(expectedImage)); } } }
/// <summary> /// Collects a row of true color pixel data. /// </summary> /// <typeparam name="TColor">The pixel format.</typeparam> /// <param name="pixels">The image pixel accessor.</param> /// <param name="row">The row index.</param> /// <param name="rawScanline">The raw scanline.</param> private void CollectColorBytes <TColor>(PixelAccessor <TColor> pixels, int row, byte[] rawScanline) where TColor : struct, IPackedPixel, IEquatable <TColor> { // We can use the optimized PixelAccessor here and copy the bytes in unmanaged memory. using (PixelArea <TColor> pixelRow = new PixelArea <TColor>(this.width, rawScanline, this.bytesPerPixel == 4 ? ComponentOrder.Xyzw : ComponentOrder.Xyz)) { pixels.CopyTo(pixelRow, row); } }
/// <summary> /// Writes the 24bit color palette to the stream. /// </summary> /// <typeparam name="TColor">The pixel format.</typeparam> /// <param name="writer">The <see cref="EndianBinaryWriter"/> containing the stream to write to.</param> /// <param name="pixels">The <see cref="PixelAccessor{TColor}"/> containing pixel data.</param> private void Write24Bit <TColor>(EndianBinaryWriter writer, PixelAccessor <TColor> pixels) where TColor : struct, IPackedPixel, IEquatable <TColor> { using (PixelArea <TColor> row = new PixelArea <TColor>(pixels.Width, ComponentOrder.Zyx, this.padding)) { for (int y = pixels.Height - 1; y >= 0; y--) { pixels.CopyTo(row, y); writer.Write(row.Bytes, 0, row.Length); } } }
/// <summary> /// Writes the 32bit color palette to the stream. /// </summary> /// <typeparam name="TPixel">The pixel format.</typeparam> /// <param name="writer">The <see cref="EndianBinaryWriter"/> containing the stream to write to.</param> /// <param name="pixels">The <see cref="PixelAccessor{TPixel}"/> containing pixel data.</param> private void Write32Bit <TPixel>(EndianBinaryWriter writer, PixelAccessor <TPixel> pixels) where TPixel : struct, IPixel <TPixel> { using (PixelArea <TPixel> row = new PixelArea <TPixel>(pixels.Width, ComponentOrder.Zyxw, this.padding)) { for (int y = pixels.Height - 1; y >= 0; y--) { pixels.CopyTo(row, y); writer.Write(row.Bytes, 0, row.Length); } } }
/// <summary> /// Writes the 24bit color palette to the stream. /// </summary> /// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <param name="writer">The <see cref="EndianBinaryWriter"/> containing the stream to write to.</param> /// <param name="pixels">The <see cref="PixelAccessor{TColor,TPacked}"/> containing pixel data.</param> private void Write24Bit <TColor, TPacked>(EndianBinaryWriter writer, PixelAccessor <TColor, TPacked> pixels) where TColor : struct, IPackedPixel <TPacked> where TPacked : struct { using (PixelRow <TColor, TPacked> row = new PixelRow <TColor, TPacked>(pixels.Width, ComponentOrder.ZYX, this.padding)) { for (int y = pixels.Height - 1; y >= 0; y--) { pixels.CopyTo(row, y); writer.Write(row.Bytes); } } }
private static void CopyToZYX <TPixel>(Image <TPixel> image) where TPixel : struct, IPixel <TPixel> { using (PixelAccessor <TPixel> pixels = image.Lock()) { byte red = 1; byte green = 2; byte blue = 3; using (PixelArea <TPixel> row = new PixelArea <TPixel>(1, ComponentOrder.Zyx)) { pixels[0, 0] = (TPixel)(object)new Rgba32(red, green, blue); pixels.CopyTo(row, 0); Assert.Equal(blue, row.Bytes[0]); Assert.Equal(green, row.Bytes[1]); Assert.Equal(red, row.Bytes[2]); } } }
private static void CopyToZYX <TColor>(Image <TColor> image) where TColor : struct, IPackedPixel, IEquatable <TColor> { using (PixelAccessor <TColor> pixels = image.Lock()) { byte red = 1; byte green = 2; byte blue = 3; using (PixelArea <TColor> row = new PixelArea <TColor>(1, ComponentOrder.Zyx)) { pixels[0, 0] = (TColor)(object)new Color(red, green, blue); pixels.CopyTo(row, 0); Assert.Equal(blue, row.Bytes[0]); Assert.Equal(green, row.Bytes[1]); Assert.Equal(red, row.Bytes[2]); } } }
private static void CopyToXYZ <TColor, TPacked>(Image <TColor, TPacked> image) where TColor : struct, IPackedPixel <TPacked> where TPacked : struct, IEquatable <TPacked> { using (PixelAccessor <TColor, TPacked> pixels = image.Lock()) { byte red = 1; byte green = 2; byte blue = 3; using (PixelArea <TColor, TPacked> row = new PixelArea <TColor, TPacked>(image.Width, image.Height, ComponentOrder.XYZ)) { pixels[0, 0] = (TColor)(object)new Color(red, green, blue); pixels.CopyTo(row, 0); Assert.Equal(red, row.Bytes[0]); Assert.Equal(green, row.Bytes[1]); Assert.Equal(blue, row.Bytes[2]); } } }
public void CopyTo_Then_CopyFrom_OnFullImageRect <TPixel>(TestImageProvider <TPixel> provider, ComponentOrder order) where TPixel : struct, IPixel <TPixel> { using (Image <TPixel> src = provider.GetImage()) { using (Image <TPixel> dest = new Image <TPixel>(src.Width, src.Height)) { using (PixelArea <TPixel> area = new PixelArea <TPixel>(src.Width, src.Height, order)) { using (PixelAccessor <TPixel> srcPixels = src.Lock()) { srcPixels.CopyTo(area, 0, 0); } using (PixelAccessor <TPixel> destPixels = dest.Lock()) { destPixels.CopyFrom(area, 0, 0); } } Assert.True(src.IsEquivalentTo(dest, false)); } } }
private static void CopyToZYXW <TColor, TPacked>(Image <TColor, TPacked> image) where TColor : struct, IPackedPixel <TPacked> where TPacked : struct { using (PixelAccessor <TColor, TPacked> pixels = image.Lock()) { byte red = 1; byte green = 2; byte blue = 3; byte alpha = 4; using (PixelRow <TColor, TPacked> row = new PixelRow <TColor, TPacked>(1, ComponentOrder.ZYXW)) { pixels[0, 0] = (TColor)(object)new Color(red, green, blue, alpha); pixels.CopyTo(row, 0); Assert.Equal(blue, row.Bytes[0]); Assert.Equal(green, row.Bytes[1]); Assert.Equal(red, row.Bytes[2]); Assert.Equal(alpha, row.Bytes[3]); } } }
public void CopyToThenCopyFromWithOffset <TColor>(TestImageProvider <TColor> provider, ComponentOrder order) where TColor : struct, IPackedPixel, IEquatable <TColor> { using (Image <TColor> destImage = new Image <TColor>(8, 8)) { TColor color; using (Image <TColor> srcImage = provider.GetImage()) { color = default(TColor); color.PackFromBytes(255, 0, 0, 255); Fill(srcImage, new Rectangle(4, 4, 8, 8), color); using (PixelAccessor <TColor> srcPixels = srcImage.Lock()) { using (PixelArea <TColor> area = new PixelArea <TColor>(8, 8, order)) { srcPixels.CopyTo(area, 4, 4); using (PixelAccessor <TColor> destPixels = destImage.Lock()) { destPixels.CopyFrom(area, 0, 0); } } } } provider.Utility.SourceFileOrDescription = order.ToString(); provider.Utility.SaveTestOutputFile(destImage, "bmp"); using (Image <TColor> expectedImage = new Image <TColor>(8, 8).Fill(color)) { Assert.True(destImage.IsEquivalentTo(expectedImage)); } } }
/// <inheritdoc/> protected override void OnApply(ImageBase <TPixel> source, Rectangle sourceRectangle) { int kernelYHeight = this.KernelY.Height; int kernelYWidth = this.KernelY.Width; int kernelXHeight = this.KernelX.Height; int kernelXWidth = this.KernelX.Width; int radiusY = kernelYHeight >> 1; int radiusX = kernelXWidth >> 1; int startY = sourceRectangle.Y; int endY = sourceRectangle.Bottom; int startX = sourceRectangle.X; int endX = sourceRectangle.Right; int maxY = endY - 1; int maxX = endX - 1; using (PixelAccessor <TPixel> targetPixels = new PixelAccessor <TPixel>(source.Width, source.Height)) using (PixelAccessor <TPixel> sourcePixels = source.Lock()) { sourcePixels.CopyTo(targetPixels); Parallel.For( startY, endY, this.ParallelOptions, y => { for (int x = startX; x < endX; x++) { float rX = 0; float gX = 0; float bX = 0; float rY = 0; float gY = 0; float bY = 0; // Apply each matrix multiplier to the color components for each pixel. for (int fy = 0; fy < kernelYHeight; fy++) { int fyr = fy - radiusY; int offsetY = y + fyr; offsetY = offsetY.Clamp(0, maxY); for (int fx = 0; fx < kernelXWidth; fx++) { int fxr = fx - radiusX; int offsetX = x + fxr; offsetX = offsetX.Clamp(0, maxX); Vector4 currentColor = sourcePixels[offsetX, offsetY].ToVector4(); if (fy < kernelXHeight) { Vector4 kx = this.KernelX[fy, fx] * currentColor; rX += kx.X; gX += kx.Y; bX += kx.Z; } if (fx < kernelYWidth) { Vector4 ky = this.KernelY[fy, fx] * currentColor; rY += ky.X; gY += ky.Y; bY += ky.Z; } } } float red = MathF.Sqrt((rX * rX) + (rY * rY)); float green = MathF.Sqrt((gX * gX) + (gY * gY)); float blue = MathF.Sqrt((bX * bX) + (bY * bY)); TPixel packed = default(TPixel); packed.PackFromVector4(new Vector4(red, green, blue, sourcePixels[x, y].ToVector4().W)); targetPixels[x, y] = packed; } }); source.SwapPixelsBuffers(targetPixels); } }
/// <inheritdoc/> protected override void OnApply(ImageBase <TPixel> source, Rectangle sourceRectangle) { int startY = sourceRectangle.Y; int endY = sourceRectangle.Bottom; int startX = sourceRectangle.X; int endX = sourceRectangle.Right; int radius = this.BrushSize >> 1; int levels = this.Levels; // Align start/end positions. int minX = Math.Max(0, startX); int maxX = Math.Min(source.Width, endX); int minY = Math.Max(0, startY); int maxY = Math.Min(source.Height, endY); // Reset offset if necessary. if (minX > 0) { startX = 0; } using (PixelAccessor <TPixel> targetPixels = new PixelAccessor <TPixel>(source.Width, source.Height)) using (PixelAccessor <TPixel> sourcePixels = source.Lock()) { sourcePixels.CopyTo(targetPixels); Parallel.For( minY, maxY, this.ParallelOptions, y => { for (int x = startX; x < endX; x++) { int maxIntensity = 0; int maxIndex = 0; int[] intensityBin = new int[levels]; float[] redBin = new float[levels]; float[] blueBin = new float[levels]; float[] greenBin = new float[levels]; for (int fy = 0; fy <= radius; fy++) { int fyr = fy - radius; int offsetY = y + fyr; // Skip the current row if (offsetY < minY) { continue; } // Outwith the current bounds so break. if (offsetY >= maxY) { break; } for (int fx = 0; fx <= radius; fx++) { int fxr = fx - radius; int offsetX = x + fxr; // Skip the column if (offsetX < 0) { continue; } if (offsetX < maxX) { // ReSharper disable once AccessToDisposedClosure Vector4 color = sourcePixels[offsetX, offsetY].ToVector4(); float sourceRed = color.X; float sourceBlue = color.Z; float sourceGreen = color.Y; int currentIntensity = (int)Math.Round((sourceBlue + sourceGreen + sourceRed) / 3.0 * (levels - 1)); intensityBin[currentIntensity] += 1; blueBin[currentIntensity] += sourceBlue; greenBin[currentIntensity] += sourceGreen; redBin[currentIntensity] += sourceRed; if (intensityBin[currentIntensity] > maxIntensity) { maxIntensity = intensityBin[currentIntensity]; maxIndex = currentIntensity; } } } float red = MathF.Abs(redBin[maxIndex] / maxIntensity); float green = MathF.Abs(greenBin[maxIndex] / maxIntensity); float blue = MathF.Abs(blueBin[maxIndex] / maxIntensity); TPixel packed = default(TPixel); packed.PackFromVector4(new Vector4(red, green, blue, sourcePixels[x, y].ToVector4().W)); targetPixels[x, y] = packed; } } }); source.SwapPixelsBuffers(targetPixels); } }
/// <inheritdoc/> protected override void OnApply(ImageBase <TPixel> source, Rectangle sourceRectangle) { int kernelLength = this.KernelXY.Height; int radius = kernelLength >> 1; int startY = sourceRectangle.Y; int endY = sourceRectangle.Bottom; int startX = sourceRectangle.X; int endX = sourceRectangle.Right; int maxY = endY - 1; int maxX = endX - 1; using (PixelAccessor <TPixel> targetPixels = new PixelAccessor <TPixel>(source.Width, source.Height)) using (PixelAccessor <TPixel> sourcePixels = source.Lock()) { sourcePixels.CopyTo(targetPixels); Parallel.For( startY, endY, this.ParallelOptions, y => { for (int x = startX; x < endX; x++) { float red = 0; float green = 0; float blue = 0; // Apply each matrix multiplier to the color components for each pixel. for (int fy = 0; fy < kernelLength; fy++) { int fyr = fy - radius; int offsetY = y + fyr; offsetY = offsetY.Clamp(0, maxY); for (int fx = 0; fx < kernelLength; fx++) { int fxr = fx - radius; int offsetX = x + fxr; offsetX = offsetX.Clamp(0, maxX); Vector4 currentColor = sourcePixels[offsetX, offsetY].ToVector4(); currentColor *= this.KernelXY[fy, fx]; red += currentColor.X; green += currentColor.Y; blue += currentColor.Z; } } TPixel packed = default(TPixel); packed.PackFromVector4(new Vector4(red, green, blue, sourcePixels[x, y].ToVector4().W)); targetPixels[x, y] = packed; } }); source.SwapPixelsBuffers(targetPixels); } }