mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Former-commit-id: 89550ed1243331a85c00f315dc8cd4c06b14ae9c Former-commit-id: 8d15dd77d84254cb59154322736904f05a434875 Former-commit-id: 219c0fd3b6925bde6cac1323b17bad9a857ec56daf/merge-core
11 changed files with 502 additions and 2 deletions
@ -0,0 +1,31 @@ |
|||
// <copyright file="Bits.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessorCore.Formats |
|||
{ |
|||
/// <summary>
|
|||
/// Holds the unprocessed bits that have been taken from the byte-stream.
|
|||
/// The n least significant bits of a form the unread bits, to be read in MSB to
|
|||
/// LSB order.
|
|||
/// </summary>
|
|||
internal class Bits |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets the accumulator.
|
|||
/// </summary>
|
|||
public uint Accumulator { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the mask.
|
|||
/// <![CDATA[mask==1<<(unreadbits-1) when unreadbits>0, with mask==0 when unreadbits==0.]]>
|
|||
/// </summary>
|
|||
public uint Mask { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the number of unread bits in the accumulator.
|
|||
/// </summary>
|
|||
public int UnreadBits { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
// <copyright file="Bytes.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessorCore.Formats |
|||
{ |
|||
/// <summary>
|
|||
/// Bytes is a byte buffer, similar to a stream, except that it
|
|||
/// has to be able to unread more than 1 byte, due to byte stuffing.
|
|||
/// Byte stuffing is specified in section F.1.2.3.
|
|||
/// </summary>
|
|||
internal class Bytes |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Bytes"/> class.
|
|||
/// </summary>
|
|||
public Bytes() |
|||
{ |
|||
this.Buffer = new byte[4096]; |
|||
this.I = 0; |
|||
this.J = 0; |
|||
this.UnreadableBytes = 0; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the buffer.
|
|||
/// buffer[i:j] are the buffered bytes read from the underlying
|
|||
/// stream that haven't yet been passed further on.
|
|||
/// </summary>
|
|||
public byte[] Buffer { get; set; } |
|||
|
|||
public int I { get; set; } |
|||
|
|||
public int J { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the unreadable bytes. The number of bytes to back up i after
|
|||
/// overshooting. It can be 0, 1 or 2.
|
|||
/// </summary>
|
|||
public int UnreadableBytes { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
// <copyright file="Component.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessorCore.Formats |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a single color component
|
|||
/// </summary>
|
|||
internal class Component |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets the horizontal sampling factor.
|
|||
/// </summary>
|
|||
public int HorizontalFactor { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the vertical sampling factor.
|
|||
/// </summary>
|
|||
public int VerticalFactor { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the identifier
|
|||
/// </summary>
|
|||
public byte Identifier { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the quantization table destination selector.
|
|||
/// </summary>
|
|||
public byte Selector { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,101 @@ |
|||
// <copyright file="GrayImage.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessorCore.Formats |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a grayscale image
|
|||
/// </summary>
|
|||
internal class GrayImage |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="GrayImage"/> class.
|
|||
/// </summary>
|
|||
/// <param name="width">The width.</param>
|
|||
/// <param name="height">The height.</param>
|
|||
public GrayImage(int width, int height) |
|||
{ |
|||
this.Width = width; |
|||
this.Height = height; |
|||
this.Pixels = new byte[width * height]; |
|||
this.Stride = width; |
|||
this.Offset = 0; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Prevents a default instance of the <see cref="GrayImage"/> class from being created.
|
|||
/// </summary>
|
|||
private GrayImage() |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the pixels.
|
|||
/// </summary>
|
|||
public byte[] Pixels { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the stride.
|
|||
/// </summary>
|
|||
public int Stride { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the horizontal position.
|
|||
/// </summary>
|
|||
public int X { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the vertical position.
|
|||
/// </summary>
|
|||
public int Y { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the width.
|
|||
/// </summary>
|
|||
public int Width { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the height.
|
|||
/// </summary>
|
|||
public int Height { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the offset
|
|||
/// </summary>
|
|||
public int Offset { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets an image made up of a subset of the originals pixels.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-coordinate of the image.</param>
|
|||
/// <param name="y">The y-coordinate of the image.</param>
|
|||
/// <param name="width">The width.</param>
|
|||
/// <param name="height">The height.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="GrayImage"/>.
|
|||
/// </returns>
|
|||
public GrayImage Subimage(int x, int y, int width, int height) |
|||
{ |
|||
return new GrayImage |
|||
{ |
|||
Width = width, |
|||
Height = height, |
|||
Pixels = this.Pixels, |
|||
Stride = this.Stride, |
|||
Offset = (y * this.Stride) + x |
|||
}; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the row offset at the given position
|
|||
/// </summary>
|
|||
/// <param name="y">The y-coordinate of the image.</param>
|
|||
/// <returns>The <see cref="int"/></returns>
|
|||
public int GetRowOffset(int y) |
|||
{ |
|||
return this.Offset + (y * this.Stride); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
// <copyright file="Huffman.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessorCore.Formats |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a Huffman tree
|
|||
/// </summary>
|
|||
internal class Huffman |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Huffman"/> class.
|
|||
/// </summary>
|
|||
/// <param name="lutSize">The log-2 size of the Huffman decoder's look-up table.</param>
|
|||
/// <param name="maxNCodes">The maximum (inclusive) number of codes in a Huffman tree.</param>
|
|||
/// <param name="maxCodeLength">The maximum (inclusive) number of bits in a Huffman code.</param>
|
|||
public Huffman(int lutSize, int maxNCodes, int maxCodeLength) |
|||
{ |
|||
this.Lut = new ushort[1 << lutSize]; |
|||
this.Values = new byte[maxNCodes]; |
|||
this.MinCodes = new int[maxCodeLength]; |
|||
this.MaxCodes = new int[maxCodeLength]; |
|||
this.Indices = new int[maxCodeLength]; |
|||
this.Length = 0; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the number of codes in the tree.
|
|||
/// </summary>
|
|||
public int Length { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the look-up table for the next LutSize bits in the bit-stream.
|
|||
/// The high 8 bits of the uint16 are the encoded value. The low 8 bits
|
|||
/// are 1 plus the code length, or 0 if the value is too large to fit in
|
|||
/// lutSize bits.
|
|||
/// </summary>
|
|||
public ushort[] Lut { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the the decoded values, sorted by their encoding.
|
|||
/// </summary>
|
|||
public byte[] Values { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the array of minimum codes.
|
|||
/// MinCodes[i] is the minimum code of length i, or -1 if there are no codes of that length.
|
|||
/// </summary>
|
|||
public int[] MinCodes { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the array of maximum codes.
|
|||
/// MaxCodes[i] is the maximum code of length i, or -1 if there are no codes of that length.
|
|||
/// </summary>
|
|||
public int[] MaxCodes { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the array of indices. Indices[i] is the index into Values of MinCodes[i].
|
|||
/// </summary>
|
|||
public int[] Indices { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,228 @@ |
|||
// <copyright file="YCbCrImage.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessorCore.Formats |
|||
{ |
|||
/// <summary>
|
|||
/// Represents an image made up of three color components (luminance, blue chroma, red chroma)
|
|||
/// </summary>
|
|||
internal class YCbCrImage |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="YCbCrImage"/> class.
|
|||
/// </summary>
|
|||
/// <param name="width">The width.</param>
|
|||
/// <param name="height">The height.</param>
|
|||
/// <param name="ratio">The ratio.</param>
|
|||
public YCbCrImage(int width, int height, YCbCrSubsampleRatio ratio) |
|||
{ |
|||
int cw, ch; |
|||
YCbCrSize(width, height, ratio, out cw, out ch); |
|||
this.YChannel = new byte[width * height]; |
|||
this.CbChannel = new byte[cw * ch]; |
|||
this.CrChannel = new byte[cw * ch]; |
|||
this.Ratio = ratio; |
|||
this.YStride = width; |
|||
this.CStride = cw; |
|||
this.X = 0; |
|||
this.Y = 0; |
|||
this.Width = width; |
|||
this.Height = height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Prevents a default instance of the <see cref="YCbCrImage"/> class from being created.
|
|||
/// </summary>
|
|||
private YCbCrImage() |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Provides enumeration of the various available subsample ratios.
|
|||
/// </summary>
|
|||
public enum YCbCrSubsampleRatio |
|||
{ |
|||
YCbCrSubsampleRatio444, |
|||
|
|||
YCbCrSubsampleRatio422, |
|||
|
|||
YCbCrSubsampleRatio420, |
|||
|
|||
YCbCrSubsampleRatio440, |
|||
|
|||
YCbCrSubsampleRatio411, |
|||
|
|||
YCbCrSubsampleRatio410, |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the luminance components channel.
|
|||
/// </summary>
|
|||
public byte[] YChannel { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the blue chroma components channel.
|
|||
/// </summary>
|
|||
public byte[] CbChannel { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the red chroma components channel.
|
|||
/// </summary>
|
|||
public byte[] CrChannel { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the Y slice index delta between vertically adjacent pixels.
|
|||
/// </summary>
|
|||
public int YStride { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the red and blue chroma slice index delta between vertically adjacent pixels
|
|||
/// that map to separate chroma samples.
|
|||
/// </summary>
|
|||
public int CStride { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the index of the first luminance element.
|
|||
/// </summary>
|
|||
public int YOffset { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the index of the first element of red or blue chroma.
|
|||
/// </summary>
|
|||
public int COffset { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the horizontal position.
|
|||
/// </summary>
|
|||
public int X { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the vertical position.
|
|||
/// </summary>
|
|||
public int Y { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the width.
|
|||
/// </summary>
|
|||
public int Width { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the height.
|
|||
/// </summary>
|
|||
public int Height { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the subsampling ratio.
|
|||
/// </summary>
|
|||
public YCbCrSubsampleRatio Ratio { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets an image made up of a subset of the originals pixels.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-coordinate of the image.</param>
|
|||
/// <param name="y">The y-coordinate of the image.</param>
|
|||
/// <param name="width">The width.</param>
|
|||
/// <param name="height">The height.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="YCbCrImage"/>.
|
|||
/// </returns>
|
|||
public YCbCrImage Subimage(int x, int y, int width, int height) |
|||
{ |
|||
YCbCrImage ret = new YCbCrImage |
|||
{ |
|||
Width = width, |
|||
Height = height, |
|||
YChannel = this.YChannel, |
|||
CbChannel = this.CbChannel, |
|||
CrChannel = this.CrChannel, |
|||
Ratio = this.Ratio, |
|||
YStride = this.YStride, |
|||
CStride = this.CStride, |
|||
YOffset = (y * this.YStride) + x, |
|||
COffset = (y * this.CStride) + x |
|||
}; |
|||
return ret; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the offset of the first luminance component at the given row
|
|||
/// </summary>
|
|||
/// <param name="y">The row number.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="int"/>.
|
|||
/// </returns>
|
|||
public int GetRowYOffset(int y) |
|||
{ |
|||
return y * this.YStride; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the offset of the first chroma component at the given row
|
|||
/// </summary>
|
|||
/// <param name="y">The row number.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="int"/>.
|
|||
/// </returns>
|
|||
public int GetRowCOffset(int y) |
|||
{ |
|||
switch (this.Ratio) |
|||
{ |
|||
case YCbCrSubsampleRatio.YCbCrSubsampleRatio422: |
|||
return y * this.CStride; |
|||
case YCbCrSubsampleRatio.YCbCrSubsampleRatio420: |
|||
return (y / 2) * this.CStride; |
|||
case YCbCrSubsampleRatio.YCbCrSubsampleRatio440: |
|||
return (y / 2) * this.CStride; |
|||
case YCbCrSubsampleRatio.YCbCrSubsampleRatio411: |
|||
return y * this.CStride; |
|||
case YCbCrSubsampleRatio.YCbCrSubsampleRatio410: |
|||
return (y / 2) * this.CStride; |
|||
default: |
|||
return y * this.CStride; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the height and width of the chroma components
|
|||
/// </summary>
|
|||
/// <param name="width">The width.</param>
|
|||
/// <param name="height">The height.</param>
|
|||
/// <param name="ratio">The subsampling ratio.</param>
|
|||
/// <param name="chromaWidth">The chroma width.</param>
|
|||
/// <param name="chromaHeight">The chroma height.</param>
|
|||
private static void YCbCrSize(int width, int height, YCbCrSubsampleRatio ratio, out int chromaWidth, out int chromaHeight) |
|||
{ |
|||
switch (ratio) |
|||
{ |
|||
case YCbCrSubsampleRatio.YCbCrSubsampleRatio422: |
|||
chromaWidth = (width + 1) / 2; |
|||
chromaHeight = height; |
|||
break; |
|||
case YCbCrSubsampleRatio.YCbCrSubsampleRatio420: |
|||
chromaWidth = (width + 1) / 2; |
|||
chromaHeight = (height + 1) / 2; |
|||
break; |
|||
case YCbCrSubsampleRatio.YCbCrSubsampleRatio440: |
|||
chromaWidth = width; |
|||
chromaHeight = (height + 1) / 2; |
|||
break; |
|||
case YCbCrSubsampleRatio.YCbCrSubsampleRatio411: |
|||
chromaWidth = (width + 3) / 4; |
|||
chromaHeight = height; |
|||
break; |
|||
case YCbCrSubsampleRatio.YCbCrSubsampleRatio410: |
|||
chromaWidth = (width + 3) / 4; |
|||
chromaHeight = (height + 1) / 2; |
|||
break; |
|||
default: |
|||
|
|||
// Default to 4:4:4 subsampling.
|
|||
chromaWidth = width; |
|||
chromaHeight = height; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1 +1 @@ |
|||
efdc36c9d84d1fd42bf3b1e722946bccef95db1c |
|||
8ce31914f581080b90c50b6a6529db20a29e7551 |
|||
Loading…
Reference in new issue