// 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.
// Always visit conditional fields to ensure they are initialized.
Status Conditional(bool/*condition*/) override { return true; }
Status AllDefault(const Fields& /*fields*/, bool* JXL_RESTRICT all_default) override { // Just initialize this field and don't skip initializing others.
JXL_RETURN_IF_ERROR(Bool(true, all_default)); returnfalse;
}
Status VisitNested(Fields* /*fields*/) override { // Avoid re-initializing nested bundles (their ctors already called // Bundle::Init for their fields). returntrue;
}
};
// Similar to InitVisitor, but also initializes nested fields. struct SetDefaultVisitor : public VisitorBase {
Status Bits(const size_t /*unused*/, const uint32_t default_value,
uint32_t* JXL_RESTRICT value) override {
*value = default_value; returntrue;
}
// Always visit conditional fields to ensure they are initialized.
Status Conditional(bool/*condition*/) override { return true; }
Status AllDefault(const Fields& /*fields*/, bool* JXL_RESTRICT all_default) override { // Just initialize this field and don't skip initializing others.
JXL_RETURN_IF_ERROR(Bool(true, all_default)); returnfalse;
}
};
class AllDefaultVisitor : public VisitorBase { public: explicit AllDefaultVisitor() = default;
Status AllDefault(const Fields& /*fields*/, bool* JXL_RESTRICT /*all_default*/) override { // Visit all fields so we can compute the actual all_default_ value. returnfalse;
}
bool AllDefault() const { return all_default_; }
private: bool all_default_ = true;
};
class ReadVisitor : public VisitorBase { public: explicit ReadVisitor(BitReader* reader) : reader_(reader) {}
Status Bits(const size_t bits, const uint32_t /*default_value*/,
uint32_t* JXL_RESTRICT value) override {
*value = BitsCoder::Read(bits, reader_); if (!reader_->AllReadsWithinBounds()) { return JXL_STATUS(StatusCode::kNotEnoughBytes, "Not enough bytes for header");
} returntrue;
}
Status U32(const U32Enc dist, const uint32_t /*default_value*/,
uint32_t* JXL_RESTRICT value) override {
*value = U32Coder::Read(dist, reader_); if (!reader_->AllReadsWithinBounds()) { return JXL_STATUS(StatusCode::kNotEnoughBytes, "Not enough bytes for header");
} returntrue;
}
Status U64(const uint64_t /*default_value*/,
uint64_t* JXL_RESTRICT value) override {
*value = U64Coder::Read(reader_); if (!reader_->AllReadsWithinBounds()) { return JXL_STATUS(StatusCode::kNotEnoughBytes, "Not enough bytes for header");
} returntrue;
}
Status F16(constfloat/*default_value*/, float* JXL_RESTRICT value) override {
ok_ &= F16Coder::Read(reader_, value); if (!reader_->AllReadsWithinBounds()) { return JXL_STATUS(StatusCode::kNotEnoughBytes, "Not enough bytes for header");
} returntrue;
}
// This never fails because visitors are expected to keep reading until // EndExtensions, see comment there.
Status BeginExtensions(uint64_t* JXL_RESTRICT extensions) override {
JXL_QUIET_RETURN_IF_ERROR(VisitorBase::BeginExtensions(extensions)); if (*extensions == 0) returntrue;
// For each nonzero bit, i.e. extension that is present: for (uint64_t remaining_extensions = *extensions; remaining_extensions != 0;
remaining_extensions &= remaining_extensions - 1) { const size_t idx_extension =
Num0BitsBelowLS1Bit_Nonzero(remaining_extensions); // Read additional U64 (one per extension) indicating the number of bits // (allows skipping individual extensions).
JXL_RETURN_IF_ERROR(U64(0, &extension_bits_[idx_extension])); if (!SafeAdd(total_extension_bits_, extension_bits_[idx_extension],
total_extension_bits_)) { return JXL_FAILURE("Extension bits overflowed, invalid codestream");
}
} // Used by EndExtensions to skip past any _remaining_ extensions.
pos_after_ext_size_ = reader_->TotalBitsConsumed();
JXL_ENSURE(pos_after_ext_size_ != 0); returntrue;
}
Status EndExtensions() override {
JXL_QUIET_RETURN_IF_ERROR(VisitorBase::EndExtensions()); // Happens if extensions == 0: don't read size, done. if (pos_after_ext_size_ == 0) returntrue;
// Not enough bytes as set by BeginExtensions or earlier. Do not return // this as a JXL_FAILURE or false (which can also propagate to error // through e.g. JXL_RETURN_IF_ERROR), since this may be used while // silently checking whether there are enough bytes. If this case must be // treated as an error, reader_>Close() will do this, just like is already // done for non-extension fields. if (!enough_bytes_) returntrue;
// Skip new fields this (old?) decoder didn't know about, if any. const size_t bits_read = reader_->TotalBitsConsumed();
uint64_t end; if (!SafeAdd(pos_after_ext_size_, total_extension_bits_, end)) { return JXL_FAILURE("Invalid extension size, caused overflow");
} if (bits_read > end) { return JXL_FAILURE("Read more extension bits than budgeted");
} const size_t remaining_bits = end - bits_read; if (remaining_bits != 0) {
JXL_WARNING("Skipping %" PRIuS "-bit extension(s)", remaining_bits);
reader_->SkipBits(remaining_bits); if (!reader_->AllReadsWithinBounds()) { return JXL_STATUS(StatusCode::kNotEnoughBytes, "Not enough bytes for header");
}
} returntrue;
}
Status OK() const { return ok_; }
private: // Whether any error other than not enough bytes occurred. bool ok_ = true;
// Whether there are enough input bytes to read from. bool enough_bytes_ = true;
BitReader* const reader_; // May be 0 even if the corresponding extension is present.
uint64_t extension_bits_[Bundle::kMaxExtensions] = {0};
uint64_t total_extension_bits_ = 0;
size_t pos_after_ext_size_ = 0; // 0 iff extensions == 0.
Status AllDefault(const Fields& /*fields*/, bool* JXL_RESTRICT all_default) override {
JXL_RETURN_IF_ERROR(Bool(true, all_default)); returnfalse; // For max bits, assume nothing is default
}
// Always visit conditional fields to get a (loose) upper bound.
Status Conditional(bool/*condition*/) override { return true; }
Status BeginExtensions(uint64_t* JXL_RESTRICT /*extensions*/) override { // Skip - extensions are not included in "MaxBits" because their length // is potentially unbounded. returntrue;
}
Status EndExtensions() override { returntrue; }
size_t MaxBits() const { return max_bits_; }
private:
size_t max_bits_ = 0;
};
class CanEncodeVisitor : public VisitorBase { public: explicit CanEncodeVisitor() = default;
Status GetSizes(size_t* JXL_RESTRICT extension_bits,
size_t* JXL_RESTRICT total_bits) {
JXL_RETURN_IF_ERROR(ok_);
*extension_bits = 0;
*total_bits = encoded_bits_; // Only if extension field was nonzero will we encode their sizes. if (pos_after_ext_ != 0) {
JXL_ENSURE(encoded_bits_ >= pos_after_ext_);
*extension_bits = encoded_bits_ - pos_after_ext_; // Also need to encode *extension_bits and bill it to *total_bits.
size_t encoded_bits = 0;
ok_ &= U64Coder::CanEncode(*extension_bits, &encoded_bits);
*total_bits += encoded_bits;
// TODO(janwas): support encoding individual extension sizes. We // currently ascribe all bits to the first and send zeros for the // others. for (size_t i = 1; i < hwy::PopCount(extensions_); ++i) {
encoded_bits = 0;
ok_ &= U64Coder::CanEncode(0, &encoded_bits);
*total_bits += encoded_bits;
}
} returntrue;
}
private: bool ok_ = true;
size_t encoded_bits_ = 0;
uint64_t extensions_ = 0; // Snapshot of encoded_bits_ after visiting the extension field, but NOT // including the hidden extension sizes.
uint64_t pos_after_ext_ = 0;
};
} // namespace
void Bundle::Init(Fields* fields) {
InitVisitor visitor; if (!visitor.Visit(fields)) {
JXL_DEBUG_ABORT("Init should never fail");
}
} void Bundle::SetDefault(Fields* fields) {
SetDefaultVisitor visitor; if (!visitor.Visit(fields)) {
JXL_DEBUG_ABORT("SetDefault should never fail");
}
} bool Bundle::AllDefault(const Fields& fields) {
AllDefaultVisitor visitor; if (!visitor.VisitConst(fields)) {
JXL_DEBUG_ABORT("AllDefault should never fail");
} return visitor.AllDefault();
}
size_t Bundle::MaxBits(const Fields& fields) {
MaxBitsVisitor visitor;
Status ret = visitor.VisitConst(fields);
(void)ret;
JXL_DASSERT(ret); return visitor.MaxBits();
}
Status Bundle::CanEncode(const Fields& fields, size_t* extension_bits,
size_t* total_bits) {
CanEncodeVisitor visitor;
JXL_QUIET_RETURN_IF_ERROR(visitor.VisitConst(fields));
JXL_QUIET_RETURN_IF_ERROR(visitor.GetSizes(extension_bits, total_bits)); returntrue;
}
Status Bundle::Read(BitReader* reader, Fields* fields) {
ReadVisitor visitor(reader);
JXL_RETURN_IF_ERROR(visitor.Visit(fields)); return visitor.OK();
} bool Bundle::CanRead(BitReader* reader, Fields* fields) {
ReadVisitor visitor(reader);
Status status = visitor.Visit(fields); // We are only checking here whether there are enough bytes. We still return // true for other errors because it means there are enough bytes to determine // there's an error. Use Read() to determine which error it is. return status.code() != StatusCode::kNotEnoughBytes;
}
// It is difficult to verify whether Dist32Byte are sorted, so check all // selectors and keep the one with the fewest total_bits.
*total_bits = 64; // more than any valid encoding for (uint32_t s = 0; s < 4; ++s) { const U32Distr d = enc.GetDistr(s); if (d.IsDirect()) { if (d.Direct() == value) {
*selector = s;
*total_bits = 2; returntrue; // Done, direct is always the best possible.
} continue;
} const size_t extra_bits = d.ExtraBits(); const uint32_t offset = d.Offset(); if (value < offset || value >= offset + (1ULL << extra_bits)) continue;
Status F16Coder::CanEncode(float value, size_t* JXL_RESTRICT encoded_bits) {
*encoded_bits = MaxEncodedBits(); if (std::isnan(value) || std::isinf(value)) { return JXL_FAILURE("Should not attempt to store NaN and infinity");
} return std::abs(value) <= 65504.0f;
}
Status CheckHasEnoughBits(Visitor* visitor, size_t bits) { if (!visitor->IsReading()) returnfalse;
ReadVisitor* rv = static_cast<ReadVisitor*>(visitor);
size_t have_bits = rv->reader_->TotalBytes() * kBitsPerByte;
size_t want_bits = bits + rv->reader_->TotalBitsConsumed(); if (have_bits < want_bits) { return JXL_STATUS(StatusCode::kNotEnoughBytes, "Not enough bytes for header");
} 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.