mirror of https://github.com/SixLabors/ImageSharp
1 changed files with 91 additions and 0 deletions
@ -0,0 +1,91 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Buffers; |
|||
using System.Collections.Generic; |
|||
using System.Numerics; |
|||
using System.Text; |
|||
using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder |
|||
{ |
|||
internal abstract class SpectralConverter |
|||
{ |
|||
public abstract void ConvertStride(); |
|||
} |
|||
|
|||
internal class SpectralConverter<TPixel> : SpectralConverter |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
private Configuration configuration; |
|||
|
|||
private JpegComponentPostProcessor[] componentProcessors; |
|||
|
|||
private JpegColorConverter colorConverter; |
|||
|
|||
private IMemoryOwner<Vector4> rgbaBuffer; |
|||
|
|||
private Buffer2D<TPixel> pixelBuffer; |
|||
|
|||
public JpegFrame Frame |
|||
{ |
|||
set => this.InjectFrame(value); |
|||
} |
|||
|
|||
public SpectralConverter(Configuration configuration) |
|||
{ |
|||
this.configuration = configuration; |
|||
} |
|||
|
|||
private void InjectFrame(JpegFrame frame) |
|||
{ |
|||
MemoryAllocator allocator = this.configuration.MemoryAllocator; |
|||
|
|||
// pixel buffer for resulting image
|
|||
this.pixelBuffer = allocator.Allocate2D<TPixel>(frame.PixelWidth, frame.PixelHeight, AllocationOptions.Clean); |
|||
|
|||
// component processors from spectral to Rgba32
|
|||
this.componentProcessors = new JpegComponentPostProcessor[frame.Components.Length]; |
|||
for (int i = 0; i < this.componentProcessors.Length; i++) |
|||
{ |
|||
this.componentProcessors[i] = new JpegComponentPostProcessor(allocator, this, frame.Components[i]); |
|||
} |
|||
|
|||
// single 'stride' rgba32 buffer for conversion between spectral and TPixel
|
|||
this.rgbaBuffer = allocator.Allocate<Vector4>(frame.PixelWidth); |
|||
|
|||
// color converter from Rgba32 to TPixel
|
|||
this.colorConverter = JpegColorConverter.GetConverter(rawJpeg.ColorSpace, frame.Precision); |
|||
} |
|||
|
|||
public override void ConvertStride() |
|||
{ |
|||
int maxY = Math.Min(this.pixelBuffer.Height, this.PixelRowCounter + PixelRowsPerStep); |
|||
|
|||
var buffers = new Buffer2D<float>[this.componentProcessors.Length]; |
|||
for (int i = 0; i < this.componentProcessors.Length; i++) |
|||
{ |
|||
this.componentProcessors[i].CopyBlocksToColorBuffer(); |
|||
buffers[i] = this.componentProcessors[i].ColorBuffer; |
|||
} |
|||
|
|||
for (int yy = this.PixelRowCounter; yy < maxY; yy++) |
|||
{ |
|||
int y = yy - this.PixelRowCounter; |
|||
|
|||
var values = new JpegColorConverter.ComponentValues(buffers, y); |
|||
this.colorConverter.ConvertToRgba(values, this.rgbaBuffer.GetSpan()); |
|||
|
|||
Span<TPixel> destRow = destination.GetPixelRowSpan(yy); |
|||
|
|||
// TODO: Investigate if slicing is actually necessary
|
|||
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, this.rgbaBuffer.GetSpan().Slice(0, destRow.Length), destRow); |
|||
} |
|||
|
|||
this.PixelRowCounter += PixelRowsPerStep; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue