Pression  1.0.0
Compressor, decompressor, uploader and downloader plugins
 All Classes Files Functions Variables Macros Pages
pression::Compressor Class Reference

A C++ class to handle one compressor plugin instance. More...

#include <compressor.h>

+ Collaboration diagram for pression::Compressor:

Public Member Functions

PRESSION_API Compressor ()
 Construct a new, invalid compressor instance. More...
 
PRESSION_API Compressor (PluginRegistry &from, const uint32_t name)
 Construct a new, named compressor instance. More...
 
virtual PRESSION_API ~Compressor ()
 Destruct the compressor. More...
 
PRESSION_API bool isGood () const
 
 operator bool_t () const
 
bool operator! () const
 
PRESSION_API bool uses (const uint32_t name) const
 
PRESSION_API const
EqCompressorInfo
getInfo () const
 
PRESSION_API bool setup (PluginRegistry &from, const uint32_t name)
 Set up a new, named compressor instance. More...
 
PRESSION_API bool setup (PluginRegistry &registry, const uint32_t tokenType, const float minQuality, const bool ignoreMSE)
 Set up a new, auto-selected compressor instance. More...
 
PRESSION_API bool realloc ()
 Reallocate the current instance. More...
 
PRESSION_API void clear ()
 Reset to EQ_COMPRESSOR_NONE. More...
 
PRESSION_API void compress (void *const in, const uint64_t inDims[2])
 Compress one-dimensional data. More...
 
PRESSION_API void compress (void *const in, const uint64_t pvp[4], const uint64_t flags)
 Compress two-dimensional data. More...
 
PRESSION_API unsigned getNumResults () const LB_DEPRECATED
 
PRESSION_API CompressorResult getResult () const
 
PRESSION_API void getResult (const unsigned i, void **const out, uint64_t *const outSize) const LB_DEPRECATED
 

Static Public Member Functions

static PRESSION_API uint32_t choose (const PluginRegistry &registry, const uint32_t tokenType, const float minQuality, const bool ignoreMSE)
 Find the best compressor in all plugins for the given parameters. More...
 

Detailed Description

A C++ class to handle one compressor plugin instance.

Example:

