// 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.
// OpenEXR::Int64 is deprecated in favor of using uint64_t directly, but using // uint64_t as recommended causes build failures with previous OpenEXR versions // on macOS, where the definition for OpenEXR::Int64 was actually not equivalent // to uint64_t. This alternative should work in all cases. using ExrInt64 = decltype(std::declval<OpenEXR::IStream>().tellg());
class InMemoryOStream : public OpenEXR::OStream { public: // `bytes` must outlive the InMemoryOStream. explicit InMemoryOStream(std::vector<uint8_t>* const bytes)
: OStream(/*fileName=*/""), bytes_(*bytes) {}
// Ensure that the destructor of RgbaOutputFile has run before we look at the // size of `bytes`.
{
InMemoryOStream os(bytes);
OpenEXR::RgbaOutputFile output(
os, header, has_alpha ? OpenEXR::WRITE_RGBA : OpenEXR::WRITE_RGB); // How many rows to write at once. Again, the OpenEXR documentation // recommends writing the whole image in one call. constint y_chunk_size = ysize;
std::vector<OpenEXR::Rgba> output_rows(xsize * y_chunk_size);
for (size_t start_y = 0; start_y < ysize; start_y += y_chunk_size) { // Inclusive. const size_t end_y = std::min(start_y + y_chunk_size - 1, ysize - 1);
output.setFrameBuffer(output_rows.data() - start_y * xsize, /*xStride=*/1, /*yStride=*/xsize); for (size_t y = start_y; y <= end_y; ++y) { const uint8_t* in_row = &in[(y - start_y) * in_stride];
OpenEXR::Rgba* const JXL_RESTRICT row_data =
&output_rows[(y - start_y) * xsize]; for (size_t x = 0; x < xsize; ++x) { const uint8_t* in_pixel = &in_row[4 * num_channels * x]; float r = loadFloat(&in_pixel[0]); float g = loadFloat(&in_pixel[4]); float b = loadFloat(&in_pixel[8]); constfloat alpha = loadAlpha(&in_pixel[12]); if (!alpha_is_premultiplied) {
r *= alpha;
g *= alpha;
b *= alpha;
}
row_data[x] = OpenEXR::Rgba(r, g, b, alpha);
}
}
output.writePixels(/*numScanLines=*/end_y - start_y + 1);
}
}
returntrue;
}
class EXREncoder : public Encoder {
std::vector<JxlPixelFormat> AcceptedFormats() const override {
std::vector<JxlPixelFormat> formats; for (const uint32_t num_channels : {1, 2, 3, 4}) { for (const JxlDataType data_type : {JXL_TYPE_FLOAT}) { for (JxlEndianness endianness : {JXL_BIG_ENDIAN, JXL_LITTLE_ENDIAN}) {
formats.push_back(JxlPixelFormat{/*num_channels=*/num_channels, /*data_type=*/data_type, /*endianness=*/endianness, /*align=*/0});
}
}
} return formats;
}
Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded_image,
ThreadPool* pool) const override {
JXL_RETURN_IF_ERROR(VerifyBasicInfo(ppf.info));
encoded_image->icc.clear();
encoded_image->bitstreams.clear();
encoded_image->bitstreams.reserve(ppf.frames.size()); for (constauto& frame : ppf.frames) {
JXL_RETURN_IF_ERROR(VerifyPackedImage(frame.color, ppf.info));
encoded_image->bitstreams.emplace_back();
JXL_RETURN_IF_ERROR(EncodeImageEXR(frame.color, ppf.info,
ppf.color_encoding, pool,
&encoded_image->bitstreams.back()));
} 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.