public void CopyTo_Then_CopyFrom_WithOffset <TColor>(TestImageProvider <TColor> provider, ComponentOrder order) where TColor : struct, IPackedPixel, IEquatable <TColor> { var srcImage = provider.GetImage(); var color = default(TColor); color.PackFromBytes(255, 0, 0, 255); Fill(srcImage, new Rectangle(4, 4, 8, 8), color); var destImage = new Image <TColor>(8, 8); using (var srcPixels = srcImage.Lock()) { using (var area = new PixelArea <TColor>(8, 8, order)) { srcPixels.CopyTo(area, 4, 4); using (var destPixels = destImage.Lock()) { destPixels.CopyFrom(area, 0, 0); } } } provider.Utility.SourceFileOrDescription = order.ToString(); provider.Utility.SaveTestOutputFile(destImage, "bmp"); var expectedImage = new Image <TColor>(8, 8).Fill(color); Assert.True(destImage.IsEquivalentTo(expectedImage)); }
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)); } } }
public void CanAddSamplesToFilmTile() { var width = 800; var height = 600; var film = new Film(new PixelVector(width, height), new Bounds2D(0, 0, 1, 1), new MitchellFilter(new Vector2(2, 2), 0.25f, 0.5f), 10f, 1f); var testSink = new TestRGBSink(); film.SetSink(testSink); var tileArea = new PixelArea(0, 0, 16, 16); var tile = film.CreateFilmTile(in tileArea); tile.AddSample(new Point2D(0.5f, 0.5f), Spectrum.One); film.MergeFilmTile(tile); film.WriteFile(1f); film.Return(); testSink.Data[0].Should().BeGreaterThan(0f); testSink.Data[1].Should().BeGreaterThan(0f); testSink.Data[2].Should().BeGreaterThan(0f); testSink.Data[800 * 3 + 0].Should().BeGreaterThan(0f); testSink.Data[800 * 3 + 1].Should().BeGreaterThan(0f); testSink.Data[800 * 3 + 2].Should().BeGreaterThan(0f); }
private static void CopyFromZYX <TColor>(Image <TColor> image) where TColor : struct, IPixel <TColor> { using (PixelAccessor <TColor> pixels = image.Lock()) { byte red = 1; byte green = 2; byte blue = 3; byte alpha = 255; using (PixelArea <TColor> row = new PixelArea <TColor>(1, ComponentOrder.Zyx)) { row.Bytes[0] = blue; row.Bytes[1] = green; row.Bytes[2] = red; pixels.CopyFrom(row, 0); Color color = (Color)(object)pixels[0, 0]; Assert.Equal(red, color.R); Assert.Equal(green, color.G); Assert.Equal(blue, color.B); Assert.Equal(alpha, color.A); } } }
private void RestoreToBackground(ImageBase <TColor, TPacked> frame) { if (this.restoreArea == null) { return; } // Optimization for when the size of the frame is the same as the image size. if (this.restoreArea.Value.Width == this.decodedImage.Width && this.restoreArea.Value.Height == this.decodedImage.Height) { using (PixelAccessor <TColor, TPacked> pixelAccessor = frame.Lock()) { pixelAccessor.Reset(); } } else { using (PixelArea <TColor, TPacked> emptyRow = new PixelArea <TColor, TPacked>(this.restoreArea.Value.Width, ComponentOrder.XYZW)) { using (PixelAccessor <TColor, TPacked> pixelAccessor = frame.Lock()) { for (int y = this.restoreArea.Value.Top; y < this.restoreArea.Value.Top + this.restoreArea.Value.Height; y++) { pixelAccessor.CopyFrom(emptyRow, y, this.restoreArea.Value.Left); } } } } this.restoreArea = null; }
public void Initialize() { var area = new PixelArea(new PixelCoordinate(0, 0), new PixelCoordinate(100, 100)); var hs = new HaltonSampler(10, area); hs.SamplesPerPixel.Should().Be(10); }
public void HoldMinAndMax() { var pa = new PixelArea(new PixelCoordinate(10, 20), new PixelCoordinate(50, 100)); pa.Min.Should().Be(new PixelCoordinate(10, 20)); pa.Max.Should().Be(new PixelCoordinate(50, 100)); }
public void GetCameraSampleForPixels() { var start = new PixelCoordinate(0, 0); var end = new PixelCoordinate(100, 100); var area = new PixelArea(start, end); var hs = new HaltonSampler(10, area); var arena = new ObjectArena(); hs.StartPixel(in start); var cs = hs.GetCameraSample(in start, arena); cs.FilmPoint.X.Should().BeInRange(0f, 1f); cs.FilmPoint.Y.Should().BeInRange(0f, 1f); cs.LensPoint.X.Should().BeInRange(0f, 1f); cs.LensPoint.Y.Should().BeInRange(0f, 1f); var next = new PixelCoordinate(1, 0); hs.StartPixel(in next); var csn = hs.GetCameraSample(in next, arena); csn.FilmPoint.X.Should().BeInRange(1f, 2f); csn.FilmPoint.Y.Should().BeInRange(0f, 1f); csn.LensPoint.X.Should().BeInRange(0f, 1f); csn.LensPoint.Y.Should().BeInRange(0f, 1f); cs.FilmPoint.X.Should().NotBe(csn.FilmPoint.X); cs.FilmPoint.Y.Should().NotBe(csn.FilmPoint.Y); cs.LensPoint.X.Should().NotBe(csn.LensPoint.X); cs.LensPoint.Y.Should().NotBe(csn.LensPoint.Y); }
/// <summary> /// Reads the 16 bit color palette from the stream /// </summary> /// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam> /// <param name="pixels">The <see cref="PixelAccessor{TColor, TPacked}"/> to assign the palette to.</param> /// <param name="width">The width of the bitmap.</param> /// <param name="height">The height of the bitmap.</param> /// <param name="inverted">Whether the bitmap is inverted.</param> private void ReadRgb16 <TColor, TPacked>(PixelAccessor <TColor, TPacked> pixels, int width, int height, bool inverted) where TColor : struct, IPackedPixel <TPacked> where TPacked : struct { // We divide here as we will store the colors in our floating point format. const int ScaleR = 8; // 256/32 const int ScaleG = 4; // 256/64 const int ComponentCount = 2; TColor color = default(TColor); using (PixelArea <TColor, TPacked> row = new PixelArea <TColor, TPacked>(width, ComponentOrder.XYZ)) { for (int y = 0; y < height; y++) { row.Read(this.currentStream); int newY = Invert(y, height, inverted); int offset = 0; for (int x = 0; x < width; x++) { short temp = BitConverter.ToInt16(row.Bytes, offset); byte r = (byte)(((temp & Rgb16RMask) >> 11) * ScaleR); byte g = (byte)(((temp & Rgb16GMask) >> 5) * ScaleG); byte b = (byte)((temp & Rgb16BMask) * ScaleR); color.PackFromBytes(r, g, b, 255); pixels[x, newY] = color; offset += ComponentCount; } } } }
private static void CopyFromZYXW <TPixel>(Image <TPixel> image) where TPixel : struct, IPixel <TPixel> { using (PixelAccessor <TPixel> pixels = image.Lock()) { byte red = 1; byte green = 2; byte blue = 3; byte alpha = 4; using (PixelArea <TPixel> row = new PixelArea <TPixel>(1, ComponentOrder.Zyxw)) { row.Bytes[0] = blue; row.Bytes[1] = green; row.Bytes[2] = red; row.Bytes[3] = alpha; pixels.CopyFrom(row, 0); Rgba32 color = (Rgba32)(object)pixels[0, 0]; Assert.Equal(red, color.R); Assert.Equal(green, color.G); Assert.Equal(blue, color.B); Assert.Equal(alpha, color.A); } } }
public static void AddGifFrameBuffer(PipelineContext ctx, bool replay = true) { if (!(ctx.ImageFrame is WicImageFrame wicFrame) || !(wicFrame.Container is WicGifContainer gif)) { return; } Debug.Assert(wicFrame.WicMetadataReader != null); if (replay && ctx.Settings.FrameIndex > 0) { WicImageFrame.ReplayGifAnimationContext(gif, ctx.Settings.FrameIndex - 1); } var finfo = WicImageFrame.GetGifFrameInfo(gif, wicFrame.WicSource, wicFrame.WicMetadataReader); var ldisp = gif.AnimationContext?.LastDisposal ?? GifDisposalMethod.RestoreBackground; bool useBuffer = !replay && finfo.Disposal == GifDisposalMethod.Preserve; if (!replay) { var anictx = gif.AnimationContext ??= new GifAnimationContext(); if (finfo.Disposal == GifDisposalMethod.Preserve) { WicImageFrame.UpdateGifAnimationContext(gif, wicFrame.WicSource, wicFrame.WicMetadataReader); } anictx.LastDisposal = finfo.Disposal; anictx.LastFrame = ctx.Settings.FrameIndex; ldisp = finfo.Disposal; } if (gif.AnimationContext != null && gif.AnimationContext.FrameBufferSource != null && ldisp != GifDisposalMethod.RestoreBackground) { ctx.Source = gif.AnimationContext.FrameBufferSource; } if (!finfo.FullScreen && ldisp == GifDisposalMethod.RestoreBackground && !useBuffer) { var innerArea = new PixelArea(finfo.Left, finfo.Top, wicFrame.Source.Width, wicFrame.Source.Height); var outerArea = new PixelArea(0, 0, gif.ScreenWidth, gif.ScreenHeight); var bgColor = finfo.Alpha ? Color.Empty : Color.FromArgb((int)gif.BackgroundColor); ctx.Source = new PadTransformInternal(wicFrame.Source, bgColor, innerArea, outerArea, true); } else if (ldisp != GifDisposalMethod.RestoreBackground && !useBuffer) { Debug.Assert(gif.AnimationContext?.FrameBufferSource != null); var ani = gif.AnimationContext; var fbuff = ani.FrameBufferSource; ani.FrameOverlay?.Dispose(); ani.FrameOverlay = new OverlayTransform(fbuff, wicFrame.Source, finfo.Left, finfo.Top, finfo.Alpha); ctx.Source = ani.FrameOverlay; } }
/// <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> /// Converts the 8x8 region of the image whose top-left corner is x,y to its YCbCr values. /// </summary> /// <typeparam name="TColor">The pixel format.</typeparam> /// <param name="pixels">The pixel accessor.</param> /// <param name="x">The x-position within the image.</param> /// <param name="y">The y-position within the image.</param> /// <param name="yBlock">The luminance block.</param> /// <param name="cbBlock">The red chroma block.</param> /// <param name="crBlock">The blue chroma block.</param> /// <param name="rgbBytes">Temporal <see cref="PixelArea{TColor}"/> provided by the caller</param> private static void ToYCbCr <TColor>( PixelAccessor <TColor> pixels, int x, int y, Block8x8F *yBlock, Block8x8F *cbBlock, Block8x8F *crBlock, PixelArea <TColor> rgbBytes) where TColor : struct, IPackedPixel, IEquatable <TColor> { float *yBlockRaw = (float *)yBlock; float *cbBlockRaw = (float *)cbBlock; float *crBlockRaw = (float *)crBlock; rgbBytes.Reset(); pixels.CopyRGBBytesStretchedTo(rgbBytes, y, x); byte *data = (byte *)rgbBytes.DataPointer; for (int j = 0; j < 8; j++) { int j8 = j * 8; for (int i = 0; i < 8; i++) { // Convert returned bytes into the YCbCr color space. Assume RGBA int r = data[0]; int g = data[1]; int b = data[2]; // Speed up the algorithm by removing floating point calculation // Scale by 65536, add .5F and truncate value. We use bit shifting to divide the result int y0 = 19595 * r; // (0.299F * 65536) + .5F int y1 = 38470 * g; // (0.587F * 65536) + .5F int y2 = 7471 * b; // (0.114F * 65536) + .5F int cb0 = -11057 * r; // (-0.168736F * 65536) + .5F int cb1 = 21710 * g; // (0.331264F * 65536) + .5F int cb2 = 32768 * b; // (0.5F * 65536) + .5F int cr0 = 32768 * r; // (0.5F * 65536) + .5F int cr1 = 27439 * g; // (0.418688F * 65536) + .5F int cr2 = 5329 * b; // (0.081312F * 65536) + .5F float yy = (y0 + y1 + y2) >> 16; float cb = 128 + ((cb0 - cb1 + cb2) >> 16); float cr = 128 + ((cr0 - cr1 - cr2) >> 16); int index = j8 + i; yBlockRaw[index] = yy; cbBlockRaw[index] = cb; crBlockRaw[index] = cr; data += 3; } } }
/// <summary> /// Encodes the image with no subsampling. /// </summary> /// <typeparam name="TColor">The pixel format.</typeparam> /// <param name="pixels">The pixel accessor providing access to the image pixels.</param> private void Encode444 <TColor>(PixelAccessor <TColor> pixels) where TColor : struct, IPackedPixel, IEquatable <TColor> { // TODO: Need a JpegScanEncoder<TColor> class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.) Block8x8F b = default(Block8x8F); Block8x8F cb = default(Block8x8F); Block8x8F cr = default(Block8x8F); Block8x8F temp1 = default(Block8x8F); Block8x8F temp2 = default(Block8x8F); Block8x8F onStackLuminanceQuantTable = this.luminanceQuantTable; Block8x8F onStackChrominanceQuantTable = this.chrominanceQuantTable; UnzigData unzig = UnzigData.Create(); // ReSharper disable once InconsistentNaming int prevDCY = 0, prevDCCb = 0, prevDCCr = 0; using (PixelArea <TColor> rgbBytes = new PixelArea <TColor>(8, 8, ComponentOrder.Xyz)) { for (int y = 0; y < pixels.Height; y += 8) { for (int x = 0; x < pixels.Width; x += 8) { ToYCbCr(pixels, x, y, &b, &cb, &cr, rgbBytes); prevDCY = this.WriteBlock( QuantIndex.Luminance, prevDCY, &b, &temp1, &temp2, &onStackLuminanceQuantTable, unzig.Data); prevDCCb = this.WriteBlock( QuantIndex.Chrominance, prevDCCb, &cb, &temp1, &temp2, &onStackChrominanceQuantTable, unzig.Data); prevDCCr = this.WriteBlock( QuantIndex.Chrominance, prevDCCr, &cr, &temp1, &temp2, &onStackChrominanceQuantTable, unzig.Data); } } } }
public void FindIntersect() { var a = new PixelArea(new PixelCoordinate(0, 0), new PixelCoordinate(50, 100)); var b = new PixelArea(new PixelCoordinate(20, 30), new PixelCoordinate(100, 60)); var i = PixelArea.Intersect(a, b); i.Min.X.Should().Be(20); i.Min.Y.Should().Be(30); i.Max.X.Should().Be(50); i.Max.Y.Should().Be(60); }
public static void AddCropper(PipelineContext ctx, PixelArea area = default) { var crop = area.IsEmpty ? PixelArea.FromGdiRect(ctx.Settings.Crop).DeOrient(ctx.Orientation, ctx.Source.Width, ctx.Source.Height) : area; if (crop == ctx.Source.Area) { return; } ctx.Source = new CropTransform(ctx.Source, crop); }
public void CanCreateFilmTile() { var width = 800; var height = 600; var film = new Film(new PixelVector(width, height), new Bounds2D(new Point2D(0, 0), new Point2D(1, 1)), new MitchellFilter(new Vector2(2, 3), 0.25f, 0.5f), 10f, 1f); var tileArea = new PixelArea(0, 0, 200, 200); var tile = film.CreateFilmTile(in tileArea); tile.PixelBounds.Equals(new PixelArea(0, 0, 201, 202)).Should().BeTrue(); }
/// <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); } } }
private static void RenderToCanvas(PixelArea area, Canvas canvas, RenderPipeline pipeline, ISampler sampler) { for (var y = area.Min.Y; y < area.Max.Y; y++) { for (var x = area.Min.X; x < area.Max.X; x++) { var pixel = new PixelCoordinate(x, y); var c = pipeline.Capture(new PixelInformation(pixel, canvas.Width, canvas.Height), sampler); canvas.WritePixel(in c, pixel.X, pixel.Y); } } }
/// <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 (PixelArea <TColor, TPacked> row = new PixelArea <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); } } }
/// <summary> /// Copy a region of an image into dest. De "outlier" area will be stretched out with pixels on the right and bottom of the image. /// </summary> /// <typeparam name="TPixel">The pixel type</typeparam> /// <param name="pixels">The input pixel acessor</param> /// <param name="dest">The destination <see cref="PixelArea{TPixel}"/></param> /// <param name="sourceY">Starting Y coord</param> /// <param name="sourceX">Starting X coord</param> public static void CopyRGBBytesStretchedTo <TPixel>( this PixelAccessor <TPixel> pixels, PixelArea <TPixel> dest, int sourceY, int sourceX) where TPixel : struct, IPixel <TPixel> { pixels.SafeCopyTo(dest, sourceY, sourceX); int stretchFromX = pixels.Width - sourceX; int stretchFromY = pixels.Height - sourceY; StretchPixels(dest, stretchFromX, stretchFromY); }
private static void AssertSamePixels(PixelArea <Color, uint> data, int x1, int y1, int x2, int y2) { int idx1 = data.RowByteCount * y1 + x1 * 3; byte r1 = data.Bytes[idx1]; byte g1 = data.Bytes[idx1 + 1]; int idx2 = data.RowByteCount * y2 + x2 * 3; byte r2 = data.Bytes[idx2]; byte g2 = data.Bytes[idx2 + 1]; Assert.Equal(r1, r2); Assert.Equal(g1, g2); }
/// <summary> /// Copy a region of an image into dest. De "outlier" area will be stretched out with pixels on the right and bottom of the image. /// </summary> /// <typeparam name="TColor">The pixel type</typeparam> /// <param name="pixels">The input pixel acessor</param> /// <param name="dest">The destination <see cref="PixelArea{TColor}"/></param> /// <param name="sourceY">Starting Y coord</param> /// <param name="sourceX">Starting X coord</param> public static void CopyRGBBytesStretchedTo <TColor>( this PixelAccessor <TColor> pixels, PixelArea <TColor> dest, int sourceY, int sourceX) where TColor : struct, IPackedPixel, IEquatable <TColor> { pixels.SafeCopyTo(dest, sourceY, sourceX); int stretchFromX = pixels.Width - sourceX; int stretchFromY = pixels.Height - sourceY; StretchPixels(dest, stretchFromX, stretchFromY); }
public PadTransformInternal(PixelSource source, Color color, PixelArea innerArea, PixelArea outerArea, bool replay = false) : base(source) { if (Format.NumericRepresentation != PixelNumericRepresentation.UnsignedInteger || Format.ChannelCount != Format.BytesPerPixel) { throw new NotSupportedException("Pixel format not supported."); } fill = (uint)color.ToArgb(); passthrough = !replay; inner = innerArea; Width = outerArea.Width; Height = outerArea.Height; }
/// <summary> /// Reads the 24 bit color palette from the stream /// </summary> /// <typeparam name="TColor">The pixel format.</typeparam> /// <param name="pixels">The <see cref="PixelAccessor{TColor}"/> to assign the palette to.</param> /// <param name="width">The width of the bitmap.</param> /// <param name="height">The height of the bitmap.</param> /// <param name="inverted">Whether the bitmap is inverted.</param> private void ReadRgb24 <TColor>(PixelAccessor <TColor> pixels, int width, int height, bool inverted) where TColor : struct, IPackedPixel, IEquatable <TColor> { int padding = CalculatePadding(width, 3); using (PixelArea <TColor> row = new PixelArea <TColor>(width, ComponentOrder.Zyx, padding)) { for (int y = 0; y < height; y++) { row.Read(this.currentStream); int newY = Invert(y, height, inverted); pixels.CopyFrom(row, newY); } } }
/// <summary> /// Reads the 32 bit color palette from the stream /// </summary> /// <typeparam name="TPixel">The pixel format.</typeparam> /// <param name="pixels">The <see cref="PixelAccessor{TPixel}"/> to assign the palette to.</param> /// <param name="width">The width of the bitmap.</param> /// <param name="height">The height of the bitmap.</param> /// <param name="inverted">Whether the bitmap is inverted.</param> private void ReadRgb32 <TPixel>(PixelAccessor <TPixel> pixels, int width, int height, bool inverted) where TPixel : struct, IPixel <TPixel> { int padding = CalculatePadding(width, 4); using (PixelArea <TPixel> row = new PixelArea <TPixel>(width, ComponentOrder.Zyxw, padding)) { for (int y = 0; y < height; y++) { row.Read(this.currentStream); int newY = Invert(y, height, inverted); pixels.CopyFrom(row, newY); } } }
/// <summary> /// Converts the 8x8 region of the image whose top-left corner is x,y to its YCbCr values. /// </summary> /// <typeparam name="TColor">The pixel format.</typeparam> /// <param name="pixels">The pixel accessor.</param> /// <param name="x">The x-position within the image.</param> /// <param name="y">The y-position within the image.</param> /// <param name="yBlock">The luminance block.</param> /// <param name="cbBlock">The red chroma block.</param> /// <param name="crBlock">The blue chroma block.</param> /// <param name="rgbBytes">Temporal <see cref="PixelArea{TColor}"/> provided by the caller</param> private static void ToYCbCr <TColor>( PixelAccessor <TColor> pixels, int x, int y, Block8x8F *yBlock, Block8x8F *cbBlock, Block8x8F *crBlock, PixelArea <TColor> rgbBytes) where TColor : struct, IPixel <TColor> { float *yBlockRaw = (float *)yBlock; float *cbBlockRaw = (float *)cbBlock; float *crBlockRaw = (float *)crBlock; rgbBytes.Reset(); pixels.CopyRGBBytesStretchedTo(rgbBytes, y, x); ref byte data0 = ref rgbBytes.Bytes[0];
public void CopyStretchedRGBTo_FromOrigo <TPixel>(TestImageProvider <TPixel> provider) where TPixel : struct, IPixel <TPixel> { using (Image <TPixel> src = provider.GetImage()) using (Image <TPixel> dest = new Image <TPixel>(8, 8)) using (PixelArea <TPixel> area = new PixelArea <TPixel>(8, 8, ComponentOrder.Xyz)) using (PixelAccessor <TPixel> s = src.Lock()) using (PixelAccessor <TPixel> d = dest.Lock()) { s.CopyRGBBytesStretchedTo(area, 0, 0); d.CopyFrom(area, 0, 0); Assert.Equal(s[0, 0], d[0, 0]); Assert.Equal(s[7, 0], d[7, 0]); Assert.Equal(s[0, 7], d[0, 7]); Assert.Equal(s[7, 7], d[7, 7]); } }
private static void StretchPixels <TPixel>(PixelArea <TPixel> area, int fromX, int fromY) where TPixel : struct, IPixel <TPixel> { if (IsInvalidStretchStartingPosition(area, fromX, fromY)) { return; } for (int y = 0; y < fromY; y++) { ref RGB24 ptrBase = ref GetRowStart(area, y); for (int x = fromX; x < area.Width; x++) { // Copy the left neighbour pixel to the current one Unsafe.Add(ref ptrBase, x) = Unsafe.Add(ref ptrBase, x - 1); } }