Skip to content

Commit

Permalink
stb_image: update to v2.15, support 16-bit PNGs
Browse files Browse the repository at this point in the history
Also removes SSE2 runtime detection, which was causing compilation issues on Fedora
Also now supports HDR images with #?RGBE header
  • Loading branch information
rdb committed May 24, 2017
1 parent 68be3c6 commit c52bab1
Show file tree
Hide file tree
Showing 2 changed files with 1,002 additions and 553 deletions.
144 changes: 107 additions & 37 deletions panda/src/pnmimagetypes/pnmFileTypeStbImage.cxx
Expand Up @@ -240,12 +240,28 @@ StbImageReader(PNMFileType *type, istream *file, bool owns_file, string magic_nu
_context.img_buffer_end = _buffer + length;
_context.img_buffer_original_end = _context.img_buffer_end;

#ifndef STBI_NO_PNG
stbi__png png;
png.s = &_context;
#endif

// Invoke stbi_info to read the image size and channel count.
if (strncmp(magic_number.c_str(), "#?", 2) == 0 &&
if (magic_number[0] == '#' && magic_number[1] == '?' &&
stbi__hdr_info(&_context, &_x_size, &_y_size, &_num_channels)) {
_is_valid = true;
_is_float = true;

#ifndef STBI_NO_PNG
} else if (magic_number[0] == '\x89' && magic_number[1] == 'P' &&
stbi__png_info_raw(&png, &_x_size, &_y_size, &_num_channels)) {
// Detect the case of using PNGs so that we can determine whether to do a
// 16-bit load instead.
if (png.depth == 16) {
_maxval = 65535;
}
_is_valid = true;
#endif

} else if (stbi__info_main(&_context, &_x_size, &_y_size, &_num_channels)) {
_is_valid = true;

Expand All @@ -254,8 +270,6 @@ StbImageReader(PNMFileType *type, istream *file, bool owns_file, string magic_nu
pnmimage_cat.error()
<< "stb_info failure: " << stbi_failure_reason() << "\n";
}

_maxval = 255;
}

/**
Expand Down Expand Up @@ -307,11 +321,13 @@ read_pfm(PfmFile &pfm) {
int len;
unsigned char count, value;
int i, j, k, c1, c2, z;
const char *headerToken;

// Check identifier
if (strcmp(stbi__hdr_gettoken(&_context, buffer), "#?RADIANCE") != 0) {
headerToken = stbi__hdr_gettoken(&_context, buffer);
if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) {
pnmimage_cat.error()
<< "Missing #?RADIANCE header.\n";
<< "Missing #?RADIANCE or #?RGBE header.\n";
return false;
}

Expand Down Expand Up @@ -387,27 +403,43 @@ read_pfm(PfmFile &pfm) {
len <<= 8;
len |= stbi__get8(&_context);
if (len != width) {
STBI_FREE(scanline);
pnmimage_cat.error() << "Corrupt HDR: invalid decoded scanline length.\n";
STBI_FREE(scanline);
return false;
}
if (scanline == NULL) {
scanline = (stbi_uc *) stbi__malloc(width * 4);
if (scanline == nullptr) {
scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0);
if (!scanline) {
pnmimage_cat.error() << "Out of memory while reading HDR file.\n";
STBI_FREE(hdr_data);
return false;
}
}

for (k = 0; k < 4; ++k) {
int nleft;
i = 0;
while (i < width) {
while ((nleft = width - i) > 0) {
count = stbi__get8(&_context);
if (count > 128) {
// Run
value = stbi__get8(&_context);
count -= 128;
if (count > nleft) {
pnmimage_cat.error() << "Bad RLE data in HDR file.\n";
STBI_FREE(scanline);
return false;
}
for (z = 0; z < count; ++z) {
scanline[i++ * 4 + k] = value;
}
} else {
// Dump
if (count > nleft) {
pnmimage_cat.error() << "Bad RLE data in HDR file.\n";
STBI_FREE(scanline);
return false;
}
for (z = 0; z < count; ++z) {
scanline[i++ * 4 + k] = stbi__get8(&_context);
}
Expand All @@ -418,7 +450,9 @@ read_pfm(PfmFile &pfm) {
stbi__hdr_convert(hdr_data+(j*width + i)*3, scanline + i*4, 3);
}
}
STBI_FREE(scanline);
if (scanline) {
STBI_FREE(scanline);
}
}

pfm.swap_table(table);
Expand Down Expand Up @@ -460,9 +494,14 @@ read_data(xel *array, xelval *alpha) {
int cols = 0;
int rows = 0;
int comp = _num_channels;
stbi_uc *data = stbi__load_main(&_context, &cols, &rows, &comp, _num_channels);
void *data;
if (_maxval != 65535) {
data = stbi__load_and_postprocess_8bit(&_context, &cols, &rows, &comp, _num_channels);
} else {
data = stbi__load_and_postprocess_16bit(&_context, &cols, &rows, &comp, _num_channels);
}

if (data == NULL) {
if (data == nullptr) {
pnmimage_cat.error()
<< "stbi_load failure: " << stbi_failure_reason() << "\n";
return 0;
Expand All @@ -472,36 +511,67 @@ read_data(xel *array, xelval *alpha) {
nassertr(comp == _num_channels, 0);

size_t pixels = (size_t)_x_size * (size_t)rows;
stbi_uc *ptr = data;
switch (_num_channels) {
case 1:
for (size_t i = 0; i < pixels; ++i) {
PPM_ASSIGN(array[i], ptr[i], ptr[i], ptr[i]);
}
break;
if (_maxval != 65535) {
uint8_t *ptr = (uint8_t *)data;
switch (_num_channels) {
case 1:
for (size_t i = 0; i < pixels; ++i) {
PPM_ASSIGN(array[i], ptr[i], ptr[i], ptr[i]);
}
break;

case 2:
for (size_t i = 0; i < pixels; ++i) {
PPM_ASSIGN(array[i], ptr[0], ptr[0], ptr[0]);
alpha[i] = ptr[1];
ptr += 2;
}
break;
case 2:
for (size_t i = 0; i < pixels; ++i) {
PPM_ASSIGN(array[i], ptr[0], ptr[0], ptr[0]);
alpha[i] = ptr[1];
ptr += 2;
}
break;

case 3:
for (size_t i = 0; i < pixels; ++i) {
PPM_ASSIGN(array[i], ptr[0], ptr[1], ptr[2]);
ptr += 3;
}
break;

case 3:
for (size_t i = 0; i < pixels; ++i) {
PPM_ASSIGN(array[i], ptr[0], ptr[1], ptr[2]);
ptr += 3;
case 4:
for (size_t i = 0; i < pixels; ++i) {
PPM_ASSIGN(array[i], ptr[0], ptr[1], ptr[2]);
alpha[i] = ptr[3];
ptr += 4;
}
break;
}
break;
} else {
uint16_t *ptr = (uint16_t *)data;
switch (_num_channels) {
case 1:
for (size_t i = 0; i < pixels; ++i) {
PPM_ASSIGN(array[i], ptr[i], ptr[i], ptr[i]);
}
break;

case 4:
for (size_t i = 0; i < pixels; ++i) {
PPM_ASSIGN(array[i], ptr[0], ptr[1], ptr[2]);
alpha[i] = ptr[3];
ptr += 4;
case 2:
for (size_t i = 0; i < pixels; ++i) {
PPM_ASSIGN(array[i], ptr[0], ptr[0], ptr[0]);
alpha[i] = ptr[1];
ptr += 2;
}
break;

case 3:
memcpy(array, ptr, pixels * sizeof(uint16_t) * 3);
break;

case 4:
for (size_t i = 0; i < pixels; ++i) {
PPM_ASSIGN(array[i], ptr[0], ptr[1], ptr[2]);
alpha[i] = ptr[3];
ptr += 4;
}
break;
}
break;
}

stbi_image_free(data);
Expand Down

0 comments on commit c52bab1

Please sign in to comment.