|
|
|
@ -22,11 +22,6 @@ namespace ImageSharp.Formats |
|
|
|
/// </summary>
|
|
|
|
private const int QuantizationTableCount = 2; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Lookup tables for converting Rgb to YCbCr
|
|
|
|
/// </summary>
|
|
|
|
private static readonly RgbToYCbCrTables RgbToYCbCrTables = default(RgbToYCbCrTables).Init(); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Counts the number of bits needed to hold an integer.
|
|
|
|
/// </summary>
|
|
|
|
@ -106,6 +101,11 @@ namespace ImageSharp.Formats |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Lookup tables for converting Rgb to YCbCr
|
|
|
|
/// </summary>
|
|
|
|
private static RgbToYCbCrTables rgbToYCbCrTables = RgbToYCbCrTables.Create(); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// A scratch buffer to reduce allocations.
|
|
|
|
/// </summary>
|
|
|
|
@ -288,6 +288,7 @@ namespace ImageSharp.Formats |
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
|
|
/// <param name="pixels">The pixel accessor.</param>
|
|
|
|
/// <param name="tables">The reference to the tables instance.</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>
|
|
|
|
@ -296,6 +297,7 @@ namespace ImageSharp.Formats |
|
|
|
/// <param name="rgbBytes">Temporal <see cref="PixelArea{TPixel}"/> provided by the caller</param>
|
|
|
|
private static void ToYCbCr<TPixel>( |
|
|
|
PixelAccessor<TPixel> pixels, |
|
|
|
RgbToYCbCrTables* tables, |
|
|
|
int x, |
|
|
|
int y, |
|
|
|
Block8x8F* yBlock, |
|
|
|
@ -326,7 +328,7 @@ namespace ImageSharp.Formats |
|
|
|
|
|
|
|
int index = j8 + i; |
|
|
|
|
|
|
|
RgbToYCbCrTables.Allocate(ref yBlockRaw, ref cbBlockRaw, ref crBlockRaw, index, r, g, b); |
|
|
|
RgbToYCbCrTables.Allocate(ref yBlockRaw, ref cbBlockRaw, ref crBlockRaw, tables, index, r, g, b); |
|
|
|
|
|
|
|
dataIdx += 3; |
|
|
|
} |
|
|
|
@ -447,38 +449,41 @@ namespace ImageSharp.Formats |
|
|
|
// ReSharper disable once InconsistentNaming
|
|
|
|
int prevDCY = 0, prevDCCb = 0, prevDCCr = 0; |
|
|
|
|
|
|
|
using (PixelArea<TPixel> rgbBytes = new PixelArea<TPixel>(8, 8, ComponentOrder.Xyz)) |
|
|
|
fixed (RgbToYCbCrTables* tables = &rgbToYCbCrTables) |
|
|
|
{ |
|
|
|
for (int y = 0; y < pixels.Height; y += 8) |
|
|
|
using (PixelArea<TPixel> rgbBytes = new PixelArea<TPixel>(8, 8, ComponentOrder.Xyz)) |
|
|
|
{ |
|
|
|
for (int x = 0; x < pixels.Width; x += 8) |
|
|
|
for (int y = 0; y < pixels.Height; y += 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); |
|
|
|
for (int x = 0; x < pixels.Width; x += 8) |
|
|
|
{ |
|
|
|
ToYCbCr(pixels, tables, 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); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -820,49 +825,51 @@ namespace ImageSharp.Formats |
|
|
|
|
|
|
|
// ReSharper disable once InconsistentNaming
|
|
|
|
int prevDCY = 0, prevDCCb = 0, prevDCCr = 0; |
|
|
|
|
|
|
|
using (PixelArea<TPixel> rgbBytes = new PixelArea<TPixel>(8, 8, ComponentOrder.Xyz)) |
|
|
|
fixed (RgbToYCbCrTables* tables = &rgbToYCbCrTables) |
|
|
|
{ |
|
|
|
for (int y = 0; y < pixels.Height; y += 16) |
|
|
|
using (PixelArea<TPixel> rgbBytes = new PixelArea<TPixel>(8, 8, ComponentOrder.Xyz)) |
|
|
|
{ |
|
|
|
for (int x = 0; x < pixels.Width; x += 16) |
|
|
|
for (int y = 0; y < pixels.Height; y += 16) |
|
|
|
{ |
|
|
|
for (int i = 0; i < 4; i++) |
|
|
|
for (int x = 0; x < pixels.Width; x += 16) |
|
|
|
{ |
|
|
|
int xOff = (i & 1) * 8; |
|
|
|
int yOff = (i & 2) * 4; |
|
|
|
|
|
|
|
ToYCbCr(pixels, x + xOff, y + yOff, &b, cbPtr + i, crPtr + i, rgbBytes); |
|
|
|
for (int i = 0; i < 4; i++) |
|
|
|
{ |
|
|
|
int xOff = (i & 1) * 8; |
|
|
|
int yOff = (i & 2) * 4; |
|
|
|
|
|
|
|
ToYCbCr(pixels, tables, x + xOff, y + yOff, &b, cbPtr + i, crPtr + i, rgbBytes); |
|
|
|
|
|
|
|
prevDCY = this.WriteBlock( |
|
|
|
QuantIndex.Luminance, |
|
|
|
prevDCY, |
|
|
|
&b, |
|
|
|
&temp1, |
|
|
|
&temp2, |
|
|
|
&onStackLuminanceQuantTable, |
|
|
|
unzig.Data); |
|
|
|
} |
|
|
|
|
|
|
|
Block8x8F.Scale16X16To8X8(&b, cbPtr); |
|
|
|
prevDCCb = this.WriteBlock( |
|
|
|
QuantIndex.Chrominance, |
|
|
|
prevDCCb, |
|
|
|
&b, |
|
|
|
&temp1, |
|
|
|
&temp2, |
|
|
|
&onStackChrominanceQuantTable, |
|
|
|
unzig.Data); |
|
|
|
|
|
|
|
prevDCY = this.WriteBlock( |
|
|
|
QuantIndex.Luminance, |
|
|
|
prevDCY, |
|
|
|
Block8x8F.Scale16X16To8X8(&b, crPtr); |
|
|
|
prevDCCr = this.WriteBlock( |
|
|
|
QuantIndex.Chrominance, |
|
|
|
prevDCCr, |
|
|
|
&b, |
|
|
|
&temp1, |
|
|
|
&temp2, |
|
|
|
&onStackLuminanceQuantTable, |
|
|
|
&onStackChrominanceQuantTable, |
|
|
|
unzig.Data); |
|
|
|
} |
|
|
|
|
|
|
|
Block8x8F.Scale16X16To8X8(&b, cbPtr); |
|
|
|
prevDCCb = this.WriteBlock( |
|
|
|
QuantIndex.Chrominance, |
|
|
|
prevDCCb, |
|
|
|
&b, |
|
|
|
&temp1, |
|
|
|
&temp2, |
|
|
|
&onStackChrominanceQuantTable, |
|
|
|
unzig.Data); |
|
|
|
|
|
|
|
Block8x8F.Scale16X16To8X8(&b, crPtr); |
|
|
|
prevDCCr = this.WriteBlock( |
|
|
|
QuantIndex.Chrominance, |
|
|
|
prevDCCr, |
|
|
|
&b, |
|
|
|
&temp1, |
|
|
|
&temp2, |
|
|
|
&onStackChrominanceQuantTable, |
|
|
|
unzig.Data); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|