Merge branch 'master' into kimkulling/add_windows_clang_issue-5519

kimkulling/add_windows_clang_issue-5519
Kim Kulling 2024-04-18 10:44:44 +01:00 committed by GitHub
commit 2beab55a4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 235 additions and 226 deletions

View File

@ -452,18 +452,20 @@ configure_package_config_file(
INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}" INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}"
) )
install( if(ASSIMP_INSTALL)
install(
FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}" FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}"
DESTINATION "${CONFIG_INSTALL_DIR}" DESTINATION "${CONFIG_INSTALL_DIR}"
COMPONENT ${LIBASSIMP-DEV_COMPONENT} COMPONENT ${LIBASSIMP-DEV_COMPONENT}
) )
install( install(
EXPORT "${TARGETS_EXPORT_NAME}" EXPORT "${TARGETS_EXPORT_NAME}"
NAMESPACE "${NAMESPACE}" NAMESPACE "${NAMESPACE}"
DESTINATION "${CONFIG_INSTALL_DIR}" DESTINATION "${CONFIG_INSTALL_DIR}"
COMPONENT ${LIBASSIMP-DEV_COMPONENT} COMPONENT ${LIBASSIMP-DEV_COMPONENT}
) )
endif()
IF( ASSIMP_BUILD_DOCS ) IF( ASSIMP_BUILD_DOCS )
ADD_SUBDIRECTORY(doc) ADD_SUBDIRECTORY(doc)
@ -481,7 +483,7 @@ IF(ASSIMP_HUNTER_ENABLED)
set(ASSIMP_BUILD_MINIZIP TRUE) set(ASSIMP_BUILD_MINIZIP TRUE)
ELSE() ELSE()
# If the zlib is already found outside, add an export in case assimpTargets can't find it. # If the zlib is already found outside, add an export in case assimpTargets can't find it.
IF( ZLIB_FOUND ) IF( ZLIB_FOUND AND ASSIMP_INSTALL)
INSTALL( TARGETS zlib zlibstatic INSTALL( TARGETS zlib zlibstatic
EXPORT "${TARGETS_EXPORT_NAME}") EXPORT "${TARGETS_EXPORT_NAME}")
ENDIF() ENDIF()
@ -705,6 +707,7 @@ ELSE()
set(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src") set(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src")
# This is probably wrong # This is probably wrong
if (ASSIMP_INSTALL)
INSTALL( TARGETS ${draco_LIBRARIES} INSTALL( TARGETS ${draco_LIBRARIES}
EXPORT "${TARGETS_EXPORT_NAME}" EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
@ -714,6 +717,7 @@ ELSE()
COMPONENT ${LIBASSIMP_COMPONENT} COMPONENT ${LIBASSIMP_COMPONENT}
INCLUDES DESTINATION include INCLUDES DESTINATION include
) )
endif()
ENDIF() ENDIF()
ENDIF() ENDIF()
ENDIF() ENDIF()

View File

