|
|
|
@ -201,6 +201,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg |
|
|
|
{ |
|
|
|
Guard.NotNull(image, nameof(image)); |
|
|
|
Guard.NotNull(stream, nameof(stream)); |
|
|
|
cancellationToken.ThrowIfCancellationRequested(); |
|
|
|
|
|
|
|
const ushort max = JpegConstants.MaxLength; |
|
|
|
if (image.Width >= max || image.Height >= max) |
|
|
|
@ -249,7 +250,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg |
|
|
|
this.WriteDefineHuffmanTables(componentCount); |
|
|
|
|
|
|
|
// Write the image data.
|
|
|
|
this.WriteStartOfScan(image); |
|
|
|
this.WriteStartOfScan(image, cancellationToken); |
|
|
|
|
|
|
|
// Write the End Of Image marker.
|
|
|
|
this.buffer[0] = JpegConstants.Markers.XFF; |
|
|
|
@ -398,7 +399,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg |
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
|
|
/// <param name="pixels">The pixel accessor providing access to the image pixels.</param>
|
|
|
|
private void Encode444<TPixel>(Image<TPixel> pixels) |
|
|
|
/// <param name="cancellationToken">The token to monitor for cancellation.</param>
|
|
|
|
private void Encode444<TPixel>(Image<TPixel> pixels, CancellationToken cancellationToken) |
|
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
|
{ |
|
|
|
// TODO: Need a JpegScanEncoder<TPixel> class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.)
|
|
|
|
@ -420,6 +422,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg |
|
|
|
|
|
|
|
for (int y = 0; y < pixels.Height; y += 8) |
|
|
|
{ |
|
|
|
cancellationToken.ThrowIfCancellationRequested(); |
|
|
|
var currentRows = new RowOctet<TPixel>(pixelBuffer, y); |
|
|
|
|
|
|
|
for (int x = 0; x < pixels.Width; x += 8) |
|
|
|
@ -945,7 +948,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg |
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
|
|
/// <param name="image">The pixel accessor providing access to the image pixels.</param>
|
|
|
|
private void WriteStartOfScan<TPixel>(Image<TPixel> image) |
|
|
|
/// <param name="cancellationToken">The token to monitor for cancellation.</param>
|
|
|
|
private void WriteStartOfScan<TPixel>(Image<TPixel> image, CancellationToken cancellationToken) |
|
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
|
{ |
|
|
|
// TODO: Need a JpegScanEncoder<TPixel> class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.)
|
|
|
|
@ -955,10 +959,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg |
|
|
|
switch (this.subsample) |
|
|
|
{ |
|
|
|
case JpegSubsample.Ratio444: |
|
|
|
this.Encode444(image); |
|
|
|
this.Encode444(image, cancellationToken); |
|
|
|
break; |
|
|
|
case JpegSubsample.Ratio420: |
|
|
|
this.Encode420(image); |
|
|
|
this.Encode420(image, cancellationToken); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
@ -972,7 +976,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg |
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
|
|
/// <param name="pixels">The pixel accessor providing access to the image pixels.</param>
|
|
|
|
private void Encode420<TPixel>(Image<TPixel> pixels) |
|
|
|
/// <param name="cancellationToken">The token to monitor for cancellation.</param>
|
|
|
|
private void Encode420<TPixel>(Image<TPixel> pixels, CancellationToken cancellationToken) |
|
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
|
{ |
|
|
|
// TODO: Need a JpegScanEncoder<TPixel> class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.)
|
|
|
|
@ -1000,6 +1005,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg |
|
|
|
|
|
|
|
for (int y = 0; y < pixels.Height; y += 16) |
|
|
|
{ |
|
|
|
cancellationToken.ThrowIfCancellationRequested(); |
|
|
|
for (int x = 0; x < pixels.Width; x += 16) |
|
|
|
{ |
|
|
|
for (int i = 0; i < 4; i++) |
|
|
|
|