From eb08d0049a1baa0ceda66ac1b34f5f97c4050270 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 30 Oct 2020 13:42:38 +0000 Subject: [PATCH] Few more simplifications to JXL decoder --- codecs/jxl/dec/jxl_dec.cpp | 26 +++++++++++++++----------- codecs/jxl/dec/jxl_dec.wasm | Bin 327240 -> 327165 bytes 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/codecs/jxl/dec/jxl_dec.cpp b/codecs/jxl/dec/jxl_dec.cpp index e2282b38..1fde78da 100644 --- a/codecs/jxl/dec/jxl_dec.cpp +++ b/codecs/jxl/dec/jxl_dec.cpp @@ -11,6 +11,9 @@ using namespace emscripten; thread_local const val Uint8ClampedArray = val::global("Uint8ClampedArray"); thread_local const val ImageData = val::global("ImageData"); +// R, G, B, A +#define COMPONENTS_PER_PIXEL 4 + #define EXPECT_TRUE(a) \ if (!(a)) \ return val::null(); @@ -24,14 +27,14 @@ val decode(std::string data) { EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSubscribeEvents( dec.get(), JXL_DEC_BASIC_INFO | JXL_DEC_COLOR_ENCODING | JXL_DEC_FULL_IMAGE)); + auto next_in = (const uint8_t*)data.c_str(); auto avail_in = data.size(); EXPECT_EQ(JXL_DEC_BASIC_INFO, JxlDecoderProcessInput(dec.get(), &next_in, &avail_in)); - size_t buffer_size; - const JxlPixelFormat format = {4, JXL_LITTLE_ENDIAN, JXL_TYPE_FLOAT}; - EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderImageOutBufferSize(dec.get(), &format, &buffer_size)); JxlBasicInfo info; EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderGetBasicInfo(dec.get(), &info)); + size_t pixel_count = info.xsize * info.ysize; + size_t component_count = pixel_count * COMPONENTS_PER_PIXEL; EXPECT_EQ(JXL_DEC_COLOR_ENCODING, JxlDecoderProcessInput(dec.get(), &next_in, &avail_in)); size_t icc_size; @@ -42,12 +45,13 @@ val decode(std::string data) { JxlDecoderGetColorAsICCProfile(dec.get(), JXL_COLOR_PROFILE_TARGET_DATA, icc_profile.data(), icc_profile.size())); - auto float_pixels = std::make_unique((buffer_size + 3) / 4); - EXPECT_EQ(JXL_DEC_SUCCESS, - JxlDecoderSetImageOutBuffer(dec.get(), &format, float_pixels.get(), buffer_size)); + auto float_pixels = std::make_unique(component_count); + static const JxlPixelFormat format = {COMPONENTS_PER_PIXEL, JXL_LITTLE_ENDIAN, JXL_TYPE_FLOAT}; + EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderSetImageOutBuffer(dec.get(), &format, float_pixels.get(), + component_count * sizeof(float))); EXPECT_EQ(JXL_DEC_FULL_IMAGE, JxlDecoderProcessInput(dec.get(), &next_in, &avail_in)); - auto pixels = std::make_unique(info.xsize * info.ysize * 4); + auto byte_pixels = std::make_unique(component_count); // Convert to sRGB. skcms_ICCProfile jxl_profile; // If the image is encoded in its original color space, the decoded data will be in the color @@ -63,12 +67,12 @@ val decode(std::string data) { EXPECT_TRUE(skcms_Transform( float_pixels.get(), skcms_PixelFormat_RGBA_ffff, info.alpha_premultiplied ? skcms_AlphaFormat_PremulAsEncoded : skcms_AlphaFormat_Unpremul, - &jxl_profile, pixels.get(), skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul, - skcms_sRGB_profile(), info.xsize * info.ysize)); + &jxl_profile, byte_pixels.get(), skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul, + skcms_sRGB_profile(), pixel_count)); return ImageData.new_( - Uint8ClampedArray.new_(typed_memory_view(info.xsize * info.ysize * 4, pixels.get())), - info.xsize, info.ysize); + Uint8ClampedArray.new_(typed_memory_view(component_count, byte_pixels.get())), info.xsize, + info.ysize); } EMSCRIPTEN_BINDINGS(my_module) { diff --git a/codecs/jxl/dec/jxl_dec.wasm b/codecs/jxl/dec/jxl_dec.wasm index 8b2b0b6cf35607e6f4abd3ef8a531fcc039f58e4..16b6767e472d08fc2e72a500ce75d1208c7c4053 100644 GIT binary patch delta 12263 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 delta 12057 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�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