Migrate more importers to compression class

pull/4381/head
Kim Kulling 2022-02-08 20:43:47 +01:00
parent eb5a7938e0
commit 27bcddfb1a
6 changed files with 58 additions and 66 deletions

View File

@ -66,11 +66,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// zlib is needed for compressed blend files // zlib is needed for compressed blend files
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
# ifdef ASSIMP_BUILD_NO_OWN_ZLIB #include "Common/Compression.h"
/* #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h> # include <zlib.h>
# else # else
# include "../contrib/zlib/zlib.h" # include "../contrib/zlib/zlib.h"
# endif # endif*/
#endif #endif
namespace Assimp { namespace Assimp {
@ -141,7 +142,7 @@ void BlenderImporter::SetupProperties(const Importer * /*pImp*/) {
void BlenderImporter::InternReadFile(const std::string &pFile, void BlenderImporter::InternReadFile(const std::string &pFile,
aiScene *pScene, IOSystem *pIOHandler) { aiScene *pScene, IOSystem *pIOHandler) {
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
std::vector<Bytef> uncompressed; std::vector<char> uncompressed;
#endif #endif
FileDatabase file; FileDatabase file;
@ -159,7 +160,6 @@ void BlenderImporter::InternReadFile(const std::string &pFile,
#ifdef ASSIMP_BUILD_NO_COMPRESSED_BLEND #ifdef ASSIMP_BUILD_NO_COMPRESSED_BLEND
ThrowException("BLENDER magic bytes are missing, is this file compressed (Assimp was built without decompression support)?"); ThrowException("BLENDER magic bytes are missing, is this file compressed (Assimp was built without decompression support)?");
#else #else
if (magic[0] != 0x1f || static_cast<uint8_t>(magic[1]) != 0x8b) { if (magic[0] != 0x1f || static_cast<uint8_t>(magic[1]) != 0x8b) {
ThrowException("BLENDER magic bytes are missing, couldn't find GZIP header either"); ThrowException("BLENDER magic bytes are missing, couldn't find GZIP header either");
} }
@ -173,42 +173,12 @@ void BlenderImporter::InternReadFile(const std::string &pFile,
stream->Seek(0L, aiOrigin_SET); stream->Seek(0L, aiOrigin_SET);
std::shared_ptr<StreamReaderLE> reader = std::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream)); std::shared_ptr<StreamReaderLE> reader = std::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
// build a zlib stream size_t total = 0;
z_stream zstream; Compression compression;
zstream.opaque = Z_NULL; if (compression.open(Compression::Format::Binary)) {
zstream.zalloc = Z_NULL; total = compression.decompress((unsigned char *)reader->GetPtr(), reader->GetRemainingSize(), uncompressed);
zstream.zfree = Z_NULL; compression.close();
zstream.data_type = Z_BINARY; }
// http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib
inflateInit2(&zstream, 16 + MAX_WBITS);
zstream.next_in = reinterpret_cast<Bytef *>(reader->GetPtr());
zstream.avail_in = (uInt)reader->GetRemainingSize();
size_t total = 0l;
// TODO: be smarter about this, decompress directly into heap buffer
// and decompress the data .... do 1k chunks in the hope that we won't kill the stack
#define MYBLOCK 1024
Bytef block[MYBLOCK];
int ret;
do {
zstream.avail_out = MYBLOCK;
zstream.next_out = block;
ret = inflate(&zstream, Z_NO_FLUSH);
if (ret != Z_STREAM_END && ret != Z_OK) {
ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .BLEND file");
}
const size_t have = MYBLOCK - zstream.avail_out;
total += have;
uncompressed.resize(total);
memcpy(uncompressed.data() + total - have, block, have);
} while (ret != Z_STREAM_END);
// terminate zlib
inflateEnd(&zstream);
// replace the input stream with a memory stream // replace the input stream with a memory stream
stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t *>(uncompressed.data()), total)); stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t *>(uncompressed.data()), total));

View File

@ -46,11 +46,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB //#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h> #include "Common/Compression.h"
/*# include <zlib.h>
#else #else
# include "../contrib/zlib/zlib.h" # include "../contrib/zlib/zlib.h"
#endif #endif*/
#include "FBXTokenizer.h" #include "FBXTokenizer.h"
#include "FBXParser.h" #include "FBXParser.h"
@ -571,8 +572,11 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha
else if(encmode == 1) { else if(encmode == 1) {
// zlib/deflate, next comes ZIP head (0x78 0x01) // zlib/deflate, next comes ZIP head (0x78 0x01)
// see http://www.ietf.org/rfc/rfc1950.txt // see http://www.ietf.org/rfc/rfc1950.txt
Compression compress;
z_stream zstream; if (compress.open(Compression::Format::Binary)) {
compress.decompress(data, comp_len, buff);
}
/* z_stream zstream;
zstream.opaque = Z_NULL; zstream.opaque = Z_NULL;
zstream.zalloc = Z_NULL; zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL; zstream.zfree = Z_NULL;
@ -581,9 +585,9 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha
// http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib // http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib
if(Z_OK != inflateInit(&zstream)) { if(Z_OK != inflateInit(&zstream)) {
ParseError("failure initializing zlib"); ParseError("failure initializing zlib");
} }*/
zstream.next_in = reinterpret_cast<Bytef*>( const_cast<char*>(data) ); /* zstream.next_in = reinterpret_cast<Bytef *>(const_cast<char *>(data));
zstream.avail_in = comp_len; zstream.avail_in = comp_len;
zstream.avail_out = static_cast<uInt>(buff.size()); zstream.avail_out = static_cast<uInt>(buff.size());
@ -595,7 +599,7 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha
} }
// terminate zlib // terminate zlib
inflateEnd(&zstream); inflateEnd(&zstream);*/
} }
#ifdef ASSIMP_BUILD_DEBUG #ifdef ASSIMP_BUILD_DEBUG
else { else {

View File

@ -60,11 +60,12 @@ using namespace Assimp::Formatter;
#ifndef ASSIMP_BUILD_NO_COMPRESSED_X #ifndef ASSIMP_BUILD_NO_COMPRESSED_X
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB /* #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
#include <zlib.h> #include <zlib.h>
#else #else
#include "../contrib/zlib/zlib.h" #include "../contrib/zlib/zlib.h"
#endif #endif*/
#include "Common/Compression.h"
// Magic identifier for MSZIP compressed data // Magic identifier for MSZIP compressed data
#define MSZIP_MAGIC 0x4B43 #define MSZIP_MAGIC 0x4B43
@ -72,13 +73,13 @@ using namespace Assimp::Formatter;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Dummy memory wrappers for use with zlib // Dummy memory wrappers for use with zlib
static void *dummy_alloc(void * /*opaque*/, unsigned int items, unsigned int size) { /* static void *dummy_alloc(void * opaque, unsigned int items, unsigned int size) {
return ::operator new(items *size); return ::operator new(items *size);
} }
static void dummy_free(void * /*opaque*/, void *address) { static void dummy_free(void * opaque, void *address) {
return ::operator delete(address); return ::operator delete(address);
} }*/
#endif // !! ASSIMP_BUILD_NO_COMPRESSED_X #endif // !! ASSIMP_BUILD_NO_COMPRESSED_X
@ -171,15 +172,16 @@ XFileParser::XFileParser(const std::vector<char> &pBuffer) :
* /////////////////////////////////////////////////////////////////////// * ///////////////////////////////////////////////////////////////////////
*/ */
Compression compression;
// build a zlib stream // build a zlib stream
z_stream stream; /* z_stream stream;
stream.opaque = nullptr; stream.opaque = nullptr;
stream.zalloc = &dummy_alloc; stream.zalloc = &dummy_alloc;
stream.zfree = &dummy_free; stream.zfree = &dummy_free;
stream.data_type = (mIsBinaryFormat ? Z_BINARY : Z_ASCII); stream.data_type = (mIsBinaryFormat ? Z_BINARY : Z_ASCII);
// initialize the inflation algorithm // initialize the inflation algorithm
::inflateInit2(&stream, -MAX_WBITS); ::inflateInit2(&stream, -MAX_WBITS);*/
// skip unknown data (checksum, flags?) // skip unknown data (checksum, flags?)
mP += 6; mP += 6;
@ -213,7 +215,12 @@ XFileParser::XFileParser(const std::vector<char> &pBuffer) :
// Allocate storage and terminating zero and do the actual uncompressing // Allocate storage and terminating zero and do the actual uncompressing
uncompressed.resize(est_out + 1); uncompressed.resize(est_out + 1);
char *out = &uncompressed.front(); char *out = &uncompressed.front();
while (mP + 3 < mEnd) {
if (compression.open(mIsBinaryFormat ? Compression::Format::Binary : Compression::Format::ASCII)) {
compression.decompress(mP, std::distance(mP, mEnd-3), uncompressed);
compression.close();
}
/* while (mP + 3 < mEnd) {
uint16_t ofs = *((uint16_t *)mP); uint16_t ofs = *((uint16_t *)mP);
AI_SWAP2(ofs); AI_SWAP2(ofs);
mP += 4; mP += 4;
@ -242,7 +249,7 @@ XFileParser::XFileParser(const std::vector<char> &pBuffer) :
} }
// terminate zlib // terminate zlib
::inflateEnd(&stream); ::inflateEnd(&stream);*/
// ok, update pointers to point to the uncompressed file data // ok, update pointers to point to the uncompressed file data
mP = &uncompressed[0]; mP = &uncompressed[0];

View File

@ -112,7 +112,7 @@ const aiImporterDesc *XGLImporter::GetInfo() const {
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL #ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
std::vector<unsigned char> uncompressed; std::vector<char> uncompressed;
#endif #endif
m_scene = pScene; m_scene = pScene;
@ -132,7 +132,7 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
Compression c; Compression c;
size_t total = 0l; size_t total = 0l;
if (c.open()) { if (c.open(Compression::Format::Binary)) {
// skip two extra bytes, zgl files do carry a crc16 upfront (I think) // skip two extra bytes, zgl files do carry a crc16 upfront (I think)
raw_reader->IncPtr(2); raw_reader->IncPtr(2);
total = c.decompress((unsigned char *)raw_reader->GetPtr(), raw_reader->GetRemainingSize(), uncompressed); total = c.decompress((unsigned char *)raw_reader->GetPtr(), raw_reader->GetRemainingSize(), uncompressed);

View File

@ -70,7 +70,7 @@ Compression::~Compression() {
delete mImpl; delete mImpl;
} }
bool Compression::open() { bool Compression::open(Format format) {
ai_assert(mImpl != nullptr); ai_assert(mImpl != nullptr);
if (mImpl->mOpen) { if (mImpl->mOpen) {
@ -81,7 +81,11 @@ bool Compression::open() {
mImpl->mZSstream.opaque = Z_NULL; mImpl->mZSstream.opaque = Z_NULL;
mImpl->mZSstream.zalloc = Z_NULL; mImpl->mZSstream.zalloc = Z_NULL;
mImpl->mZSstream.zfree = Z_NULL; mImpl->mZSstream.zfree = Z_NULL;
mImpl->mZSstream.data_type = Z_BINARY; if (format == Format::Binary) {
mImpl->mZSstream.data_type = Z_BINARY;
} else {
mImpl->mZSstream.data_type = Z_ASCII;
}
// raw decompression without a zlib or gzip header // raw decompression without a zlib or gzip header
inflateInit2(&mImpl->mZSstream, -MAX_WBITS); inflateInit2(&mImpl->mZSstream, -MAX_WBITS);
@ -90,12 +94,12 @@ bool Compression::open() {
return mImpl->mOpen; return mImpl->mOpen;
} }
constexpr size_t MYBLOCK = 1024; constexpr size_t MYBLOCK = 32786;
size_t Compression::decompress(unsigned char *data, size_t in, std::vector<unsigned char> &uncompressed) { size_t Compression::decompress(const void *data, size_t in, std::vector<char> &uncompressed) {
ai_assert(mImpl != nullptr); ai_assert(mImpl != nullptr);
mImpl->mZSstream.next_in = reinterpret_cast<Bytef *>(data); mImpl->mZSstream.next_in = (Bytef*)(data);
mImpl->mZSstream.avail_in = (uInt)in; mImpl->mZSstream.avail_in = (uInt)in;
Bytef block[MYBLOCK] = {}; Bytef block[MYBLOCK] = {};

View File

@ -48,6 +48,13 @@ namespace Assimp {
/// @brief This class provides the decompression of zlib-compressed data. /// @brief This class provides the decompression of zlib-compressed data.
class Compression { class Compression {
public: public:
enum class Format {
Binary = 0,
ASCII,
NumFormats,
InvalidFormat
};
/// @brief The class constructor. /// @brief The class constructor.
Compression(); Compression();
@ -56,7 +63,7 @@ public:
/// @brief Will open the access to the compression. /// @brief Will open the access to the compression.
/// @return true if close was successful, false if not. /// @return true if close was successful, false if not.
bool open(); bool open(Format format);
/// @brief Will return the open state. /// @brief Will return the open state.
/// @return true if the access is opened, false if not. /// @return true if the access is opened, false if not.
@ -70,7 +77,7 @@ public:
/// @param[in] data The data to decompress /// @param[in] data The data to decompress
/// @param[in] in The size of the data. /// @param[in] in The size of the data.
/// @param[out uncompressed A std::vector containing the decompressed data. /// @param[out uncompressed A std::vector containing the decompressed data.
size_t decompress(unsigned char *data, size_t in, std::vector<unsigned char> &uncompressed); size_t decompress(const void *data, size_t in, std::vector<char> &uncompressed);
private: private:
struct impl; struct impl;