Merge pull request #2242 from mjerabek/a-bunch-of-fixes

Fix compressed assbin load/export, 3DS loader hardening, ...
pull/2249/head
Kim Kulling 2018-11-30 09:24:52 +01:00 committed by GitHub
commit d94c2a4b10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 101 additions and 104 deletions

View File

@ -170,7 +170,7 @@ IF(NOT IGNORE_GIT_HASH)
# Get the latest abbreviated commit hash of the working branch
EXECUTE_PROCESS(
COMMAND git log -1 --format=%h --no-show-signature
COMMAND git rev-parse --short=8 HEAD
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE

View File

@ -161,19 +161,21 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler)
{
StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
this->stream = &stream;
// We should have at least one chunk
if (stream.GetRemainingSize() < 16) {
throw DeadlyImportError("3DS file is either empty or corrupt: " + pFile);
}
this->stream = &stream;
// Allocate our temporary 3DS representation
mScene = new D3DS::Scene();
D3DS::Scene _scene;
mScene = &_scene;
// Initialize members
D3DS::Node _rootNode("UNNAMED");
mLastNodeIndex = -1;
mCurrentNode = new D3DS::Node("UNNAMED");
mCurrentNode = &_rootNode;
mRootNode = mCurrentNode;
mRootNode->mHierarchyPos = -1;
mRootNode->mHierarchyIndex = -1;
@ -193,7 +195,6 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
// file.
for (auto &mesh : mScene->mMeshes) {
if (mesh.mFaces.size() > 0 && mesh.mPositions.size() == 0) {
delete mScene;
throw DeadlyImportError("3DS file contains faces but no vertices: " + pFile);
}
CheckIndices(mesh);
@ -201,7 +202,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
ComputeNormalsWithSmoothingsGroups<D3DS::Face>(mesh);
}
// Replace all occurrences of the default material with a
// Replace all occurences of the default material with a
// valid material. Generate it if no material containing
// DEFAULT in its name has been found in the file
ReplaceDefaultMaterial();
@ -218,10 +219,8 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
// Now apply the master scaling factor to the scene
ApplyMasterScale(pScene);
// Delete our internal scene representation and the root
// node, so the whole hierarchy will follow
delete mRootNode;
delete mScene;
// Our internal scene representation and the root
// node will be automatically deleted, so the whole hierarchy will follow
AI_DEBUG_INVALIDATE_PTR(mRootNode);
AI_DEBUG_INVALIDATE_PTR(mScene);

View File

@ -89,7 +89,7 @@ size_t Write<unsigned int>(IOStream * stream, const unsigned int& w) {
const uint32_t t = (uint32_t)w;
if (w > t) {
// this shouldn't happen, integers in Assimp data structures never exceed 2^32
throw new DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion");
throw DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion");
}
stream->Write(&t,4,1);
@ -805,10 +805,16 @@ public:
WriteBinaryScene( &uncompressedStream, pScene );
uLongf uncompressedSize = static_cast<uLongf>(uncompressedStream.Tell());
uLongf compressedSize = (uLongf)(uncompressedStream.Tell() * 1.001 + 12.);
uLongf compressedSize = (uLongf)compressBound(uncompressedSize);
uint8_t* compressedBuffer = new uint8_t[ compressedSize ];
compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 );
int res = compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 );
if(res != Z_OK)
{
delete [] compressedBuffer;
pIOSystem->Close(out);
throw DeadlyExportError("Compression failed.");
}
out->Write( &uncompressedSize, sizeof(uint32_t), 1 );
out->Write( compressedBuffer, sizeof(char), compressedSize );

View File

