From 8c15954391c6454374ecee6af08c4e48d4349808 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 22 Feb 2018 13:31:41 +0100 Subject: [PATCH] YCbCrForwardConverter WIP --- .../Components/Encoder/RgbToYCbCrTables.cs | 58 ++++++++++++++++++- .../Jpeg/GolangPort/JpegEncoderCore.cs | 37 +++++++++--- .../Jpeg/GolangPort/Utils/OrigJpegUtils.cs | 11 ++++ 3 files changed, 95 insertions(+), 11 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/RgbToYCbCrTables.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/RgbToYCbCrTables.cs index 3c1d666850..01fe51c8d1 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/RgbToYCbCrTables.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/RgbToYCbCrTables.cs @@ -2,6 +2,10 @@ // Licensed under the Apache License, Version 2.0. using System.Runtime.CompilerServices; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Formats.Jpeg.Common; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Encoder { @@ -95,16 +99,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Encoder /// TODO: Replace this logic with SIMD conversion (similar to the one in the decoder)! /// Optimized method to allocates the correct y, cb, and cr values to the DCT blocks from the given r, g, b values. /// + /// The reference to the tables instance. /// The The luminance block. /// The red chroma block. /// The blue chroma block. - /// The reference to the tables instance. /// The current index. /// The red value. /// The green value. /// The blue value. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Rgb2YCbCr(float* yBlockRaw, float* cbBlockRaw, float* crBlockRaw, ref RgbToYCbCrTables* tables, int index, int r, int g, int b) + public static void Rgb2YCbCr(RgbToYCbCrTables* tables, float* yBlockRaw, float* cbBlockRaw, float* crBlockRaw, int index, int r, int g, int b) { // float y = (0.299F * r) + (0.587F * g) + (0.114F * b); yBlockRaw[index] = (tables->YRTable[r] + tables->YGTable[g] + tables->YBTable[b]) >> ScaleBits; @@ -116,6 +120,27 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Encoder crBlockRaw[index] = (tables->CbBTable[r] + tables->CrGTable[g] + tables->CrBTable[b]) >> ScaleBits; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ConvertPixelInto(int r, int g, int b, ref float yResult, ref float cbResult, ref float crResult) + { + ref int start = ref Unsafe.As(ref this); + + ref int yR = ref start; + ref int yG = ref Unsafe.Add(ref start, 256 * 1); + ref int yB = ref Unsafe.Add(ref start, 256 * 2); + + ref int cbR = ref Unsafe.Add(ref start, 256 * 3); + ref int cbG = ref Unsafe.Add(ref start, 256 * 4); + ref int cbB = ref Unsafe.Add(ref start, 256 * 5); + + ref int crG = ref Unsafe.Add(ref start, 256 * 6); + ref int crB = ref Unsafe.Add(ref start, 256 * 7); + + yResult = (Unsafe.Add(ref yR, r) + Unsafe.Add(ref yG, g) + Unsafe.Add(ref yB, b)) >> ScaleBits; + cbResult = (Unsafe.Add(ref cbR, r) + Unsafe.Add(ref cbG, g) + Unsafe.Add(ref cbB, b)) >> ScaleBits; + crResult = (Unsafe.Add(ref cbB, r) + Unsafe.Add(ref crG, g) + Unsafe.Add(ref crB, b)) >> ScaleBits; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int Fix(float x) { @@ -128,4 +153,33 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Encoder return x >> ScaleBits; } } + + // TODO! + internal struct YCbCrForwardConverter + where TPixel : struct, IPixel + { + public Block8x8F Y; + + public Block8x8F Cb; + + public Block8x8F Cr; + + private RgbToYCbCrTables colorTables; + + private GenericBlock8x8 pixelBlock; + + private GenericBlock8x8 rgbBlock; + + public static YCbCrForwardConverter Create() + { + var result = default(YCbCrForwardConverter); + result.colorTables = RgbToYCbCrTables.Create(); + return result; + } + + public void Convert(IPixelSource pixels, int x, int y) + { + + } + } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/JpegEncoderCore.cs index b03b0b5341..fcac30a2c8 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/JpegEncoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/JpegEncoderCore.cs @@ -303,15 +303,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort RgbToYCbCrTables* tables, int x, int y, - Block8x8F* yBlock, - Block8x8F* cbBlock, - Block8x8F* crBlock, + ref Block8x8F yBlock, + ref Block8x8F cbBlock, + ref Block8x8F crBlock, PixelArea rgbBytes) where TPixel : struct, IPixel { - float* yBlockRaw = (float*)yBlock; - float* cbBlockRaw = (float*)cbBlock; - float* crBlockRaw = (float*)crBlock; + ref float yBlockStart = ref Unsafe.As(ref yBlock); + ref float cbBlockStart = ref Unsafe.As(ref cbBlock); + ref float crBlockStart = ref Unsafe.As(ref crBlock); + + float* yBlockRaw = (float*) Unsafe.AsPointer(ref yBlock); + float* cbBlockRaw = (float*)Unsafe.AsPointer(ref cbBlock); + float* crBlockRaw = (float*)Unsafe.AsPointer(ref crBlock); rgbBytes.Reset(); pixels.CopyRGBBytesStretchedTo(rgbBytes, y, x); @@ -331,7 +335,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort int index = j8 + i; - RgbToYCbCrTables.Rgb2YCbCr(yBlockRaw, cbBlockRaw, crBlockRaw, ref tables, index, r, g, b); + RgbToYCbCrTables.Rgb2YCbCr(tables, yBlockRaw, cbBlockRaw, crBlockRaw, index, r, g, b); + //tables->ConvertPixelInto( + // r, + // g, + // b, + // ref Unsafe.Add(ref yBlockRaw, index), + // ref Unsafe.Add(ref cbBlockRaw, index), + // ref Unsafe.Add(ref crBlockRaw, index)); dataIdx += 3; } @@ -460,7 +471,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort { for (int x = 0; x < pixels.Width; x += 8) { - ToYCbCr(pixels, tables, x, y, &b, &cb, &cr, rgbBytes); + ToYCbCr(pixels, tables, x, y, ref b, ref cb, ref cr, rgbBytes); prevDCY = this.WriteBlock( QuantIndex.Luminance, @@ -920,7 +931,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort int xOff = (i & 1) * 8; int yOff = (i & 2) * 4; - ToYCbCr(pixels, tables, x + xOff, y + yOff, &b, cbPtr + i, crPtr + i, rgbBytes); + ToYCbCr( + pixels, + tables, + x + xOff, + y + yOff, + ref b, + ref Unsafe.AsRef(cbPtr + i), + ref Unsafe.AsRef(crPtr + i), + rgbBytes); prevDCY = this.WriteBlock( QuantIndex.Luminance, diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Utils/OrigJpegUtils.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Utils/OrigJpegUtils.cs index 42a7d56e3b..caa7014a4b 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Utils/OrigJpegUtils.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Utils/OrigJpegUtils.cs @@ -7,11 +7,22 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Utils { + using SixLabors.ImageSharp.Formats.Jpeg.Common; + /// /// Jpeg specific utilities and extension methods /// internal static class OrigJpegUtils { + /// + /// Stack only TPixel -> Rgb24 conversion method on 8x8 blocks. + /// + public static void ConvertToRgbUnsafe(ref GenericBlock8x8 source, ref GenericBlock8x8 dest) + where TPixel : struct, IPixel + { + PixelOperations.Instance.ToRgb24(source.AsSpanUnsafe(), dest.AsSpanUnsafe(), 64); + } + /// /// 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. ///