mirror of https://github.com/SixLabors/ImageSharp
7 changed files with 7 additions and 602 deletions
@ -1,19 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components |
|||
{ |
|||
[StructLayout(LayoutKind.Sequential)] |
|||
internal readonly struct FourByte |
|||
{ |
|||
public readonly byte X; |
|||
|
|||
public readonly byte Y; |
|||
|
|||
public readonly byte Z; |
|||
|
|||
public readonly byte W; |
|||
} |
|||
} |
|||
@ -1,142 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using SixLabors.ImageSharp.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a section of the jpeg component data laid out in pixel order.
|
|||
/// </summary>
|
|||
internal struct PdfJsJpegPixelArea : IDisposable |
|||
{ |
|||
private readonly MemoryManager memoryManager; |
|||
|
|||
private IBuffer<byte> componentData; |
|||
|
|||
private int rowStride; |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of components
|
|||
/// </summary>
|
|||
public int NumberOfComponents; |
|||
|
|||
/// <summary>
|
|||
/// Gets the width
|
|||
/// </summary>
|
|||
public int Width; |
|||
|
|||
/// <summary>
|
|||
/// Gets the height
|
|||
/// </summary>
|
|||
public int Height; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="PdfJsJpegPixelArea"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="memoryManager">The <see cref="MemoryManager"/> to use for buffer allocations.</param>
|
|||
/// <param name="imageWidth">The image width</param>
|
|||
/// <param name="imageHeight">The image height</param>
|
|||
/// <param name="numberOfComponents">The number of components</param>
|
|||
public PdfJsJpegPixelArea(MemoryManager memoryManager, int imageWidth, int imageHeight, int numberOfComponents) |
|||
{ |
|||
this.memoryManager = memoryManager; |
|||
this.Width = imageWidth; |
|||
this.Height = imageHeight; |
|||
this.NumberOfComponents = numberOfComponents; |
|||
this.componentData = null; |
|||
this.rowStride = this.Width * this.NumberOfComponents; |
|||
this.componentData = this.memoryManager.Allocate<byte>(this.Width * this.Height * this.NumberOfComponents); |
|||
} |
|||
|
|||
//// <summary>
|
|||
//// Organsizes the decoded jpeg components into a linear array ordered by component.
|
|||
//// This must be called before attempting to retrieve the data.
|
|||
//// </summary>
|
|||
//// <param name="components">The jpeg component blocks</param>
|
|||
// public void LinearizeBlockData(PdfJsComponentBlocks components)
|
|||
// {
|
|||
// ref byte componentDataRef = ref MemoryMarshal.GetReference(this.componentData.Span);
|
|||
// const uint Mask3Lsb = 0xFFFFFFF8; // Used to clear the 3 LSBs
|
|||
|
|||
// using (IBuffer<int> xScaleBlockOffset = this.memoryManager.Allocate<int>(this.Width))
|
|||
// {
|
|||
// ref int xScaleBlockOffsetRef = ref MemoryMarshal.GetReference(xScaleBlockOffset.Span);
|
|||
// int numberOfComponents = this.NumberOfComponents;
|
|||
// int width = this.Width;
|
|||
// int height = this.Height;
|
|||
//
|
|||
// for (int i = 0; i < numberOfComponents; i++)
|
|||
// {
|
|||
// ref PdfJsComponent component = ref components.Components[i];
|
|||
// ref short outputRef = ref MemoryMarshal.GetReference(component.Output.Span);
|
|||
// Vector2 componentScale = component.Scale;
|
|||
// float cX = componentScale.X;
|
|||
// float cY = componentScale.Y;
|
|||
// int blocksPerScanline = (component.BlocksPerLine + 1) << 3;
|
|||
//
|
|||
// // Precalculate the xScaleBlockOffset
|
|||
// int j;
|
|||
// for (int x = 0; x < width; x++)
|
|||
// {
|
|||
// j = (int)(x * cX);
|
|||
// Unsafe.Add(ref xScaleBlockOffsetRef, x) = (int)((j & Mask3Lsb) << 3) | (j & 7);
|
|||
// }
|
|||
//
|
|||
// // Linearize the blocks of the component
|
|||
// int offset = i;
|
|||
// for (int y = 0; y < height; y++)
|
|||
// {
|
|||
// j = (int)(y * cY);
|
|||
// int index = blocksPerScanline * (int)(j & Mask3Lsb) | ((j & 7) << 3);
|
|||
// for (int x = 0; x < width; x++)
|
|||
// {
|
|||
// Unsafe.Add(ref componentDataRef, offset) = (byte)Unsafe.Add(ref outputRef, index + Unsafe.Add(ref xScaleBlockOffsetRef, x));
|
|||
// offset += numberOfComponents;
|
|||
// }
|
|||
// }
|
|||
// }
|
|||
// }
|
|||
// }
|
|||
|
|||
/// <summary>
|
|||
/// Gets a <see cref="Span{Byte}"/> representing the row 'y' beginning from the the first byte on that row.
|
|||
/// </summary>
|
|||
/// <param name="y">The y-coordinate of the pixel row. Must be greater than or equal to zero and less than the height of the pixel area.</param>
|
|||
/// <returns>The <see cref="Span{TPixel}"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Span<byte> GetRowSpan(int y) |
|||
{ |
|||
this.CheckCoordinates(y); |
|||
return this.componentData.Slice(y * this.rowStride, this.rowStride); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public void Dispose() |
|||
{ |
|||
this.componentData?.Dispose(); |
|||
this.componentData = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Checks the coordinates to ensure they are within bounds.
|
|||
/// </summary>
|
|||
/// <param name="y">The y-coordinate of the row. Must be greater than zero and less than the height of the area.</param>
|
|||
/// <exception cref="ArgumentOutOfRangeException">
|
|||
/// Thrown if the coordinates are not within the bounds of the image.
|
|||
/// </exception>
|
|||
[Conditional("DEBUG")] |
|||
private void CheckCoordinates(int y) |
|||
{ |
|||
if (y < 0 || y >= this.Height) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(nameof(y), y, $"{y} is outwith the area bounds."); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,131 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components |
|||
{ |
|||
/// <summary>
|
|||
/// Provides 8-bit lookup tables for converting from YCbCr to Rgb colorspace.
|
|||
/// Methods to build the tables are based on libjpeg implementation.
|
|||
/// </summary>
|
|||
internal readonly struct PdfJsYCbCrToRgbTables |
|||
{ |
|||
/// <summary>
|
|||
/// The red red-chrominance table
|
|||
/// </summary>
|
|||
public static int[] CrRTable = new int[256]; |
|||
|
|||
/// <summary>
|
|||
/// The blue blue-chrominance table
|
|||
/// </summary>
|
|||
public static int[] CbBTable = new int[256]; |
|||
|
|||
/// <summary>
|
|||
/// The green red-chrominance table
|
|||
/// </summary>
|
|||
public static int[] CrGTable = new int[256]; |
|||
|
|||
/// <summary>
|
|||
/// The green blue-chrominance table
|
|||
/// </summary>
|
|||
public static int[] CbGTable = new int[256]; |
|||
|
|||
// Speediest right-shift on some machines and gives us enough accuracy at 4 decimal places.
|
|||
private const int ScaleBits = 16; |
|||
|
|||
private const int Half = 1 << (ScaleBits - 1); |
|||
|
|||
private const int MinSample = 0; |
|||
|
|||
private const int HalfSample = 128; |
|||
|
|||
private const int MaxSample = 255; |
|||
|
|||
/// <summary>
|
|||
/// Initializes the YCbCr tables
|
|||
/// </summary>
|
|||
public static void Create() |
|||
{ |
|||
for (int i = 0, x = -128; i <= 255; i++, x++) |
|||
{ |
|||
// i is the actual input pixel value, in the range 0..255
|
|||
// The Cb or Cr value we are thinking of is x = i - 128
|
|||
// Cr=>R value is nearest int to 1.402 * x
|
|||
CrRTable[i] = RightShift((Fix(1.402F) * x) + Half); |
|||
|
|||
// Cb=>B value is nearest int to 1.772 * x
|
|||
CbBTable[i] = RightShift((Fix(1.772F) * x) + Half); |
|||
|
|||
// Cr=>G value is scaled-up -0.714136286
|
|||
CrGTable[i] = (-Fix(0.714136286F)) * x; |
|||
|
|||
// Cb => G value is scaled - up - 0.344136286 * x
|
|||
// We also add in Half so that need not do it in inner loop
|
|||
CbGTable[i] = ((-Fix(0.344136286F)) * x) + Half; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Optimized method to pack bytes to the image from the YCbCr color space.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="packed">The packed pixel.</param>
|
|||
/// <param name="y">The y luminance component.</param>
|
|||
/// <param name="cb">The cb chroma component.</param>
|
|||
/// <param name="cr">The cr chroma component.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void PackYCbCr<TPixel>(ref TPixel packed, byte y, byte cb, byte cr) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
byte r = (byte)(y + CrRTable[cr]).Clamp(0, 255); |
|||
|
|||
// The values for the G calculation are left scaled up, since we must add them together before rounding.
|
|||
byte g = (byte)(y + RightShift(CbGTable[cb] + CrGTable[cr])).Clamp(0, 255); |
|||
|
|||
byte b = (byte)(y + CbBTable[cb]).Clamp(0, 255); |
|||
|
|||
packed.PackFromRgba32(new Rgba32(r, g, b, 255)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Optimized method to pack bytes to the image from the YccK color space.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="packed">The packed pixel.</param>
|
|||
/// <param name="y">The y luminance component.</param>
|
|||
/// <param name="cb">The cb chroma component.</param>
|
|||
/// <param name="cr">The cr chroma component.</param>
|
|||
/// <param name="k">The keyline component.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void PackYccK<TPixel>(ref TPixel packed, byte y, byte cb, byte cr, byte k) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
int c = (MaxSample - (y + CrRTable[cr])).Clamp(0, 255); |
|||
|
|||
// The values for the G calculation are left scaled up, since we must add them together before rounding.
|
|||
int m = (MaxSample - (y + RightShift(CbGTable[cb] + CrGTable[cr]))).Clamp(0, 255); |
|||
|
|||
int cy = (MaxSample - (y + CbBTable[cb])).Clamp(0, 255); |
|||
|
|||
byte r = (byte)((c * k) / MaxSample); |
|||
byte g = (byte)((m * k) / MaxSample); |
|||
byte b = (byte)((cy * k) / MaxSample); |
|||
|
|||
packed.PackFromRgba32(new Rgba32(r, g, b, MaxSample)); |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static int Fix(float x) |
|||
{ |
|||
return (int)((x * (1L << ScaleBits)) + 0.5F); |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static int RightShift(int x) |
|||
{ |
|||
return x >> ScaleBits; |
|||
} |
|||
} |
|||
} |
|||
@ -1,17 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components |
|||
{ |
|||
[StructLayout(LayoutKind.Sequential)] |
|||
internal readonly struct ThreeByte |
|||
{ |
|||
public readonly byte X; |
|||
|
|||
public readonly byte Y; |
|||
|
|||
public readonly byte Z; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue