Repository navigation
Support for JPEG XL (JXL) images - #3153
winscripter wants to merge 223 commits into
Conversation
Implementation of ac_strategy.h and ac_strategy.c
For now JxlMemoryManager will be a wrapper around MemoryPool<T>.
Implementation of image.h and image.c; AC strategy implementation was slightly adjusted to reduce errors.
This is an implementation of field_encodings.h. Note that I avoided implementing EnumValid() and Values() functions, as we have dedicated methods in .NET to do exactly that (Enum.IsDefined, Enum.GetValues)
Implementation of spline.h
Implemented ANS constants
|
While I'm working on this, I'd like to note something important. Libjxl is licensed under the BSD 3-Clause license, and since I'm using libjxl code as reference, that means the license must be included. I'm not really sure what would be the proper way to include the license. I might place the LICENSE.txt file in the Jxl folder or add a README linking to the libjxl repo. |
See ans_common.h
It is too large for a struct.
See ans_common.h
Add JxlAnsEntry and JxlAnsSymbol. See ans_common.h. These correspond to the Entry and Symbol structures within AliasTable.
Currently, there's a VarLenUint8/VarLenUint16 as well as histogram parsing implementation. I will additionally have to implement parsing of ANS codes, uint config and LZ77 parameters.
…dd tone mapping stage, add entropy encoder, add performance optimizations
| #pragma warning disable IDE1006 // Naming Styles | ||
| #pragma warning disable SA1307 // Accessible fields should begin with upper-case letter |
There was a problem hiding this comment.
Why suppress and don't fix?
| Span<int> countsSpan = CollectionsMarshal.AsSpan(a.Counts); | ||
| ref int countsRef = ref MemoryMarshal.GetReference(countsSpan); | ||
|
|
||
| for (int i = 0; i < countsSpan.Length; i += Vector<int>.Count) |
There was a problem hiding this comment.
Please have a look at all of these loops, I won't comment them to avoid some noise.
They may work by accident, as the input is won't make it happen, but this is a clear bug.
There was a problem hiding this comment.
libjxl uses SIMD through its Google Highway library, which has an API that's extremely similar to .NET. Interestingly, the reference implementation itself contains loops that advance by the SIMD lane count without explicitly handling a potentially incomplete final vector.
For example, this is the C++ reference of the highlighted function:
for (size_t i = 0; i < a.counts.size(); i += Lanes(di)) {
const auto counts = LoadU(di, &a.counts[i]);
const bool nz = !AllTrue(di, Eq(counts, kZero));
total = Add(total, counts);
if (nz) nz_pos = i;
}a.counts.size()-.countsis astd::vector<T>, so.size()is just number of items in it ->countsSpan.Length- Lanes(di) -
diis the definition for integer vector types, so when it's used it refers toVector<int>. Lanes() is the number of items a CPU can process in the vector of that type at once ->Vector<int>.Count
There is potential for bug here too, but it seems like that was expected.
I would still apply these fixes, but there are so many instances of this pattern that it's easy to overlook some when fixing them individually.
| /// We may need to get a ref to this field, so make this | ||
| /// public. | ||
| /// </summary> | ||
| public byte[] ContextMap = new byte[DefaultContextMap.Length]; |
There was a problem hiding this comment.
Can this be an inline array? The size is known at compile time, and it's not too big.
So maybe something like
private InlineArray... _contextMap;
public Span<byte> ContextMap => _contextMap;|
@winscripter I've finished AVIF. I should be able to switch focus and help sometime next week. |
|
@JimBobSquarePants Good job! 🎉 For JPEG XL, I've done an incredibly substantial amount of work. Out of 115866 LoC in reference software, only 43966 lines remain to be ported (including unit tests; without unit tests, it's ~18k). Currently in progress of porting simple functions and working on LZ77/AC Strategy encoder. Your help would be greatly appreciated! |
You’re a legend!! |
Expanded AC strategy encoder, added ANS encoder prototype with StoreVarLenUIntX (X=8,16), added prototype of CfL encoder, added LZ77 hash chain, added modular SIMD, patch colorspace info, frame encoder basic functions, expanded heuristics
|
So it looks like I'll have to port an external library that JPEG-XL uses, and this will take some time. JPEG-XL's color management system (CMS) relies on an external C/C++ library. It supports either lcms2 or skcms, and they can be configured with its preprocessor directives in its build system. That means I'll have to port one of the two depending on what I'll go with. I'm choosing to go with skcms. Lcms2 is more feature rich and libjxl only uses a fraction of it, while skcms is Google's own Skia CMS library that's only around 5k LoC and much easier to port. Skcms is also more focused on correctness. |
…omTransformData inline array fields public, remove unnecessary usings from noise decoder, document JxlAnsHelper
|
@winscripter please do not worry about conflicts at the moment. I’ve just merged the AVIF code and am following up with another PR that I’ve already started which contains ICC writing and bulk pixel format API changes. I’ll handle the merge from main in a couple of days max. Note this means you will not need to port any CMS. |
Prerequisites
Description
This is a work-in-progress PR whose goal is to introduce decoding and encoding of JPEG XL (*.jxl) images.
Reference software
I use libjxl as reference. See https://github.com/libjxl/libjxl.
Performance
I will begin by applying light optimizations as I implement parts of the JPEG XL codec. Once the codec seems complete enough to handle decoding and encoding of JPEG XL images, I will apply heavier optimizations. Examples include but are not limited to stack allocation, array pooling, and SIMD.
Implementations
The JPEG XL codec lives under
src/ImageSharp/Formats/Jxl.Testing
I will start adding tests whenever the codec is complete enough to handle decoding of JPEG XL images.
Additionally, JPEG XL reference software, libjxl, contains its own tests too, which I might also implement without modification.
Progress
🟡 AC strategy
🟢 AC strategy image/row
🟢 AC context
🔴 AC strategy tests
🟢 Adaptive Quantization (encoder)
🟡 ANS Entropy
🟢 ANS Entropy: Common
🟢 ANS Entropy: Common (Tests)
🟢 ANS Entropy: Decoder
🟠 ANS Entropy: Encoder (SIMD bit-cost calculation only)
🔴 ANS Entropy: Tests
🟢 Alpha Blending
🟡 Bit I/O
🟢 Bit I/O: Bit reader
🟢 Bit I/O: Bit writer
🔴 Bit I/O: tests
🟢 Box Content Decoder
🟢 Box Content Decoder: Uncompressed boxes
🟢 Box Content Decoder: Brotli-compressed boxes
🟢 Butteraugli
🟢 Butteraugli: Shared methods
🟢 Butteraugli: Abstractions
🟢 Butteraugli: Default comparator
🟢 Butteraugli: Encoder comparator
🟡 Cache
🟠 Cache: Decoder
🔴 Cache: Encoder
🟢 Chroma From Luma
🟢 Chroma From Luma Abstractions
🟢 Chroma From Luma Encoder
🟡 Coefficient Order
🟢 Coefficient Order: Forward
🟢 Coefficient Order: Main
🟢 Coefficient Order: Encoder
🔴 Coefficient Order: Tests
🟢 Compressed DC
🟢 Context Map
🟢 Context Map: Abstractions
🟢 Context Map: Decoder
🟢 Context Map: Encoder
🟡 Convolution
🟢 Convolution: Symmetric
🟢 Convolution: Separable
🟢 Convolution: Slow
🟢 Convolution: SIMD
🔴 Convolution: Separable5 Encoder
🔴 Convolution: Tests
🟠 Decoder: Frame
🟢 Decoder: Group
🟢 Decoder: Group Border
🟠 Decoder: Main
🟢 Decoder: Main: Codestream parser
🟢 Decoder: Main: Container format parser
🟡 Discrete Cosine Transform
🟢 Discrete Cosine Transform: DCT scales
🟢 Discrete Cosine Transform: Block data wrapper
🟠 Discrete Cosine Transform: Block-based
🟢 Discrete Cosine Transform: Slow DCT for reference in tests
🔴 Discrete Cosine Transform: Tests
🟢 Encoder dot detection
🟢 Encoder dot dictionary
🟢 Entropy coding
🟢 Encoder entropy coding
🟢 Fields
🟢 Fields: Visitor abstractions
🟢 Fields: Parser
🟢 Fields: Writer
🔴 Frame Encoder
🟢 Gaborish
🟢 Gaborish Encoder
🟢 Gaborish Tests
🟢 Group Encoder
🔴 Heuristics Encoder
🟢 Image Bundle
🟢 Image Bundle: Decoder/Common
🟢 Image Bundle: Encoder
🟢 LZ77 compression
🟢 LZ77: Standard Encoder
🟢 Huffman compression
🟢 Huffman compression: Shared
🟢 Huffman compression: Decoder
🟢 Huffman compression: Encoder
🟡 Modular
🟢 Modular: Transforms
🟢 Modular: Transforms: Palette (Inverse)
🟢 Modular: Transforms: Palette (Forward)
🟢 Modular: Transforms: RCT (Inverse)
🟢 Modular: Transforms: RCT (Forward)
🟢 Modular: Transforms: Squeeze (Inverse)
🟢 Modular: Transforms: Squeeze (Forward)
🟢 Modular: Encoding
🟢 Modular: Encoding: Context Prediction
🟢 Modular: Encoding: MA decoder
🟢 Modular: Encoding: MA encoder
🟢 Modular: Encoding: Tree Samples
🟢 Modular: Encoding: Encoding decoder
🟢 Modular: Encoding: Encoding encoder
🔴 Modular: Decoder
🔴 Modular: Encoder
🟢 Modular: Encoder SIMD
🔴 Modular: Tests
🟢 Patch Dictionary: Decoder
🔴 Patch Dictionary: Encoder
🟠 Passes State: Decoder
🔴 Passes State: Encoder
🟢 Passes State: Shared
🔴 Encoder Main
🔴 Encoder Main
🔴 Encoder Internal
🔴 Encoder Tests
🟢 Encoder: Linear Algebra
🟢 Encoder: Linear Algebra Tests
🟢 Image Operations
🟢 Image Operations
🟢 Image Operations: Tests
🟢 Common I/O: Frame Header
🟢 Common I/O: Metadata
🟢 Common I/O: Container format
🟠 JPEG to JPEG XL lossless compression
🟢 JPEG to JPEG XL lossless compression: JPEG parser/writer
🟠 JPEG to JPEG XL lossless compression (decoder)
🔴 JPEG to JPEG XL lossless compression (encoder)
🟡 Splines
🟢 Splines
🔴 Splines Tests
🟢 Quantizer
🟢 Dequantizer matrices
🟢 Quantizer encoding
🟢 Quantizer weights
🟡 Noise
🟢 Noise: Shared
🟢 Noise: Decoder
🟠 Noise: Encoder
🟢 Noise: Simulation of Photon Noise
🟢 Noise: Simulation of Photon Noise (Tests)
🔴 Noise Tests
🔴 JPEG XL Testing Tools
🟠 Render Pipeline
🔴 Render Pipeline: Main
🔴 Render Pipeline: Low Memory Render Pipeline
🟢 Render Pipeline: Stages Abstractions
🔴 Render Pipeline: Stages: Blending
🟢 Render Pipeline: Stages: Chroma Upsampling
🔴 Render Pipeline: Stages: CMS
🟢 Render Pipeline: Stages: EPF
🟢 Render Pipeline: Stages: From Linear
🟢 Render Pipeline: Stages: Gaborish
🟢 Render Pipeline: Stages: Noise
🟢 Render Pipeline: Stages: Patches
🟢 Render Pipeline: Stages: Splines
🟢 Render Pipeline: Stages: Spot color
🟢 Render Pipeline: Stages: To Linear
🟢 Render Pipeline: Stages: Tone mapping
🟠 Render Pipeline: Stages: Upsampling
🟢 Render Pipeline: Stages: Write to Output
🔴 Render Pipeline: Stages: XYB
🟢 Render Pipeline: Stages: Y'Cb'Cr -> RGB
🟡 Color Management System (CMS)
🟢 CMS: Transfer Functions
🟢 CMS: Abstractions/Color Encoding
🟢 CMS: Tone Mapping
🔴 CMS: Interface
Other completed things: