// Copyright (c) the JPEG XL Project Authors. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file.
// This C++ example decodes a JPEG XL image in one shot (all input bytes // available at once). The example outputs the pixels and color information to a // floating point image and an ICC profile on disk.
/** Decodes JPEG XL image to floating point pixels and ICC Profile. Pixel are * stored as floating point, as interleaved RGBA (4 floating point values per * pixel), line per line from top to bottom. Pixel values have nominal range * 0..1 but may go beyond this range for HDR or wide gamut. The ICC profile * describes the color format of the pixel data.
*/ bool DecodeJpegXlOneShot(const uint8_t* jxl, size_t size,
std::vector<float>* pixels, size_t* xsize,
size_t* ysize, std::vector<uint8_t>* icc_profile) { // Multi-threaded parallel runner. auto runner = JxlResizableParallelRunnerMake(nullptr);
auto dec = JxlDecoderMake(nullptr); if (JXL_DEC_SUCCESS !=
JxlDecoderSubscribeEvents(dec.get(), JXL_DEC_BASIC_INFO |
JXL_DEC_COLOR_ENCODING |
JXL_DEC_FULL_IMAGE)) {
fprintf(stderr, "JxlDecoderSubscribeEvents failed\n"); returnfalse;
}
for (;;) {
JxlDecoderStatus status = JxlDecoderProcessInput(dec.get());
if (status == JXL_DEC_ERROR) {
fprintf(stderr, "Decoder error\n"); returnfalse;
} elseif (status == JXL_DEC_NEED_MORE_INPUT) {
fprintf(stderr, "Error, already provided all input\n"); returnfalse;
} elseif (status == JXL_DEC_BASIC_INFO) { if (JXL_DEC_SUCCESS != JxlDecoderGetBasicInfo(dec.get(), &info)) {
fprintf(stderr, "JxlDecoderGetBasicInfo failed\n"); returnfalse;
}
*xsize = info.xsize;
*ysize = info.ysize;
JxlResizableParallelRunnerSetThreads(
runner.get(),
JxlResizableParallelRunnerSuggestThreads(info.xsize, info.ysize));
} elseif (status == JXL_DEC_COLOR_ENCODING) { // Get the ICC color profile of the pixel data
size_t icc_size; if (JXL_DEC_SUCCESS !=
JxlDecoderGetICCProfileSize(dec.get(), JXL_COLOR_PROFILE_TARGET_DATA,
&icc_size)) {
fprintf(stderr, "JxlDecoderGetICCProfileSize failed\n"); returnfalse;
}
icc_profile->resize(icc_size); if (JXL_DEC_SUCCESS != JxlDecoderGetColorAsICCProfile(
dec.get(), JXL_COLOR_PROFILE_TARGET_DATA,
icc_profile->data(), icc_profile->size())) {
fprintf(stderr, "JxlDecoderGetColorAsICCProfile failed\n"); returnfalse;
}
} elseif (status == JXL_DEC_NEED_IMAGE_OUT_BUFFER) {
size_t buffer_size; if (JXL_DEC_SUCCESS !=
JxlDecoderImageOutBufferSize(dec.get(), &format, &buffer_size)) {
fprintf(stderr, "JxlDecoderImageOutBufferSize failed\n"); returnfalse;
} if (buffer_size != *xsize * *ysize * 16) {
fprintf(stderr, "Invalid out buffer size %d %d\n", static_cast<int>(buffer_size), static_cast<int>(*xsize * *ysize * 16)); returnfalse;
}
pixels->resize(*xsize * *ysize * 4); void* pixels_buffer = static_cast<void*>(pixels->data());
size_t pixels_buffer_size = pixels->size() * sizeof(float); if (JXL_DEC_SUCCESS != JxlDecoderSetImageOutBuffer(dec.get(), &format,
pixels_buffer,
pixels_buffer_size)) {
fprintf(stderr, "JxlDecoderSetImageOutBuffer failed\n"); returnfalse;
}
} elseif (status == JXL_DEC_FULL_IMAGE) { // Nothing to do. Do not yet return. If the image is an animation, more // full frames may be decoded. This example only keeps the last one.
} elseif (status == JXL_DEC_SUCCESS) { // All decoding successfully finished. // It's not required to call JxlDecoderReleaseInput(dec.get()) here since // the decoder will be destroyed. returntrue;
} else {
fprintf(stderr, "Unknown decoder status\n"); returnfalse;
}
}
}
/** Writes to .pfm file (Portable FloatMap). Gimp, tev viewer and ImageMagick * support viewing this format. * The input pixels are given as 32-bit floating point with 4-channel RGBA. * The alpha channel will not be written since .pfm does not support it.
*/ bool WritePFM(constchar* filename, constfloat* pixels, size_t xsize,
size_t ysize) {
FILE* file = fopen(filename, "wb"); if (!file) {
fprintf(stderr, "Could not open %s for writing", filename); returnfalse;
}
uint32_t endian_test = 1;
uint8_t little_endian[4];
memcpy(little_endian, &endian_test, 4);
fprintf(file, "PF\n%d %d\n%s\n", static_cast<int>(xsize), static_cast<int>(ysize), little_endian[0] ? "-1.0" : "1.0"); for (int y = ysize - 1; y >= 0; y--) { for (size_t x = 0; x < xsize; x++) { for (size_t c = 0; c < 3; c++) { constfloat* f = &pixels[(y * xsize + x) * 4 + c];
fwrite(f, 4, 1, file);
}
}
} if (fclose(file) != 0) { returnfalse;
} returntrue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.