Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 41 additions & 23 deletions src/jpeg2000.imageio/jpeg2000input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,24 +571,53 @@ Jpeg2000Input::open(const std::string& name, ImageSpec& p_spec)
|| has_error()) {
if (!has_error())
errorfmt("Could not read Jpeg2000 header");
close();
return false;
}
if (!has_error()) {
if (!opj_decode(m_codec, m_stream, m_image)) {
if (!has_error())
errorfmt("Could not decode Jpeg2000 data");

// Check the header-claimed size before the expensive opj_decode. Channel
// count can still grow during decode (palette expansion), but that only
// makes the image larger, so this is a safe lower-bound estimate.
{
int w = (m_image->x1 > m_image->x0) ? int(m_image->x1 - m_image->x0)
: 0;
int h = (m_image->y1 > m_image->y0) ? int(m_image->y1 - m_image->y0)
: 0;
uint32_t prov_prec = 0;
for (uint32_t c = 0; c < m_image->numcomps; ++c)
prov_prec = std::max(prov_prec, m_image->comps[c].prec);
ImageSpec provspec(w, h, int(m_image->numcomps),
prov_prec <= 8 ? TypeDesc::UINT8 : TypeDesc::UINT16);
provspec.full_width = m_image->x1;
provspec.full_height = m_image->y1;
if (!check_open(provspec,
{ 0, std::numeric_limits<int>::max(), 0,
std::numeric_limits<int>::max(), 0, 1, 0, 16384 })) {
close();
return false;
}
}

destroy_decompressor();
destroy_stream();
// Guard against decompression bombs / corrupt headers: a tiny
// codestream claiming a multi-gigabyte image, which opj_decode
// would then hang and allocate gigabytes trying to produce.
imagesize_t filesize = ioproxy() ? ioproxy()->size() : 0;
if (!check_compression_ratio(provspec, filesize)) {
close();
return false;
}
}

if (has_error()) {
if (!opj_decode(m_codec, m_stream, m_image) || has_error()) {
if (!has_error())
errorfmt("Could not decode Jpeg2000 data");
close();
return false;
}
OIIO_ASSERT(m_image != nullptr);
destroy_decompressor();
destroy_stream();

// we support only one, three or four components in image
// we support only one, three or four components in image (final only
// after decode, since palette expansion can change it)
const int channelCount = m_image->numcomps;
if (channelCount != 1 && channelCount != 3 && channelCount != 4) {
errorfmt(
Expand Down Expand Up @@ -633,25 +662,14 @@ Jpeg2000Input::open(const std::string& name, ImageSpec& p_spec)
ROI datawindow;
m_bpp.clear();
m_bpp.reserve(channelCount);
std::vector<TypeDesc> chantypes(channelCount, TypeDesc::UINT8);
for (int i = 0; i < channelCount; i++) {
const opj_image_comp_t& comp(m_image->comps[i]);
m_bpp.push_back(comp.prec);
maxPrecision = std::max(comp.prec, maxPrecision);
ROI roichan(comp.x0, comp.x0 + comp.w * comp.dx, comp.y0,
comp.y0 + comp.h * comp.dy);
datawindow = roi_union(datawindow, roichan);
// std::cout << " chan " << i << "\n";
// std::cout << " dx=" << comp.dx << " dy=" << comp.dy
// << " x0=" << comp.x0 << " y0=" << comp.y0
// << " w=" << comp.w << " h=" << comp.h
// << " prec=" << comp.prec << " bpp=" << comp.bpp << "\n";
// std::cout << " sgnd=" << comp.sgnd << " resno_decoded=" << comp.resno_decoded << " factor=" << comp.factor << "\n";
// std::cout << " roichan=" << roichan << "\n";
}
// std::cout << "overall x0=" << m_image->x0 << " y0=" << m_image->y0
// << " x1=" << m_image->x1 << " y1=" << m_image->y1 << "\n";
// std::cout << "color_space=" << m_image->color_space << "\n";
}
TypeDesc format = (maxPrecision <= 8) ? TypeDesc::UINT8 : TypeDesc::UINT16;
m_spec = ImageSpec(datawindow.width(), datawindow.height(), channelCount,
format);
Expand All @@ -662,7 +680,7 @@ Jpeg2000Input::open(const std::string& name, ImageSpec& p_spec)
m_spec.full_width = m_image->x1;
m_spec.full_height = m_image->y1;

// Validation of resolution
// Validation of resolution, now authoritative with the final channel count
if (!check_open(m_spec,
{ 0, std::numeric_limits<int>::max(), 0,
std::numeric_limits<int>::max(), 0, 1, 0, 16384 })) {
Expand Down
Loading