/* Copyright (c) 2010, Cedric Stalder <cedric.stalder@gmail.com>
* 2010-2014, Stefan Eilemann <eile@eyescale.ch>
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License version 2.1 as published
* by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define TEST_RUNTIME 600 // seconds
#include <test.h>
#include <pression/compressor.h>
#include <pression/compressorInfo.h>
#include <pression/compressorResult.h>
#include <pression/decompressor.h>
#include <pression/plugin.h>
#include <pression/pluginRegistry.h>
#include <lunchbox/buffer.h>
#include <lunchbox/clock.h>
#include <lunchbox/file.h>
#include <lunchbox/memoryMap.h>
#include <lunchbox/rng.h>
#include <algorithm>
using namespace pression;
void _testFile();
void _testRandom();
void _testData( const uint32_t nameCompressor, const std::string& name,
const uint8_t* data, const uint64_t size );
std::vector< uint32_t > getCompressorNames( const uint32_t tokenType );
Strings getFiles( const std::string& path, Strings& files,
const std::string& ext );
PluginRegistry registry;
uint64_t _result = 0;
uint64_t _size = 0;
float _compressionTime = 0;
float _decompressionTime = 0;
float _baseTime = 0.f;
int main( int, char** )
{
registry.addDirectory( std::string( PRESSION_BUILD_DIR ) + "/lib" );
TEST( registry.addLunchboxPlugins( ));
registry.init();
_testFile();
_testRandom();
registry.exit();
Compressor compressor;
TEST( !compressor.isGood( ));
TEST( !compressor );
Decompressor decompressor;
TEST( !decompressor.isGood( ));
TEST( !decompressor );
return EXIT_SUCCESS;
}
std::vector< uint32_t > getCompressorNames( const uint32_t tokenType )
{
const Plugins& plugins = registry.getPlugins();
std::vector< uint32_t > names;
for( PluginsCIter i = plugins.begin(); i != plugins.end(); ++i )
{
const CompressorInfos& infos = (*i)->getInfos();
for( CompressorInfosCIter j = infos.begin(); j != infos.end(); ++j )
{
if ( (*j).tokenType == tokenType )
names.push_back( (*j).name );
}
}
std::sort( names.begin(), names.end( ));
return names;
}
void _testData( const uint32_t compressorName, const std::string& name,
const uint8_t* data, const uint64_t size )
{
Compressor compressor( registry, compressorName );
Decompressor decompressor( registry, compressorName );
TEST( compressor.isGood( ));
TEST( compressor );
TESTINFO( decompressor.isGood(), compressorName );
TESTINFO( decompressor, compressorName );
const uint64_t flags = EQ_COMPRESSOR_DATA_1D;
uint64_t inDims[2] = { 0, size };
compressor.compress( const_cast<uint8_t*>(data), inDims, flags );
lunchbox::Clock clock;
compressor.compress( const_cast<uint8_t*>(data), inDims, flags );
const float compressTime = clock.getTimef();
const CompressorResult& compressed = compressor.getResult();
const uint64_t compressedSize = compressed.getSize();
std::vector< void * > chunks;
std::vector< uint64_t > chunkSizes;
chunks.resize( compressed.chunks.size( ));
chunkSizes.resize( chunks.size( ));
for( unsigned i = 0; i < chunks.size(); ++i )
{
chunks[ i ] = compressed.chunks[i].data;
chunkSizes[ i ] = compressed.chunks[i].getNumBytes();
}
lunchbox::Bufferb result;
result.resize( size );
uint8_t* outData = result.getData();
decompressor.decompress( &chunks.front(), &chunkSizes.front(),
unsigned( chunks.size( )), outData, inDims );
clock.reset();
decompressor.decompress( &chunks.front(), &chunkSizes.front(),
unsigned(chunks.size()), outData, inDims);
const float decompressTime = clock.getTimef();
TEST( memcmp( outData, data, size ) == 0 );
std::cout << std::setw(20) << name << ", 0x" << std::setw(8)
<< std::setfill( '0' ) << std::hex << compressorName << std::dec
<< std::setfill(' ') << ", " << std::setw(10) << size << ", "
<< std::setw(10) << compressedSize << ", " << std::setw(10)
<< compressTime << ", " << std::setw(10) << decompressTime
<< std::endl;
_size += size;
_result += compressedSize;
_compressionTime += compressTime;
_decompressionTime += decompressTime;
}
void _testFile()
{
std::vector< uint32_t >compressorNames =
getCompressorNames( EQ_COMPRESSOR_DATATYPE_BYTE );
std::vector< std::string > files;
getFiles( "", files, ".*\\.dll" );
getFiles( "", files, ".*\\.exe" );
getFiles( "", files, ".*\\.so" );
getFiles( "../bin", files, ".*\\.dll" );
getFiles( "../lib", files, ".*\\.so" );
getFiles( "../../install/bin", files, ".*\\.dll" );
getFiles( "../../install/lib", files, ".*\\.so" );
getFiles( "images", files, ".*\\.rgb" );
getFiles( "", files, ".*\\.a" );
getFiles( "", files, ".*\\.dylib" );
getFiles( "/Users/eile/Library/Models/mediumPly/", files, ".*\\.bin" );
getFiles( "/Users/eile/Library/Models/mediumPly/", files, ".*\\.ply" );
getFiles( "/home/eilemann/Software/Models/mediumPly/", files, ".*\\.bin" );
getFiles( "/home/eilemann/Software/Models/mediumPly/", files, ".*\\.ply" );
// Limit to 30 files using a pseudo-random selection for reproducability
const size_t maxFiles = 30;
if( files.size() > maxFiles )
{
const size_t cut = files.size() - maxFiles;
for( size_t i = 0; i < cut; ++i )
files.erase( files.begin() + (i * 997 /*prime*/) % files.size( ));
}
std::cout.setf( std::ios::right, std::ios::adjustfield );
std::cout.precision( 5 );
std::cout << " File, Compressor, Uncompress, "
<< "Compressed, t_comp, t_decomp" << std::endl;
for( std::vector< uint32_t >::const_iterator i = compressorNames.begin();
i != compressorNames.end(); ++i )
{
_result = 0;
_size = 0;
_compressionTime = 0;
_decompressionTime = 0;
for( StringsCIter j = files.begin(); j != files.end(); ++j )
{
lunchbox::MemoryMap file;
const uint8_t* data = static_cast<const uint8_t*>( file.map( *j ));
if( !data )
{
LBERROR << "Can't mmap " << *j << std::endl;
continue;
}
const size_t size = file.getSize();
const std::string name = lunchbox::getFilename( *j );
_testData( *i, name, data, size );
}
if( _baseTime == 0.f )
_baseTime = _compressionTime + _decompressionTime;
std::cout << std::setw(24) << "Total, 0x" << std::setw(8)
<< std::setfill( '0' ) << std::hex << *i << std::dec
<< std::setfill(' ') << ", " << std::setw(10) << _size << ", "
<< std::setw(10) << _result << ", " << std::setw(10)
<< _compressionTime << ", " << std::setw(10)
<< _decompressionTime << std::endl
<< " info->ratio = " << float(_result) / float(_size)
<< "f;" << std::endl
<< " info->speed = " << float(_baseTime) /
float(_compressionTime + _decompressionTime)
<< "f;" << std::endl << std::endl;
}
}
void _testRandom()
{
ssize_t size = LB_10MB;
uint8_t* data = new uint8_t[size];
lunchbox::RNG rng;
#pragma omp parallel for
for( ssize_t i = 0; i < size; ++i )
data[i] = rng.get< uint8_t >();
std::vector< uint32_t >compressorNames =
getCompressorNames( EQ_COMPRESSOR_DATATYPE_BYTE );
_result = 0;
_size = 0;
_compressionTime = 0;
_decompressionTime = 0;
for( std::vector<uint32_t>::const_iterator i = compressorNames.begin();
i != compressorNames.end(); ++i )
{
size = LB_10MB;
for( size_t j = 0; j<8; ++j ) // test all granularities between mod 8..1
{
_testData( *i, "Random data", data, size );
--size;
}
std::cout << std::setw(24) << "Total, 0x" << std::setw(8)
<< std::setfill( '0' ) << std::hex << *i << std::dec
<< std::setfill(' ') << ", " << std::setw(10) << _size << ", "
<< std::setw(10) << _result << ", " << std::setw(10)
<< _compressionTime << ", " << std::setw(10)
<< _decompressionTime << std::endl << std::endl;
}
delete [] data;
}
Strings getFiles( const std::string& path, Strings& files,
const std::string& ext )
{
Strings paths = registry.getDirectories();
if( !path.empty( ))
paths.push_back( path );
for( uint64_t j = 0; j < paths.size(); ++j )
{
const Strings& candidates = lunchbox::searchDirectory( paths[j], ext );
for( StringsCIter i = candidates.begin(); i != candidates.end(); ++i )
{
const std::string& filename = *i;
files.push_back( paths[j] + '/' + filename );
}
}
return files;
}

