Added CM_AUTO, which automatically selects CM_STORE or CM_DEFLATE based on file extension. Used to avoid double-compression of already compressed file formats such as images.

This commit is contained in:
Guenter Obiltschnig 2014-09-08 11:06:57 +02:00
parent 761c2ecb19
commit c9590ff7d4
3 changed files with 53 additions and 1 deletions

View File

@ -25,6 +25,7 @@
#include "Poco/FIFOEvent.h"
#include <istream>
#include <ostream>
#include <set>
namespace Poco {
@ -69,6 +70,25 @@ public:
ZipArchive close();
/// Finalizes the ZipArchive, closes it.
void setStoreExtensions(const std::set<std::string>& extensions);
/// Sets the file extensions for which the CM_STORE compression method
/// is used if CM_AUTO is specified in addFile() or addRecursive().
/// For all other extensions, CM_DEFLATE is used. This is used to avoid
/// double compression of already compressed file formats, which usually
/// leads to worse results. Extensions will be converted to lower case.
///
/// The default extensions are:
/// - gif
/// - jpg
/// - jpeg
/// - png
const std::set<std::string>& getStoreExtensions() const;
/// Returns the file extensions for which the CM_STORE compression method
/// is used if CM_AUTO is specified in addFile() or addRecursive().
///
/// See setStoreExtensions() for more information.
private:
enum
{
@ -86,6 +106,7 @@ private:
/// copys an already compressed ZipEntry from in
private:
std::set<std::string> _storeExtensions;
std::ostream& _out;
bool _seekableOut;
ZipArchive::FileHeaders _files;
@ -114,6 +135,12 @@ inline const std::string& Compress::getZipComment() const
}
inline const std::set<std::string>& Compress::getStoreExtensions() const
{
return _storeExtensions;
}
} } // namespace Poco::Zip

View File

@ -49,7 +49,8 @@ public:
CM_DEFLATE = 8,
CM_ENHANCEDDEFLATE = 9,
CM_DATECOMPRIMPLODING = 10,
CM_UNUSED = 11
CM_UNUSED = 11,
CM_AUTO = 255 /// automatically select DM_DEFLATE or CM_STORE based on file type (extension)
};
enum CompressionLevel

View File

@ -23,6 +23,7 @@
#include "Poco/StreamCopier.h"
#include "Poco/File.h"
#include "Poco/FileStream.h"
#include "Poco/String.h"
namespace Poco {
@ -37,6 +38,10 @@ Compress::Compress(std::ostream& out, bool seekableOut):
_dirs(),
_offset(0)
{
_storeExtensions.insert("gif");
_storeExtensions.insert("png");
_storeExtensions.insert("jpg");
_storeExtensions.insert("jpeg");
}
@ -47,6 +52,15 @@ Compress::~Compress()
void Compress::addEntry(std::istream& in, const Poco::DateTime& lastModifiedAt, const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl)
{
if (cm == ZipCommon::CM_AUTO)
{
std::string ext = Poco::toLower(fileName.getExtension());
if (_storeExtensions.find(ext) != _storeExtensions.end())
cm = ZipCommon::CM_STORE;
else
cm = ZipCommon::CM_DEFLATE;
}
std::string fn = ZipUtil::validZipEntryFileName(fileName);
if (_files.size() >= 65535)
@ -300,4 +314,14 @@ ZipArchive Compress::close()
}
void Compress::setStoreExtensions(const std::set<std::string>& extensions)
{
_storeExtensions.clear();
for (std::set<std::string>::const_iterator it = extensions.begin(); it != extensions.end(); ++it)
{
_storeExtensions.insert(Poco::toLower(*it));
}
}
} } // namespace Poco::Zip