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