27#include "jxl/codestream_header.h"
28#include "jxl/decode.h"
29#include "jxl/decode_cxx.h"
54 JxlSignature
result = JxlSignatureCheck(
reinterpret_cast<const uint8_t*
>(
buffer), bytesRead);
55 return (
result == JXL_SIG_CODESTREAM) || (
result == JXL_SIG_CONTAINER);
78SkJpegxlCodec::SkJpegxlCodec(std::unique_ptr<SkJpegxlCodecPriv> codec,
80 std::unique_ptr<SkStream>
stream,
83 , fCodec(
std::move(codec))
104 auto priv = std::make_unique<SkJpegxlCodecPriv>();
105 JxlDecoder* dec =
priv->fDecoder.get();
108 auto status = JxlDecoderSubscribeEvents(dec, JXL_DEC_BASIC_INFO | JXL_DEC_COLOR_ENCODING);
109 if (status != JXL_DEC_SUCCESS) {
115 status = JxlDecoderSetInput(dec,
data->bytes(),
data->size());
116 if (status != JXL_DEC_SUCCESS) {
122 status = JxlDecoderProcessInput(dec);
123 if (status == JXL_DEC_NEED_MORE_INPUT) {
127 if (status != JXL_DEC_BASIC_INFO) {
132 status = JxlDecoderGetBasicInfo(dec, &
info);
133 if (status != JXL_DEC_SUCCESS) {
140 if (!SkTFitsIn<int32_t>(
info.xsize) || !SkTFitsIn<int32_t>(
info.ysize)) {
144 int32_t
width = SkTo<int32_t>(
info.xsize);
147 bool hasAlpha = (
info.alpha_bits != 0);
148 bool isGray = (
info.num_color_channels == 1);
158 status = JxlDecoderProcessInput(dec);
159 if (status != JXL_DEC_COLOR_ENCODING) {
166 status = JxlDecoderGetICCProfileSize(
167 dec,
nullptr, JXL_COLOR_PROFILE_TARGET_DATA, &iccSize);
168 if (status != JXL_DEC_SUCCESS) {
172 std::unique_ptr<SkEncodedInfo::ICCProfile>
profile =
nullptr;
176 status = JxlDecoderGetColorAsICCProfile(dec,
178 JXL_COLOR_PROFILE_TARGET_DATA,
179 reinterpret_cast<uint8_t*
>(icc->writable_data()),
181 if (status != JXL_DEC_SUCCESS) {
189 int bitsPerChannel = 16;
196 std::move(
priv), std::move(encodedInfo), std::move(
stream), std::move(
data)));
205 auto& codec = *fCodec.get();
207 SkASSERT(0 == index ||
static_cast<size_t>(index) < codec.fFrames.size());
208 auto* dec = codec.fDecoder.get();
209 JxlDecoderStatus status;
211 if ((codec.fLastProcessedFrame >= index) || (codec.fLastProcessedFrame =
SkCodec::kNoFrame)) {
213 JxlDecoderRewind(dec);
214 status = JxlDecoderSubscribeEvents(dec, JXL_DEC_FRAME | JXL_DEC_FULL_IMAGE);
215 if (status != JXL_DEC_SUCCESS) {
220 status = JxlDecoderSetInput(dec, fData->
bytes(), fData->
size());
221 if (status != JXL_DEC_SUCCESS) {
226 SkASSERT(codec.fLastProcessedFrame + 1 == 0);
229 int nextFrame = codec.fLastProcessedFrame + 1;
230 if (nextFrame < index) {
231 JxlDecoderSkipFrames(dec, index - nextFrame);
235 status = JxlDecoderProcessInput(dec);
239 codec.fLastProcessedFrame = index;
240 if (status != JXL_DEC_FRAME) {
246 codec.fRowBytes = rowBytes;
249 uint32_t numColorChannels = 3;
251 uint32_t numAlphaChannels = 1;
253 auto endianness = JXL_LITTLE_ENDIAN;
262 bool halfFloatOutput =
false;
265 auto dataType = halfFloatOutput ? JXL_TYPE_FLOAT16 : JXL_TYPE_UINT8;
268 {numColorChannels + numAlphaChannels, dataType, endianness, 0};
269 status = JxlDecoderSetImageOutCallback(dec, &
format, SkJpegxlCodec::imageOutCallback,
this);
270 if (status != JXL_DEC_SUCCESS) {
277 status = JxlDecoderProcessInput(dec);
278 if (status != JXL_DEC_FULL_IMAGE) {
292 JxlDecoderRewind(fCodec->fDecoder.get());
297 bool needsColorXform) {
323void SkJpegxlCodec::imageOutCallback(
void* opaque,
size_t x,
size_t y,
324 size_t num_pixels,
const void* pixels) {
326 auto& codec = *
instance->fCodec.get();
327 size_t offset =
y * codec.fRowBytes + (
x << codec.fPixelShift);
328 void*
dst = SkTAddOffset<void>(codec.fDst,
offset);
330 instance->applyColorXform(
dst, pixels, num_pixels);
333 switch (codec.fDstColorType) {
335 memcpy(
dst, pixels, 4 * num_pixels);
341 memcpy(
dst, pixels, 8 * num_pixels);
344 SK_ABORT(
"Selected output format is not supported yet");
349bool SkJpegxlCodec::scanFrames() {
350 auto decoder = JxlDecoderMake(
nullptr);
351 JxlDecoder* dec = decoder.get();
352 auto* frameHolder = fCodec.get();
353 auto& frames = frameHolder->fFrames;
354 const auto&
info = fCodec->fInfo;
357 auto alpha = (
info.alpha_bits != 0) ? SkEncodedInfo::Alpha::kUnpremul_Alpha
358 : SkEncodedInfo::Alpha::kOpaque_Alpha;
360 auto status = JxlDecoderSubscribeEvents(dec, JXL_DEC_FRAME);
361 if (status != JXL_DEC_SUCCESS) {
367 status = JxlDecoderSetInput(dec, fData->
bytes(), fData->
size());
368 if (status != JXL_DEC_SUCCESS) {
375 status = JxlDecoderProcessInput(dec);
377 case JXL_DEC_FRAME: {
378 size_t frameId = frames.size();
379 JxlFrameHeader frameHeader;
380 if (JxlDecoderGetFrameHeader(dec, &frameHeader) != JXL_DEC_SUCCESS) {
383 frames.emplace_back(
static_cast<int>(frameId), alpha);
384 auto&
frame = frames.back();
387 int duration = (1000 * frameHeader.duration *
info.animation.tps_denominator) /
388 info.animation.tps_numerator;
390 frameHolder->setAlphaAndRequiredFrame(&
frame);
393 case JXL_DEC_SUCCESS: {
404 if (!fCodec->fInfo.have_animation) {
408 if (!fCodec->fSeenAllFrames) {
409 fCodec->fSeenAllFrames = scanFrames();
412 return fCodec->fFrames.size();
419 if (
static_cast<size_t>(index) >= fCodec->fFrames.size()) {
422 fCodec->fFrames[index].fillIn(frameInfo,
true);
427 JxlBasicInfo&
info = fCodec->fInfo;
428 if (!
info.have_animation) {
432 if (
info.animation.num_loops == 0) {
436 if (SkTFitsIn<int>(
info.animation.num_loops)) {
437 return info.animation.num_loops - 1;
479 outResult = &resultStorage;
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
#define SkDEBUGFAIL(message)
#define SK_ABORT(message,...)
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
@ kGray_8_SkColorType
pixel with grayscale level in 8-bit byte
@ kRGB_565_SkColorType
pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
#define INHERITED(method,...)
sk_sp< SkData > SkCopyStreamToData(SkStream *stream)
const SkImageInfo & dstInfo() const
static constexpr int kRepetitionCountInfinite
static constexpr int kNoFrame
const Options & options() const
static sk_sp< SkData > MakeWithoutCopy(const void *data, size_t length)
const uint8_t * bytes() const
static sk_sp< SkData > MakeUninitialized(size_t length)
static std::unique_ptr< ICCProfile > Make(sk_sp< SkData >)
virtual SkEncodedInfo::Alpha onReportedAlpha() const =0
SkColorType fDstColorType
std::vector< Frame > fFrames
const SkFrame * onGetFrame(int i) const override
Result onGetPixels(const SkImageInfo &dstInfo, void *dst, size_t rowBytes, const Options &options, int *rowsDecodedPtr) override
int onGetRepetitionCount() override
int onGetFrameCount() override
bool conversionSupported(const SkImageInfo &, bool, bool) override
bool onGetFrameInfo(int, FrameInfo *) const override
static bool IsJpegxl(const void *, size_t)
static std::unique_ptr< SkCodec > MakeFromStream(std::unique_ptr< SkStream >, Result *)
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
virtual size_t getLength() const
virtual const void * getMemoryBase()
FlPixelBufferTexturePrivate * priv
uint32_t uint32_t * format
static float max(float r, float g, float b)
SK_API bool IsJpegxl(const void *, size_t)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
Swizzle_8888_u32 RGBA_to_bgrA
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
@ skcms_PixelFormat_RGBA_16161616LE
static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha, int bitsPerComponent)
SkColorType colorType() const
std::shared_ptr< const fml::Mapping > data