Definition at line 37 of file compressor.h.

Constructor & Destructor Documentation

PRESSION_API pression::Compressor::Compressor ( )

Construct a new, invalid compressor instance.

Version
1.7.1
PRESSION_API pression::Compressor::Compressor ( PluginRegistry from,
const uint32_t  name 
)

Construct a new, named compressor instance.

Parameters
fromthe plugin registry
namethe name of the compressor
Version
1.7.1
virtual PRESSION_API pression::Compressor::~Compressor ( )
virtual

Destruct the compressor.

Version
1.7.1

Member Function Documentation

static PRESSION_API uint32_t pression::Compressor::choose ( const PluginRegistry registry,
const uint32_t  tokenType,
const float  minQuality,
const bool  ignoreMSE 
)
static

Find the best compressor in all plugins for the given parameters.

This convenience method searches all compressors in all plugins to find the compressor which matches best the given parameters.

Parameters
registrythe plugin registry to choose from.
tokenTypethe structure of the data to compress.
minQualityminimal quality of the compressed data, with 0 = no quality and 1 = full quality, no loss.
ignoreMSEthe most-significant element of a four-element token can be ignored, typically the alpha channel of an image.
Returns
the name of the chosen compressor.
Version
1.7.1
PRESSION_API void pression::Compressor::clear ( )

Reset to EQ_COMPRESSOR_NONE.

Version
1.7.1
PRESSION_API void pression::Compressor::compress ( void *const  in,
const uint64_t  inDims[2] 
)

Compress one-dimensional data.

Parameters
inthe pointer to the input data.
inDimsthe dimensions of the input data
Version
1.7.1
PRESSION_API void pression::Compressor::compress ( void *const  in,
const uint64_t  pvp[4],
const uint64_t  flags 
)

Compress two-dimensional data.

Parameters
inthe pointer to the input data.
pvpthe dimensions of the input data
flagscapability flags for the compression
Version
1.7.1
PRESSION_API const EqCompressorInfo& pression::Compressor::getInfo ( ) const
Returns
the information about the allocated instance.
Version
1.7.1
PRESSION_API unsigned pression::Compressor::getNumResults ( ) const
Deprecated:
use new getResult()
Returns
the number of compressed chunks of the last compression.
Version
1.7.1
PRESSION_API CompressorResult pression::Compressor::getResult ( ) const
Returns
the result of the last compression.
Version
1.9.1
PRESSION_API void pression::Compressor::getResult ( const unsigned  i,
void **const  out,
uint64_t *const  outSize 
) const
PRESSION_API bool pression::Compressor::isGood ( ) const
Returns
true if the instance is usable.
Version
1.7.1

Referenced by operator bool_t(), and operator!().

+ Here is the caller graph for this function:

pression::Compressor::operator bool_t ( ) const
inline
Returns
true if the instance is usable, false otherwise.
Version
1.9.1

Definition at line 64 of file compressor.h.

References isGood().

+ Here is the call graph for this function:

bool pression::Compressor::operator! ( ) const
inline
Returns
true if the instance is not usable.
Version
1.9.1

Definition at line 67 of file compressor.h.

References isGood().

+ Here is the call graph for this function:

PRESSION_API bool pression::Compressor::realloc ( )

Reallocate the current instance.

Version
1.7.1
PRESSION_API bool pression::Compressor::setup ( PluginRegistry from,
const uint32_t  name 
)

Set up a new, named compressor instance.

Parameters
fromthe plugin registry.
namethe name of the compressor.
Returns
true on success, false otherwise.
Version
1.7.1
PRESSION_API bool pression::Compressor::setup ( PluginRegistry registry,
const uint32_t  tokenType,
const float  minQuality,
const bool  ignoreMSE 
)

Set up a new, auto-selected compressor instance.

See Also
choose() for parameters.
Version
1.7.1
PRESSION_API bool pression::Compressor::uses ( const uint32_t  name) const
Returns
true if the instance is usable for the given name.
Version
1.7.1

The documentation for this class was generated from the following file: