Skip to content

Commit

Permalink
Code for migrating to JXL 0.7
Browse files Browse the repository at this point in the history
  • Loading branch information
aryanpingle committed Aug 30, 2023
1 parent 84c7b0a commit 807e352
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 18 deletions.
4 changes: 2 additions & 2 deletions codecs/cpp.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FROM emscripten/emsdk:2.0.23
# RUN apt-get update && apt-get install -qqy autoconf libtool pkg-config
FROM emscripten/emsdk:2.0.34
RUN apt-get update && apt-get install -qqy autoconf libtool pkg-config
ENV CFLAGS "-O3 -flto"
ENV CXXFLAGS "${CFLAGS} -std=c++17"
ENV LDFLAGS "${CFLAGS} \
Expand Down
4 changes: 2 additions & 2 deletions codecs/jxl/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CODEC_URL = https://github.com/libjxl/libjxl.git
CODEC_VERSION = 9f544641ec83f6abd9da598bdd08178ee8a003e0
CODEC_VERSION = f95da131cf7c7ccd4da256356fde2fec1fa23bb5
CODEC_DIR = node_modules/jxl
CODEC_BUILD_ROOT := $(CODEC_DIR)/build
CODEC_MT_BUILD_DIR := $(CODEC_BUILD_ROOT)/mt
Expand Down Expand Up @@ -33,7 +33,7 @@ enc/jxl_enc_mt_simd.js: $(CODEC_MT_SIMD_BUILD_DIR)/lib/libjxl.a $(CODEC_MT_SIMD_
export CXXFLAGS += -Wno-deprecated-declarations

# Compile multithreaded wrappers with -pthread.
enc/jxl_enc_mt.js enc/jxl_enc_mt_simd.js: CXXFLAGS+=-pthread
enc/jxl_enc_mt.js enc/jxl_enc_mt_simd.js dec/jxl_dec.js: CXXFLAGS+=-pthread

$(OUT_JS):
$(CXX) \
Expand Down
8 changes: 8 additions & 0 deletions codecs/jxl/dec/jxl_dec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,16 @@ thread_local const val ImageData = val::global("ImageData");
#endif

val decode(std::string data) {
printf("JXL Decode start\n");
// printf("Length of data: %lu\n", data.length());
std::unique_ptr<JxlDecoder,
std::integral_constant<decltype(&JxlDecoderDestroy), JxlDecoderDestroy>>
dec(JxlDecoderCreate(nullptr));
EXPECT_EQ(JXL_DEC_SUCCESS,
JxlDecoderSubscribeEvents(
dec.get(), JXL_DEC_BASIC_INFO | JXL_DEC_COLOR_ENCODING | JXL_DEC_FULL_IMAGE));

// printf("decode 1\n");
auto next_in = (const uint8_t*)data.c_str();
auto avail_in = data.size();
JxlDecoderSetInput(dec.get(), next_in, avail_in);
Expand All @@ -58,7 +61,9 @@ val decode(std::string data) {
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;
// printf("Component count = %zu\n", component_count);

// printf("decode 2\n");
EXPECT_EQ(JXL_DEC_COLOR_ENCODING, JxlDecoderProcessInput(dec.get()));
static const JxlPixelFormat format = {COMPONENTS_PER_PIXEL, JXL_TYPE_FLOAT, JXL_LITTLE_ENDIAN, 0};
size_t icc_size;
Expand All @@ -69,6 +74,7 @@ val decode(std::string data) {
JxlDecoderGetColorAsICCProfile(dec.get(), &format, JXL_COLOR_PROFILE_TARGET_DATA,
icc_profile.data(), icc_profile.size()));

// printf("decode 3\n");
EXPECT_EQ(JXL_DEC_NEED_IMAGE_OUT_BUFFER, JxlDecoderProcessInput(dec.get()));
size_t buffer_size;
EXPECT_EQ(JXL_DEC_SUCCESS, JxlDecoderImageOutBufferSize(dec.get(), &format, &buffer_size));
Expand All @@ -89,6 +95,8 @@ val decode(std::string data) {
&jxl_profile, byte_pixels.get(), skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul,
skcms_sRGB_profile(), pixel_count));

printf("JXL Decode end\n");
// printf("info: xsize=%d ysize=%d\n", info.xsize, info.ysize);
return ImageData.new_(
Uint8ClampedArray.new_(typed_memory_view(component_count, byte_pixels.get())), info.xsize,
info.ysize);
Expand Down
40 changes: 40 additions & 0 deletions codecs/jxl/enc/example.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<!-- <script src="jxl_enc.js" type="module"></script> -->
<script type="module">
async function loadImage(src) {
// Load image
const img = document.createElement("img");
img.src = src;
await new Promise((resolve) => (img.onload = resolve));
// Make canvas same size as image
const canvas = document.createElement("canvas");
[canvas.width, canvas.height] = [img.width, img.height];
// Draw image onto canvas
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
return ctx.getImageData(0, 0, img.width, img.height);
}

import jxl_enc from "./jxl_enc.js"
jxl_enc().then(async (module) => {
const image = await loadImage("../../example_palette.png");
let result = null;
result = module.encode(image.data, image.width, image.height, {
effort: 7,
quality: 75,
progressive: false,
epf: -1,
lossyPalette: false,
decodingSpeedTier: 0,
photonNoiseIso: 0,
lossyModular: false,
});
console.log("size", result.length);
const blob = new Blob([result], { type: "image/jxl" });

const blobURL = URL.createObjectURL(blob);
const img = document.createElement("img");
img.src = blobURL;
document.body.appendChild(img);
});
</script>
34 changes: 20 additions & 14 deletions codecs/jxl/enc/jxl_enc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
#include <emscripten/val.h>

#include "lib/jxl/base/thread_pool_internal.h"
#include "lib/jxl/enc_color_management.h"
#include "lib/jxl/enc_external_image.h"
#include "lib/jxl/enc_file.h"
#include "lib/jxl/enc_color_management.h"

using namespace emscripten;

Expand All @@ -22,6 +22,7 @@ struct JXLOptions {
};

val encode(std::string image, int width, int height, JXLOptions options) {
printf("encoding start\n");
jxl::CompressParams cparams;
jxl::PassesEncoderState passes_enc_state;
jxl::CodecInOut io;
Expand Down Expand Up @@ -55,13 +56,13 @@ val encode(std::string image, int width, int height, JXLOptions options) {
if (options.lossyModular || quality == 100) {
cparams.modular_mode = true;
// Internal modular quality to roughly match VarDCT size.
if (quality < 7) {
cparams.quality_pair.first = cparams.quality_pair.second =
std::min(35 + (quality - 7) * 3.0f, 100.0f);
} else {
cparams.quality_pair.first = cparams.quality_pair.second =
std::min(35 + (quality - 7) * 65.f / 93.f, 100.0f);
}
// if (quality < 7) {
// cparams.quality_pair.first = cparams.quality_pair.second =
// std::min(35 + (quality - 7) * 3.0f, 100.0f);
// } else {
// cparams.quality_pair.first = cparams.quality_pair.second =
// std::min(35 + (quality - 7) * 65.f / 93.f, 100.0f);
// }
} else {
cparams.modular_mode = false;
if (quality >= 30) {
Expand All @@ -80,7 +81,7 @@ val encode(std::string image, int width, int height, JXLOptions options) {
}

if (cparams.modular_mode) {
if (cparams.quality_pair.first != 100 || cparams.quality_pair.second != 100) {
if (!cparams.IsLossless()) {
cparams.color_transform = jxl::ColorTransform::kXYB;
} else {
cparams.color_transform = jxl::ColorTransform::kNone;
Expand All @@ -96,19 +97,24 @@ val encode(std::string image, int width, int height, JXLOptions options) {

auto result = jxl::ConvertFromExternal(
jxl::Span<const uint8_t>(reinterpret_cast<const uint8_t*>(image.data()), image.size()), width,
height, jxl::ColorEncoding::SRGB(/*is_gray=*/false), /*has_alpha=*/true,
/*alpha_is_premultiplied=*/false, /*bits_per_sample=*/8, /*endiannes=*/JXL_LITTLE_ENDIAN,
/*flipped_y=*/false, pool_ptr, main, /*(only true if bits_per_sample==32) float_in=*/false);
height, jxl::ColorEncoding::SRGB(/*is_gray=*/false), 4, /*alpha_is_premultiplied=*/false,
/*bits_per_sample=*/8, /*endiannes=*/JXL_LITTLE_ENDIAN, pool_ptr, main,
/*(only true if bits_per_sample==32) float_in=*/false, 0);

if (!result) {
return val::null();
}

auto js_result = val::null();
if (EncodeFile(cparams, &io, &passes_enc_state, &bytes, jxl::GetJxlCms(), /*aux=*/nullptr, pool_ptr)) {
js_result = Uint8Array.new_(typed_memory_view(bytes.size(), bytes.data()));
if (EncodeFile(cparams, &io, &passes_enc_state, &bytes, jxl::GetJxlCms(), /*aux=*/nullptr,
pool_ptr)) {
printf("Number of bytes: %zu\n", bytes.size()); // works
auto g = typed_memory_view(bytes.size(), bytes.data());
printf("Number of bytes 2: %zu\n", bytes.size()); // works
js_result = Uint8Array.new_(g);
}

printf("encode end\n");
return js_result;
}

Expand Down

0 comments on commit 807e352

Please sign in to comment.