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 "Poco/FIFOEvent.h"
#include <istream> #include <istream>
#include <ostream> #include <ostream>
#include <set>
namespace Poco { namespace Poco {
@ -69,6 +70,25 @@ public:
ZipArchive close(); ZipArchive close();
/// Finalizes the ZipArchive, closes it. /// 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: private:
enum enum
{ {
@ -86,6 +106,7 @@ private:
/// copys an already compressed ZipEntry from in /// copys an already compressed ZipEntry from in
private: private:
std::set<std::string> _storeExtensions;
std::ostream& _out; std::ostream& _out;
bool _seekableOut; bool _seekableOut;
ZipArchive::FileHeaders _files; 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 } } // namespace Poco::Zip

View File

@ -49,7 +49,8 @@ public:
CM_DEFLATE = 8, CM_DEFLATE = 8,
CM_ENHANCEDDEFLATE = 9, CM_ENHANCEDDEFLATE = 9,
CM_DATECOMPRIMPLODING = 10, 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 enum CompressionLevel

View File

@ -23,6 +23,7 @@
#include "Poco/StreamCopier.h" #include "Poco/StreamCopier.h"
#include "Poco/File.h" #include "Poco/File.h"
#include "Poco/FileStream.h" #include "Poco/FileStream.h"
#include "Poco/String.h"
namespace Poco { namespace Poco {
@ -37,6 +38,10 @@ Compress::Compress(std::ostream& out, bool seekableOut):
_dirs(), _dirs(),
_offset(0) _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) 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); std::string fn = ZipUtil::validZipEntryFileName(fileName);
if (_files.size() >= 65535) 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 } } // namespace Poco::Zip