-
-
Notifications
You must be signed in to change notification settings - Fork 885
Jpeg encoder complete rewrite #2120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
JimBobSquarePants
merged 41 commits into
SixLabors:main
from
br3aker:dp/jpeg-encoder-color-conversion
Aug 11, 2022
Merged
Changes from all commits
Commits
Show all changes
41 commits
Select commit
Hold shift + click to select a range
96a3c19
Setup
45dfed1
RGB debug pass encoding done
ebdf4dd
Compilation fixes
0604a40
Implemented ycbcr/rgb/grayscale color converters
cad0ed0
Phase 1: prepare new encoder options API
fdb8b97
Implemented quantization and coding tables selectors
ccf664c
Implemented cmyk encoding
dfb2053
Removed precision parameter, removed YccK color space
74c9bb6
Moved color convertes to 'Components' folder
25ab5df
Implemented huffman table
ea81abc
Implemented quantization tables
dd3c3ec
Fixed sampling factors (hopefully)
3d31a16
Made frame configs internal
5d3dcc0
Implemented single component scan encoding
a5305ba
Removed obsolete code
7ece3dd
Quality property fix
fe5e3be
Fixed warnings, code cleanup
0c766a6
Small fixes
a83b3b6
Added avx accelerated rgb unpack method
23e3bb8
Fixed color converters
d6111d3
Imlemented avx accelerated subsampling
656482d
Optimization, new jpeg metadata fields
399a10c
Fixed color conversion
97dc60d
Implemented non-interleaved encoding
97f200d
Refactoring, fixes, tests
a7bea83
Implemented YccK encoding
dd0327a
Added docs to the color sonverters
503253e
Fixed scalar YccK conversion
893bc20
gfoidl review, removed obsolete enum
d351389
Removed redundant color converters creation, updated benchmarks
c6d127e
Added tests for different output color types (except ycck)
d1df701
Added tests for non-interleaved mode
c9b5e77
Fixed non-interleaved encoding with subsampling
dd504b2
Fixed spectral block border pixel padding
4a83e50
Merge branch 'main' into dp/jpeg-encoder-color-conversion
a9c7f4b
Merge fixes
2ee1913
shared-infrastructure
ade236e
Huffman table cleanup
4ab4ae2
Tests, fixed interleaved decoding I messed up during main merge
15e19c2
Removed obsolete external images
5d4fa11
Merge branch 'main' into dp/jpeg-encoder-color-conversion
JimBobSquarePants File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
159 changes: 159 additions & 0 deletions
159
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.ScaledCopy.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
// Copyright (c) Six Labors. | ||
// Licensed under the Six Labors Split License. | ||
|
||
using System.Numerics; | ||
using System.Runtime.CompilerServices; | ||
|
||
// ReSharper disable UseObjectOrCollectionInitializer | ||
// ReSharper disable InconsistentNaming | ||
namespace SixLabors.ImageSharp.Formats.Jpeg.Components | ||
{ | ||
internal partial struct Block8x8F | ||
{ | ||
[MethodImpl(InliningOptions.ShortMethod)] | ||
public void ScaledCopyFrom(ref float areaOrigin, int areaStride) => | ||
CopyFrom1x1Scale(ref Unsafe.As<float, byte>(ref areaOrigin), ref Unsafe.As<Block8x8F, byte>(ref this), areaStride); | ||
|
||
[MethodImpl(InliningOptions.ShortMethod)] | ||
public void ScaledCopyTo(ref float areaOrigin, int areaStride, int horizontalScale, int verticalScale) | ||
{ | ||
if (horizontalScale == 1 && verticalScale == 1) | ||
{ | ||
CopyTo1x1Scale(ref Unsafe.As<Block8x8F, byte>(ref this), ref Unsafe.As<float, byte>(ref areaOrigin), areaStride); | ||
return; | ||
} | ||
|
||
if (horizontalScale == 2 && verticalScale == 2) | ||
{ | ||
this.CopyTo2x2Scale(ref areaOrigin, areaStride); | ||
return; | ||
} | ||
|
||
// TODO: Optimize: implement all cases with scale-specific, loopless code! | ||
this.CopyArbitraryScale(ref areaOrigin, areaStride, horizontalScale, verticalScale); | ||
} | ||
|
||
private void CopyTo2x2Scale(ref float areaOrigin, int areaStride) | ||
{ | ||
ref Vector2 destBase = ref Unsafe.As<float, Vector2>(ref areaOrigin); | ||
int destStride = (int)((uint)areaStride / 2); | ||
|
||
WidenCopyRowImpl2x2(ref this.V0L, ref destBase, 0, destStride); | ||
WidenCopyRowImpl2x2(ref this.V0L, ref destBase, 1, destStride); | ||
WidenCopyRowImpl2x2(ref this.V0L, ref destBase, 2, destStride); | ||
WidenCopyRowImpl2x2(ref this.V0L, ref destBase, 3, destStride); | ||
WidenCopyRowImpl2x2(ref this.V0L, ref destBase, 4, destStride); | ||
WidenCopyRowImpl2x2(ref this.V0L, ref destBase, 5, destStride); | ||
WidenCopyRowImpl2x2(ref this.V0L, ref destBase, 6, destStride); | ||
WidenCopyRowImpl2x2(ref this.V0L, ref destBase, 7, destStride); | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
static void WidenCopyRowImpl2x2(ref Vector4 selfBase, ref Vector2 destBase, nint row, nint destStride) | ||
{ | ||
ref Vector4 sLeft = ref Unsafe.Add(ref selfBase, 2 * row); | ||
ref Vector4 sRight = ref Unsafe.Add(ref sLeft, 1); | ||
|
||
nint offset = 2 * row * destStride; | ||
ref Vector4 dTopLeft = ref Unsafe.As<Vector2, Vector4>(ref Unsafe.Add(ref destBase, offset)); | ||
ref Vector4 dBottomLeft = ref Unsafe.As<Vector2, Vector4>(ref Unsafe.Add(ref destBase, offset + destStride)); | ||
|
||
var xyLeft = new Vector4(sLeft.X); | ||
xyLeft.Z = sLeft.Y; | ||
xyLeft.W = sLeft.Y; | ||
|
||
var zwLeft = new Vector4(sLeft.Z); | ||
zwLeft.Z = sLeft.W; | ||
zwLeft.W = sLeft.W; | ||
|
||
var xyRight = new Vector4(sRight.X); | ||
xyRight.Z = sRight.Y; | ||
xyRight.W = sRight.Y; | ||
|
||
var zwRight = new Vector4(sRight.Z); | ||
zwRight.Z = sRight.W; | ||
zwRight.W = sRight.W; | ||
|
||
dTopLeft = xyLeft; | ||
Unsafe.Add(ref dTopLeft, 1) = zwLeft; | ||
Unsafe.Add(ref dTopLeft, 2) = xyRight; | ||
Unsafe.Add(ref dTopLeft, 3) = zwRight; | ||
|
||
dBottomLeft = xyLeft; | ||
Unsafe.Add(ref dBottomLeft, 1) = zwLeft; | ||
Unsafe.Add(ref dBottomLeft, 2) = xyRight; | ||
Unsafe.Add(ref dBottomLeft, 3) = zwRight; | ||
} | ||
} | ||
|
||
[MethodImpl(InliningOptions.ColdPath)] | ||
private void CopyArbitraryScale(ref float areaOrigin, int areaStride, int horizontalScale, int verticalScale) | ||
{ | ||
for (int y = 0; y < 8; y++) | ||
{ | ||
int yy = y * verticalScale; | ||
int y8 = y * 8; | ||
|
||
for (int x = 0; x < 8; x++) | ||
{ | ||
int xx = x * horizontalScale; | ||
|
||
float value = this[y8 + x]; | ||
nint baseIdx = (yy * areaStride) + xx; | ||
|
||
for (nint i = 0; i < verticalScale; i++, baseIdx += areaStride) | ||
{ | ||
for (nint j = 0; j < horizontalScale; j++) | ||
{ | ||
// area[xx + j, yy + i] = value; | ||
Unsafe.Add(ref areaOrigin, baseIdx + j) = value; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
private static void CopyTo1x1Scale(ref byte origin, ref byte dest, int areaStride) | ||
{ | ||
int destStride = areaStride * sizeof(float); | ||
|
||
CopyRowImpl(ref origin, ref dest, destStride, 0); | ||
CopyRowImpl(ref origin, ref dest, destStride, 1); | ||
CopyRowImpl(ref origin, ref dest, destStride, 2); | ||
CopyRowImpl(ref origin, ref dest, destStride, 3); | ||
CopyRowImpl(ref origin, ref dest, destStride, 4); | ||
CopyRowImpl(ref origin, ref dest, destStride, 5); | ||
CopyRowImpl(ref origin, ref dest, destStride, 6); | ||
CopyRowImpl(ref origin, ref dest, destStride, 7); | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
static void CopyRowImpl(ref byte origin, ref byte dest, int destStride, int row) | ||
{ | ||
origin = ref Unsafe.Add(ref origin, row * 8 * sizeof(float)); | ||
dest = ref Unsafe.Add(ref dest, row * destStride); | ||
Unsafe.CopyBlock(ref dest, ref origin, 8 * sizeof(float)); | ||
} | ||
} | ||
|
||
private static void CopyFrom1x1Scale(ref byte origin, ref byte dest, int areaStride) | ||
{ | ||
int destStride = areaStride * sizeof(float); | ||
|
||
CopyRowImpl(ref origin, ref dest, destStride, 0); | ||
CopyRowImpl(ref origin, ref dest, destStride, 1); | ||
CopyRowImpl(ref origin, ref dest, destStride, 2); | ||
CopyRowImpl(ref origin, ref dest, destStride, 3); | ||
CopyRowImpl(ref origin, ref dest, destStride, 4); | ||
CopyRowImpl(ref origin, ref dest, destStride, 5); | ||
CopyRowImpl(ref origin, ref dest, destStride, 6); | ||
CopyRowImpl(ref origin, ref dest, destStride, 7); | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
static void CopyRowImpl(ref byte origin, ref byte dest, int sourceStride, int row) | ||
{ | ||
origin = ref Unsafe.Add(ref origin, row * sourceStride); | ||
dest = ref Unsafe.Add(ref dest, row * 8 * sizeof(float)); | ||
Unsafe.CopyBlock(ref dest, ref origin, 8 * sizeof(float)); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.