@ -1400,19 +1400,20 @@ IF (RT_FOUND AND ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC)
TARGET_LINK_LIBRARIES(assimp rt) TARGET_LINK_LIBRARIES(assimp rt)
ENDIF () ENDIF ()
IF(ASSIMP_INSTALL)
INSTALL( TARGETS assimp INSTALL( TARGETS assimp
EXPORT "${TARGETS_EXPORT_NAME}" EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT} LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP-DEV_COMPONENT} ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP-DEV_COMPONENT}
RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT} RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT} FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}
INCLUDES DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR} INCLUDES DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}
) )
INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev) INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev)
INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev) INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev)
ENDIF()
if (ASSIMP_ANDROID_JNIIOSYSTEM) if (ASSIMP_ANDROID_JNIIOSYSTEM AND ASSIMP_INSTALL)
INSTALL(FILES ${HEADER_PATH}/${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/AndroidJNIIOSystem.h INSTALL(FILES ${HEADER_PATH}/${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/AndroidJNIIOSystem.h
DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}
COMPONENT assimp-dev) COMPONENT assimp-dev)

View File

@ -346,16 +346,20 @@ void ComputeUVMappingProcess::Execute(aiScene *pScene) {
ASSIMP_LOG_DEBUG("GenUVCoordsProcess begin"); ASSIMP_LOG_DEBUG("GenUVCoordsProcess begin");
char buffer[1024]; char buffer[1024];
if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here"); throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
}
std::list<MappingInfo> mappingStack; std::list<MappingInfo> mappingStack;
/* Iterate through all materials and search for non-UV mapped textures // Iterate through all materials and search for non-UV mapped textures
*/
for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) { for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
mappingStack.clear(); mappingStack.clear();
aiMaterial *mat = pScene->mMaterials[i]; aiMaterial *mat = pScene->mMaterials[i];
if (mat == nullptr) {
ASSIMP_LOG_INFO("Material pointer in nullptr, skipping.");
continue;
}
for (unsigned int a = 0; a < mat->mNumProperties; ++a) { for (unsigned int a = 0; a < mat->mNumProperties; ++a) {
aiMaterialProperty *prop = mat->mProperties[a]; aiMaterialProperty *prop = mat->mProperties[a];
if (!::strcmp(prop->mKey.data, "$tex.mapping")) { if (!::strcmp(prop->mKey.data, "$tex.mapping")) {

View File

@ -81,27 +81,26 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) {
// Find out which materials are referenced by meshes // Find out which materials are referenced by meshes
std::vector<bool> abReferenced(pScene->mNumMaterials,false); std::vector<bool> abReferenced(pScene->mNumMaterials,false);
for (unsigned int i = 0;i < pScene->mNumMeshes;++i) for (unsigned int i = 0;i < pScene->mNumMeshes;++i) {
abReferenced[pScene->mMeshes[i]->mMaterialIndex] = true; abReferenced[pScene->mMeshes[i]->mMaterialIndex] = true;
}
// If a list of materials to be excluded was given, match the list with // If a list of materials to be excluded was given, match the list with
// our imported materials and 'salt' all positive matches to ensure that // our imported materials and 'salt' all positive matches to ensure that
// we get unique hashes later. // we get unique hashes later.
if (mConfigFixedMaterials.length()) { if (mConfigFixedMaterials.length()) {
std::list<std::string> strings; std::list<std::string> strings;
ConvertListToStrings(mConfigFixedMaterials,strings); ConvertListToStrings(mConfigFixedMaterials,strings);
for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
aiMaterial* mat = pScene->mMaterials[i]; aiMaterial* mat = pScene->mMaterials[i];
ai_assert(mat != nullptr);
aiString name; aiString name;
mat->Get(AI_MATKEY_NAME,name); mat->Get(AI_MATKEY_NAME,name);
if (name.length) { if (name.length != 0) {
std::list<std::string>::const_iterator it = std::find(strings.begin(), strings.end(), name.data); std::list<std::string>::const_iterator it = std::find(strings.begin(), strings.end(), name.data);
if (it != strings.end()) { if (it != strings.end()) {
// Our brilliant 'salt': A single material property with ~ as first // Our brilliant 'salt': A single material property with ~ as first
// character to mark it as internal and temporary. // character to mark it as internal and temporary.
const int dummy = 1; const int dummy = 1;
@ -126,7 +125,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) {
// store all hashes in a list and so a quick search whether // store all hashes in a list and so a quick search whether
// we do already have a specific hash. This allows us to // we do already have a specific hash. This allows us to
// determine which materials are identical. // determine which materials are identical.
uint32_t *aiHashes = new uint32_t[ pScene->mNumMaterials ];; uint32_t *aiHashes = new uint32_t[ pScene->mNumMaterials ];
for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
// No mesh is referencing this material, remove it. // No mesh is referencing this material, remove it.
if (!abReferenced[i]) { if (!abReferenced[i]) {
@ -157,15 +156,16 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) {
// If the new material count differs from the original, // If the new material count differs from the original,
// we need to rebuild the material list and remap mesh material indexes. // we need to rebuild the material list and remap mesh material indexes.
if (iNewNum < 1) { if (iNewNum < 1) {
//throw DeadlyImportError("No materials remaining"); delete [] aiMappingTable;
delete [] aiHashes;
pScene->mNumMaterials = 0;
return; return;
} }
if (iNewNum != pScene->mNumMaterials) { if (iNewNum != pScene->mNumMaterials) {
ai_assert(iNewNum > 0); ai_assert(iNewNum > 0);
aiMaterial** ppcMaterials = new aiMaterial*[iNewNum]; aiMaterial** ppcMaterials = new aiMaterial*[iNewNum];
::memset(ppcMaterials,0,sizeof(void*)*iNewNum); ::memset(ppcMaterials,0,sizeof(void*)*iNewNum);
for (unsigned int p = 0; p < pScene->mNumMaterials;++p) for (unsigned int p = 0; p < pScene->mNumMaterials;++p) {
{
// if the material is not referenced ... remove it // if the material is not referenced ... remove it
if (!abReferenced[p]) { if (!abReferenced[p]) {
continue; continue;

View File

@ -1,4 +1,4 @@
/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb /* stb_image - v2.29 - public domain image loader - http://nothings.org/stb
no warranty implied; use at your own risk no warranty implied; use at your own risk
Do this: Do this:
@ -48,6 +48,7 @@ LICENSE
RECENT REVISION HISTORY: RECENT REVISION HISTORY:
2.29 (2023-05-xx) optimizations
2.28 (2023-01-29) many error fixes, security errors, just tons of stuff 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff
2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes
2.26 (2020-07-13) many minor fixes 2.26 (2020-07-13) many minor fixes
@ -1072,8 +1073,8 @@ static int stbi__addints_valid(int a, int b)
return a <= INT_MAX - b; return a <= INT_MAX - b;
} }
// returns 1 if the product of two signed shorts is valid, 0 on overflow. // returns 1 if the product of two ints fits in a signed short, 0 on overflow.
static int stbi__mul2shorts_valid(short a, short b) static int stbi__mul2shorts_valid(int a, int b)
{ {
if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow
if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid
@ -3384,13 +3385,13 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
return 1; return 1;
} }
static int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j)
{ {
// some JPEGs have junk at end, skip over it but if we find what looks // some JPEGs have junk at end, skip over it but if we find what looks
// like a valid marker, resume there // like a valid marker, resume there
while (!stbi__at_eof(j->s)) { while (!stbi__at_eof(j->s)) {
int x = stbi__get8(j->s); stbi_uc x = stbi__get8(j->s);
while (x == 255) { // might be a marker while (x == 0xff) { // might be a marker
if (stbi__at_eof(j->s)) return STBI__MARKER_none; if (stbi__at_eof(j->s)) return STBI__MARKER_none;
x = stbi__get8(j->s); x = stbi__get8(j->s);
if (x != 0x00 && x != 0xff) { if (x != 0x00 && x != 0xff) {
@ -4176,6 +4177,7 @@ typedef struct
{ {
stbi_uc *zbuffer, *zbuffer_end; stbi_uc *zbuffer, *zbuffer_end;
int num_bits; int num_bits;
int hit_zeof_once;
stbi__uint32 code_buffer; stbi__uint32 code_buffer;
char *zout; char *zout;
@ -4242,10 +4244,21 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
int b,s; int b,s;
if (a->num_bits < 16) { if (a->num_bits < 16) {
if (stbi__zeof(a)) { if (stbi__zeof(a)) {
return -1; /* report error for unexpected end of data. */ if (!a->hit_zeof_once) {
// This is the first time we hit eof, insert 16 extra padding btis
// to allow us to keep going; if we actually consume any of them
// though, that is invalid data. This is caught later.
a->hit_zeof_once = 1;
a->num_bits += 16; // add 16 implicit zero bits
} else {
// We already inserted our extra 16 padding bits and are again
// out, this stream is actually prematurely terminated.
return -1;
} }
} else {
stbi__fill_bits(a); stbi__fill_bits(a);
} }
}
b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
if (b) { if (b) {
s = b >> 9; s = b >> 9;
@ -4309,6 +4322,13 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
int len,dist; int len,dist;
if (z == 256) { if (z == 256) {
a->zout = zout; a->zout = zout;
if (a->hit_zeof_once && a->num_bits < 16) {
// The first time we hit zeof, we inserted 16 extra zero bits into our bit
// buffer so the decoder can just do its speculative decoding. But if we
// actually consumed any of those bits (which is the case when num_bits < 16),
// the stream actually read past the end so it is malformed.
return stbi__err("unexpected end","Corrupt PNG");
}
return 1; return 1;
} }
if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data
@ -4320,7 +4340,7 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
dist = stbi__zdist_base[z]; dist = stbi__zdist_base[z];
if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]);
if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG");
if (zout + len > a->zout_end) { if (len > a->zout_end - zout) {
if (!stbi__zexpand(a, zout, len)) return 0; if (!stbi__zexpand(a, zout, len)) return 0;
zout = a->zout; zout = a->zout;
} }
@ -4464,6 +4484,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
if (!stbi__parse_zlib_header(a)) return 0; if (!stbi__parse_zlib_header(a)) return 0;
a->num_bits = 0; a->num_bits = 0;
a->code_buffer = 0; a->code_buffer = 0;
a->hit_zeof_once = 0;
do { do {
final = stbi__zreceive(a,1); final = stbi__zreceive(a,1);
type = stbi__zreceive(a,2); type = stbi__zreceive(a,2);
@ -4619,9 +4640,8 @@ enum {
STBI__F_up=2, STBI__F_up=2,
STBI__F_avg=3, STBI__F_avg=3,
STBI__F_paeth=4, STBI__F_paeth=4,
// synthetic filters used for first scanline to avoid needing a dummy row of 0s // synthetic filter used for first scanline to avoid needing a dummy row of 0s
STBI__F_avg_first, STBI__F_avg_first
STBI__F_paeth_first
}; };
static stbi_uc first_row_filter[5] = static stbi_uc first_row_filter[5] =
@ -4630,29 +4650,56 @@ static stbi_uc first_row_filter[5] =
STBI__F_sub, STBI__F_sub,
STBI__F_none, STBI__F_none,
STBI__F_avg_first, STBI__F_avg_first,
STBI__F_paeth_first STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub
}; };
static int stbi__paeth(int a, int b, int c) static int stbi__paeth(int a, int b, int c)
{ {
int p = a + b - c; // This formulation looks very different from the reference in the PNG spec, but is
int pa = abs(p-a); // actually equivalent and has favorable data dependencies and admits straightforward
int pb = abs(p-b); // generation of branch-free code, which helps performance significantly.
int pc = abs(p-c); int thresh = c*3 - (a + b);
if (pa <= pb && pa <= pc) return a; int lo = a < b ? a : b;
if (pb <= pc) return b; int hi = a < b ? b : a;
return c; int t0 = (hi <= thresh) ? lo : c;
int t1 = (thresh <= lo) ? hi : t0;
return t1;
} }
static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 };
// adds an extra all-255 alpha channel
// dest == src is legal
// img_n must be 1 or 3
static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n)
{
int i;
// must process data backwards since we allow dest==src
if (img_n == 1) {
for (i=x-1; i >= 0; --i) {
dest[i*2+1] = 255;
dest[i*2+0] = src[i];
}
} else {
STBI_ASSERT(img_n == 3);
for (i=x-1; i >= 0; --i) {
dest[i*4+3] = 255;
dest[i*4+2] = src[i*3+2];
dest[i*4+1] = src[i*3+1];
dest[i*4+0] = src[i*3+0];
}
}
}
// create the png data from post-deflated data // create the png data from post-deflated data
static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
{ {
int bytes = (depth == 16? 2 : 1); int bytes = (depth == 16 ? 2 : 1);
stbi__context *s = a->s; stbi__context *s = a->s;
stbi__uint32 i,j,stride = x*out_n*bytes; stbi__uint32 i,j,stride = x*out_n*bytes;
stbi__uint32 img_len, img_width_bytes; stbi__uint32 img_len, img_width_bytes;
stbi_uc *filter_buf;
int all_ok = 1;
int k; int k;
int img_n = s->img_n; // copy it into a local for later int img_n = s->img_n; // copy it into a local for later
@ -4664,8 +4711,11 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
if (!a->out) return stbi__err("outofmem", "Out of memory"); if (!a->out) return stbi__err("outofmem", "Out of memory");
// note: error exits here don't need to clean up a->out individually,
// stbi__do_png always does on error.
if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG");
img_width_bytes = (((img_n * x * depth) + 7) >> 3); img_width_bytes = (((img_n * x * depth) + 7) >> 3);
if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG");
img_len = (img_width_bytes + 1) * y; img_len = (img_width_bytes + 1) * y;
// we used to check for exact match between raw_len and img_len on non-interlaced PNGs, // we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
@ -4673,188 +4723,136 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
// so just check for raw_len < img_len always. // so just check for raw_len < img_len always.
if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
for (j=0; j < y; ++j) { // Allocate two scan lines worth of filter workspace buffer.
stbi_uc *cur = a->out + stride*j; filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0);
stbi_uc *prior; if (!filter_buf) return stbi__err("outofmem", "Out of memory");
int filter = *raw++;
if (filter > 4)
return stbi__err("invalid filter","Corrupt PNG");
// Filtering for low-bit-depth images
if (depth < 8) { if (depth < 8) {
if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG");
cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
filter_bytes = 1; filter_bytes = 1;
width = img_width_bytes; width = img_width_bytes;
} }
prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above
for (j=0; j < y; ++j) {
// cur/prior filter buffers alternate
stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes;
stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes;
stbi_uc *dest = a->out + stride*j;
int nk = width * filter_bytes;
int filter = *raw++;
// check filter type
if (filter > 4) {
all_ok = stbi__err("invalid filter","Corrupt PNG");
break;
}
// if first row, use special filter that doesn't sample previous row // if first row, use special filter that doesn't sample previous row
if (j == 0) filter = first_row_filter[filter]; if (j == 0) filter = first_row_filter[filter];
// handle first byte explicitly // perform actual filtering
for (k=0; k < filter_bytes; ++k) {
switch (filter) { switch (filter) {
case STBI__F_none : cur[k] = raw[k]; break; case STBI__F_none:
case STBI__F_sub : cur[k] = raw[k]; break; memcpy(cur, raw, nk);
case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; break;
case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; case STBI__F_sub:
case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; memcpy(cur, raw, filter_bytes);
case STBI__F_avg_first : cur[k] = raw[k]; break; for (k = filter_bytes; k < nk; ++k)
case STBI__F_paeth_first: cur[k] = raw[k]; break; cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]);
} break;
case STBI__F_up:
for (k = 0; k < nk; ++k)
cur[k] = STBI__BYTECAST(raw[k] + prior[k]);
break;
case STBI__F_avg:
for (k = 0; k < filter_bytes; ++k)
cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1));
for (k = filter_bytes; k < nk; ++k)
cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1));
break;
case STBI__F_paeth:
for (k = 0; k < filter_bytes; ++k)
cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0)
for (k = filter_bytes; k < nk; ++k)
cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes]));
break;
case STBI__F_avg_first:
memcpy(cur, raw, filter_bytes);
for (k = filter_bytes; k < nk; ++k)
cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1));
break;
} }
if (depth == 8) {
if (img_n != out_n)
cur[img_n] = 255; // first pixel
raw += img_n;
cur += out_n;
prior += out_n;
} else if (depth == 16) {
if (img_n != out_n) {
cur[filter_bytes] = 255; // first pixel top byte
cur[filter_bytes+1] = 255; // first pixel bottom byte
}
raw += filter_bytes;
cur += output_bytes;
prior += output_bytes;
} else {
raw += 1;
cur += 1;
prior += 1;
}
// this is a little gross, so that we don't switch per-pixel or per-component
if (depth < 8 || img_n == out_n) {
int nk = (width - 1)*filter_bytes;
#define STBI__CASE(f) \
case f: \
for (k=0; k < nk; ++k)
switch (filter) {
// "none" filter turns into a memcpy here; make that explicit.
case STBI__F_none: memcpy(cur, raw, nk); break;
STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break;
STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break;
STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break;
STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break;
STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break;
}
#undef STBI__CASE
raw += nk; raw += nk;
// expand decoded bits in cur to dest, also adding an extra alpha channel if desired
if (depth < 8) {
stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
stbi_uc *in = cur;
stbi_uc *out = dest;
stbi_uc inb = 0;
stbi__uint32 nsmp = x*img_n;
// expand bits to bytes first
if (depth == 4) {
for (i=0; i < nsmp; ++i) {
if ((i & 1) == 0) inb = *in++;
*out++ = scale * (inb >> 4);
inb <<= 4;
}
} else if (depth == 2) {
for (i=0; i < nsmp; ++i) {
if ((i & 3) == 0) inb = *in++;
*out++ = scale * (inb >> 6);
inb <<= 2;
}
} else {
STBI_ASSERT(depth == 1);
for (i=0; i < nsmp; ++i) {
if ((i & 7) == 0) inb = *in++;
*out++ = scale * (inb >> 7);
inb <<= 1;
}
}
// insert alpha=255 values if desired
if (img_n != out_n)
stbi__create_png_alpha_expand8(dest, dest, x, img_n);
} else if (depth == 8) {
if (img_n == out_n)
memcpy(dest, cur, x*img_n);
else
stbi__create_png_alpha_expand8(dest, cur, x, img_n);
} else if (depth == 16) {
// convert the image data from big-endian to platform-native
stbi__uint16 *dest16 = (stbi__uint16*)dest;
stbi__uint32 nsmp = x*img_n;
if (img_n == out_n) {
for (i = 0; i < nsmp; ++i, ++dest16, cur += 2)
*dest16 = (cur[0] << 8) | cur[1];
} else { } else {
STBI_ASSERT(img_n+1 == out_n); STBI_ASSERT(img_n+1 == out_n);
#define STBI__CASE(f) \
case f: \
for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
for (k=0; k < filter_bytes; ++k)
switch (filter) {
STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break;
STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break;
STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break;
STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break;
STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break;
STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break;
}
#undef STBI__CASE
// the loop above sets the high byte of the pixels' alpha, but for
// 16 bit png files we also need the low byte set. we'll do that here.
if (depth == 16) {
cur = a->out + stride*j; // start at the beginning of the row again
for (i=0; i < x; ++i,cur+=output_bytes) {
cur[filter_bytes+1] = 255;
}
}
}
}
// we make a separate pass to expand bits to pixels; for performance,
// this could run two scanlines behind the above code, so it won't
// intefere with filtering but will still be in the cache.
if (depth < 8) {
for (j=0; j < y; ++j) {
stbi_uc *cur = a->out + stride*j;
stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes;
// unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit
// png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop
stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
// note that the final byte might overshoot and write more data than desired.
// we can allocate enough data that this never writes out of memory, but it
// could also overwrite the next scanline. can it overwrite non-empty data
// on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel.
// so we need to explicitly clamp the final ones
if (depth == 4) {
for (k=x*img_n; k >= 2; k-=2, ++in) {
*cur++ = scale * ((*in >> 4) );
*cur++ = scale * ((*in ) & 0x0f);
}
if (k > 0) *cur++ = scale * ((*in >> 4) );
} else if (depth == 2) {
for (k=x*img_n; k >= 4; k-=4, ++in) {
*cur++ = scale * ((*in >> 6) );
*cur++ = scale * ((*in >> 4) & 0x03);
*cur++ = scale * ((*in >> 2) & 0x03);
*cur++ = scale * ((*in ) & 0x03);
}
if (k > 0) *cur++ = scale * ((*in >> 6) );
if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03);
if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03);
} else if (depth == 1) {
for (k=x*img_n; k >= 8; k-=8, ++in) {
*cur++ = scale * ((*in >> 7) );
*cur++ = scale * ((*in >> 6) & 0x01);
*cur++ = scale * ((*in >> 5) & 0x01);
*cur++ = scale * ((*in >> 4) & 0x01);
*cur++ = scale * ((*in >> 3) & 0x01);
*cur++ = scale * ((*in >> 2) & 0x01);
*cur++ = scale * ((*in >> 1) & 0x01);
*cur++ = scale * ((*in ) & 0x01);
}
if (k > 0) *cur++ = scale * ((*in >> 7) );
if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01);
if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01);
if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01);
if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01);
if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01);
if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01);
}
if (img_n != out_n) {
int q;
// insert alpha = 255
cur = a->out + stride*j;
if (img_n == 1) { if (img_n == 1) {
for (q=x-1; q >= 0; --q) { for (i = 0; i < x; ++i, dest16 += 2, cur += 2) {
cur[q*2+1] = 255; dest16[0] = (cur[0] << 8) | cur[1];
cur[q*2+0] = cur[q]; dest16[1] = 0xffff;
} }
} else { } else {
STBI_ASSERT(img_n == 3); STBI_ASSERT(img_n == 3);
for (q=x-1; q >= 0; --q) { for (i = 0; i < x; ++i, dest16 += 4, cur += 6) {
cur[q*4+3] = 255; dest16[0] = (cur[0] << 8) | cur[1];
cur[q*4+2] = cur[q*3+2]; dest16[1] = (cur[2] << 8) | cur[3];
cur[q*4+1] = cur[q*3+1]; dest16[2] = (cur[4] << 8) | cur[5];
cur[q*4+0] = cur[q*3+0]; dest16[3] = 0xffff;
}
} }
} }
} }
} }
} else if (depth == 16) {
// force the image data from big-endian to platform-native.
// this is done in a separate pass due to the decoding relying
// on the data being untouched, but could probably be done
// per-line during decode if care is taken.
stbi_uc *cur = a->out;
stbi__uint16 *cur16 = (stbi__uint16*)cur;
for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { STBI_FREE(filter_buf);
*cur16 = (cur[0] << 8) | cur[1]; if (!all_ok) return 0;
}
}
return 1; return 1;
} }

View File

@ -198,9 +198,11 @@ endif(MINGW)
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
INSTALL( TARGETS zlibstatic IF(ASSIMP_INSTALL)
INSTALL( TARGETS zlibstatic
EXPORT "${TARGETS_EXPORT_NAME}" EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
COMPONENT ${LIBASSIMP_COMPONENT}) COMPONENT ${LIBASSIMP_COMPONENT})
ENDIF()