@ -57,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/anim.h>
#include <assimp/scene.h>
#include <assimp/importerdesc.h>
#include <memory>
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h>
@ -103,7 +104,9 @@ bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bo
template <typename T>
T Read(IOStream * stream) {
T t;
stream->Read( &t, sizeof(T), 1 );
size_t res = stream->Read( &t, sizeof(T), 1 );
if(res != 1)
throw DeadlyImportError("Unexpected EOF");
return t;
}
@ -144,6 +147,7 @@ template <>
aiString Read<aiString>(IOStream * stream) {
aiString s;
stream->Read(&s.length,4,1);
if(s.length)
stream->Read(s.data,s.length,1);
s.data[s.length] = 0;
return s;
@ -207,46 +211,48 @@ void ReadBounds( IOStream * stream, T* /*p*/, unsigned int n ) {
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* parent ) {
uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AINODE);
void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode* parent ) {
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AINODE)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
*node = new aiNode();
std::unique_ptr<aiNode> node(new aiNode());
(*node)->mName = Read<aiString>(stream);
(*node)->mTransformation = Read<aiMatrix4x4>(stream);
(*node)->mNumChildren = Read<unsigned int>(stream);
(*node)->mNumMeshes = Read<unsigned int>(stream);
node->mName = Read<aiString>(stream);
node->mTransformation = Read<aiMatrix4x4>(stream);
unsigned numChildren = Read<unsigned int>(stream);
unsigned numMeshes = Read<unsigned int>(stream);
unsigned int nb_metadata = Read<unsigned int>(stream);
if(parent) {
(*node)->mParent = parent;
node->mParent = parent;
}
if ((*node)->mNumMeshes) {
(*node)->mMeshes = new unsigned int[(*node)->mNumMeshes];
for (unsigned int i = 0; i < (*node)->mNumMeshes; ++i) {
(*node)->mMeshes[i] = Read<unsigned int>(stream);
if (numMeshes)
{
node->mMeshes = new unsigned int[numMeshes];
for (unsigned int i = 0; i < numMeshes; ++i) {
node->mMeshes[i] = Read<unsigned int>(stream);
node->mNumMeshes++;
}
}
if ((*node)->mNumChildren) {
(*node)->mChildren = new aiNode*[(*node)->mNumChildren];
for (unsigned int i = 0; i < (*node)->mNumChildren; ++i) {
ReadBinaryNode( stream, &(*node)->mChildren[i], *node );
if (numChildren) {
node->mChildren = new aiNode*[numChildren];
for (unsigned int i = 0; i < numChildren; ++i) {
ReadBinaryNode( stream, &node->mChildren[i], node.get() );
node->mNumChildren++;
}
}
if ( nb_metadata > 0 ) {
(*node)->mMetaData = aiMetadata::Alloc(nb_metadata);
node->mMetaData = aiMetadata::Alloc(nb_metadata);
for (unsigned int i = 0; i < nb_metadata; ++i) {
(*node)->mMetaData->mKeys[i] = Read<aiString>(stream);
(*node)->mMetaData->mValues[i].mType = (aiMetadataType) Read<uint16_t>(stream);
void* data( nullptr );
node->mMetaData->mKeys[i] = Read<aiString>(stream);
node->mMetaData->mValues[i].mType = (aiMetadataType) Read<uint16_t>(stream);
void* data = nullptr;
switch ((*node)->mMetaData->mValues[i].mType) {
switch (node->mMetaData->mValues[i].mType) {
case AI_BOOL:
data = new bool(Read<bool>(stream));
break;
@ -275,16 +281,16 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* p
break;
}
(*node)->mMetaData->mValues[i].mData = data;
node->mMetaData->mValues[i].mData = data;
}
}
*onode = node.release();
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) {
uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIBONE);
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIBONE)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
b->mName = Read<aiString>(stream);
@ -306,12 +312,10 @@ void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) {
static bool fitsIntoUI16(unsigned int mNumVertices) {
return ( mNumVertices < (1u<<16) );
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) {
uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIMESH);
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMESH)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
mesh->mPrimitiveTypes = Read<unsigned int>(stream);
@ -423,9 +427,8 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) {
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop) {
uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIALPROPERTY);
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMATERIALPROPERTY)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
prop->mKey = Read<aiString>(stream);
@ -440,9 +443,8 @@ void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialPro
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) {
uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIAL);
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIMATERIAL)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
mat->mNumAllocated = mat->mNumProperties = Read<unsigned int>(stream);
@ -462,9 +464,8 @@ void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) {
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) {
uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AINODEANIM);
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AINODEANIM)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
nd->mNodeName = Read<aiString>(stream);
@ -508,9 +509,8 @@ void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) {
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) {
uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AIANIMATION);
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AIANIMATION)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
anim->mName = Read<aiString> (stream);
@ -529,9 +529,8 @@ void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) {
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) {
uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AITEXTURE);
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AITEXTURE)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
tex->mWidth = Read<unsigned int>(stream);
@ -551,9 +550,8 @@ void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) {
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) {
uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AILIGHT);
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AILIGHT)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
l->mName = Read<aiString>(stream);
@ -577,9 +575,8 @@ void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) {
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) {
uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AICAMERA);
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AICAMERA)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
cam->mName = Read<aiString>(stream);
@ -594,9 +591,8 @@ void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) {
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) {
uint32_t chunkID = Read<uint32_t>(stream);
(void)(chunkID);
ai_assert(chunkID == ASSBIN_CHUNK_AISCENE);
if(Read<uint32_t>(stream) != ASSBIN_CHUNK_AISCENE)
throw DeadlyImportError("Magic chunk identifiers are wrong!");
/*uint32_t size =*/ Read<uint32_t>(stream);
scene->mFlags = Read<unsigned int>(stream);
@ -614,6 +610,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) {
// Read all meshes
if (scene->mNumMeshes) {
scene->mMeshes = new aiMesh*[scene->mNumMeshes];
memset(scene->mMeshes, 0, scene->mNumMeshes*sizeof(aiMesh*));
for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
scene->mMeshes[i] = new aiMesh();
ReadBinaryMesh( stream,scene->mMeshes[i]);
@ -623,6 +620,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) {
// Read materials
if (scene->mNumMaterials) {
scene->mMaterials = new aiMaterial*[scene->mNumMaterials];
memset(scene->mMaterials, 0, scene->mNumMaterials*sizeof(aiMaterial*));
for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
scene->mMaterials[i] = new aiMaterial();
ReadBinaryMaterial(stream,scene->mMaterials[i]);
@ -632,6 +630,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) {
// Read all animations
if (scene->mNumAnimations) {
scene->mAnimations = new aiAnimation*[scene->mNumAnimations];
memset(scene->mAnimations, 0, scene->mNumAnimations*sizeof(aiAnimation*));
for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
scene->mAnimations[i] = new aiAnimation();
ReadBinaryAnim(stream,scene->mAnimations[i]);
@ -641,6 +640,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) {
// Read all textures
if (scene->mNumTextures) {
scene->mTextures = new aiTexture*[scene->mNumTextures];
memset(scene->mTextures, 0, scene->mNumTextures*sizeof(aiTexture*));
for (unsigned int i = 0; i < scene->mNumTextures;++i) {
scene->mTextures[i] = new aiTexture();
ReadBinaryTexture(stream,scene->mTextures[i]);
@ -650,6 +650,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) {
// Read lights
if (scene->mNumLights) {
scene->mLights = new aiLight*[scene->mNumLights];
memset(scene->mLights, 0, scene->mNumLights*sizeof(aiLight*));
for (unsigned int i = 0; i < scene->mNumLights;++i) {
scene->mLights[i] = new aiLight();
ReadBinaryLight(stream,scene->mLights[i]);
@ -659,6 +660,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) {
// Read cameras
if (scene->mNumCameras) {
scene->mCameras = new aiCamera*[scene->mNumCameras];
memset(scene->mCameras, 0, scene->mNumCameras*sizeof(aiCamera*));
for (unsigned int i = 0; i < scene->mNumCameras;++i) {
scene->mCameras[i] = new aiCamera();
ReadBinaryCamera(stream,scene->mCameras[i]);
@ -701,11 +703,19 @@ void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
uLongf compressedSize = static_cast<uLongf>(stream->FileSize() - stream->Tell());
unsigned char * compressedData = new unsigned char[ compressedSize ];
stream->Read( compressedData, 1, compressedSize );
size_t len = stream->Read( compressedData, 1, compressedSize );
ai_assert(len == compressedSize);
unsigned char * uncompressedData = new unsigned char[ uncompressedSize ];
uncompress( uncompressedData, &uncompressedSize, compressedData, compressedSize );
int res = uncompress( uncompressedData, &uncompressedSize, compressedData, len );
if(res != Z_OK)
{
delete [] uncompressedData;
delete [] compressedData;
pIOHandler->Close(stream);
throw DeadlyImportError("Zlib decompression failed.");
}
MemoryIOStream io( uncompressedData, uncompressedSize );

View File

@ -59,32 +59,10 @@ bool isSeparator( T in ) {
return false;
}
static const unsigned char chartype_table[ 256 ] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 48-63
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64-79
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-95
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 96-111
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 112-127
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // > 127
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
template<class T>
inline
bool isNumeric( const T in ) {
return ( chartype_table[ static_cast<size_t>( in ) ] == 1 );
return ( in >= '0' && in <= '9' );
}
template<class T>

View File

@ -80,6 +80,8 @@ public:
// -------------------------------------------------------------------
// Read from stream
size_t Read(void* pvBuffer, size_t pSize, size_t pCount) {
ai_assert(pvBuffer);
ai_assert(pSize);
const size_t cnt = std::min(pCount,(length-pos)/pSize), ofs = pSize*cnt;
memcpy(pvBuffer,buffer+pos,ofs);

View File

@ -63,8 +63,7 @@ public:
aiColor4t (TReal _r, TReal _g, TReal _b, TReal _a)
: r(_r), g(_g), b(_b), a(_a) {}
explicit aiColor4t (TReal _r) : r(_r), g(_r), b(_r), a(_r) {}
aiColor4t (const aiColor4t& o)
: r(o.r), g(o.g), b(o.b), a(o.a) {}
aiColor4t (const aiColor4t& o) = default;
public:
// combined operators

View File

@ -69,7 +69,7 @@ public:
aiVector2t () : x(), y() {}
aiVector2t (TReal _x, TReal _y) : x(_x), y(_y) {}
explicit aiVector2t (TReal _xyz) : x(_xyz), y(_xyz) {}
aiVector2t (const aiVector2t& o) : x(o.x), y(o.y) {}
aiVector2t (const aiVector2t& o) = default;
public:

View File

@ -69,7 +69,7 @@ public:
aiVector3t() AI_NO_EXCEPT : x(), y(), z() {}
aiVector3t(TReal _x, TReal _y, TReal _z) : x(_x), y(_y), z(_z) {}
explicit aiVector3t (TReal _xyz ) : x(_xyz), y(_xyz), z(_xyz) {}
aiVector3t( const aiVector3t& o ) : x(o.x), y(o.y), z(o.z) {}
aiVector3t( const aiVector3t& o ) = default;
public:

View File

@ -82,15 +82,18 @@ void CompressBinaryDump(const char* file, unsigned int head_size)
uint8_t* data = new uint8_t[size];
fread(data,1,size,p);
uLongf out_size = (uLongf)((size-head_size) * 1.001 + 12.);
uint32_t uncompressed_size = size-head_size;
uLongf out_size = (uLongf)compressBound(uncompressed_size);
uint8_t* out = new uint8_t[out_size];
compress2(out,&out_size,data+head_size,size-head_size,9);
int res = compress2(out,&out_size,data+head_size,uncompressed_size,9);
if(res != Z_OK)
fprintf(stderr, "compress2: error\n");
fclose(p);
p = fopen(file,"w");
fwrite(data,head_size,1,p);
fwrite(&out_size,4,1,p); // write size of uncompressed data
fwrite(&uncompressed_size,4,1,p); // write size of uncompressed data
fwrite(out,out_size,1,p);
fclose(p);