stachenov / quazip

Qt/C++ wrapper over minizip
Other
565 stars 235 forks source link

Set the compression method and level for JlCompress #192

Closed lazyone233 closed 11 hours ago

lazyone233 commented 6 months ago

Currently, when using the API in JlCompress, I can only compress files or directories, and the compression level is very high (or in other words, the compression ratio is very high), which takes some time.

However, sometimes I just want to package files without compression. Or I want to set a lower compression level to reduce the compression time.

However, in the JlCompress API, there is no way to set the compression method and compression level. Therefore, I wonder if it is possible to set the compression method and compression level in JlCompress.

For example, In the JlCompress.h file, change

static bool compressFile(QuaZip* zip, QString fileName, QString fileDest);

to

static bool compressFile(QuaZip* zip, QString fileName, QString fileDest, bool isCompress = true, compressionLevel = 8);

Then, in the JlCompress.cpp file, change

bool JlCompress::compressFile(QuaZip* zip, QString fileName, QString fileDest) {
    ...
    QuaZipFile outFile(zip);
    if(!outFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileDest, fileName))) return false;
    ...
}

to

bool JlCompress::compressFile(QuaZip* zip, QString fileName, QString fileDest) {
    ...
    QuaZipFile outFile(zip);
    if(!outFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileDest, fileName), NULL, 0, isCompress?8:0, compressionLevel)) return false;
    ...
}

JlCompress's other compression APIs can also be rewritten in this way. This way, when we compress, we can set the compression method and compression level.

The reason for this setting is because after reviewing the source code, I observed that when the method is 0, it will only package without compression. When the method is 8, the higher the level value, the higher the compression degree, the higher the compression ratio, and the longer the compression time.

Finally, I want to ask if JlCompress can be modified in the way mentioned above?

cen1 commented 6 months ago

The proposal makes sense to me on the surface. Some comments.

  1. Needs to be a function overload, we must not break existing interfaces
  2. Why would a bool be needed if lvl 0 already indicates no compression?
  3. Would you be able to prepare a pull request and appropriate tests for the feature?
lazyone233 commented 6 months ago

The proposal makes sense to me on the surface. Some comments.

  1. Needs to be a function overload, we must not break existing interfaces
  2. Why would a bool be needed if lvl 0 already indicates no compression?
  3. Would you be able to prepare a pull request and appropriate tests for the feature?

for comment 1:

Of course, function overloading is possible. But to overload all compression functions just for one line, I feel it's unnecessary.

Or we can first overload those functions, and after these functions have been validated for a period of time, then proceed with the merge.

for comment 2:

In quazipfile.h, line 364, there is an explanation for the QuaZipFile::open function.

The method can take three values, 0 means no compression, Z_DEFLATED (8) uses the default compression method, and Z_BZIP2ED (12) uses the bzip2 library for compression.

The definition of level is also explained, with 0 indicating a very low compression level.

    /// Opens a file for writing.
    /** \a info argument specifies information about file. It should at
     * least specify a correct file name. Also, it is a good idea to
     * specify correct timestamp (by default, current time will be
     * used). See QuaZipNewInfo.
     *
     * The \a password argument specifies the password for crypting. Pass NULL
     * if you don't need any crypting. The \a crc argument was supposed
     * to be used for crypting too, but then it turned out that it's
     * false information, so you need to set it to 0 unless you want to
     * use the raw mode (see below).
     *
     * Arguments \a method and \a level specify compression method and
     * level. The only compression methods supported are
     * Z_DEFLATED and Z_BZIP2ED. But you may also
     * specify 0 for no compression. If all of the files in the archive
     * use both method 0 and either level 0 is explicitly specified or
     * data descriptor writing is disabled with
     * QuaZip::setDataDescriptorWritingEnabled(), then the
     * resulting archive is supposed to be compatible with the 1.0 ZIP
     * format version, should you need that. Except for this, \a level
     * has no other effects with method 0.
     *
     * If the method is \a Z_BZIP2ED, then the level must be specified
     * explicitly (1 to 9), as the bzip2 backend doesn't support
     * \a Z_DEFAULT_COMPRESSION.
     *
     * If \a raw is \c true, no compression is performed. In this case,
     * \a crc and uncompressedSize field of the \a info are required.
     *
     * Arguments \a windowBits, \a memLevel, \a strategy provide zlib
     * algorithms tuning. See deflateInit2() in zlib.
     **/
    bool open(OpenMode mode, const QuaZipNewInfo& info,
        const char *password =nullptr, quint32 crc =0,
        int method =Z_DEFLATED, int level =Z_DEFAULT_COMPRESSION, bool raw =false,
        int windowBits =-MAX_WBITS, int memLevel =DEF_MEM_LEVEL, int strategy =Z_DEFAULT_STRATEGY);

for comment 3:

I can prepare a pull request, but I haven't used the bzip2 library. If using only the default compression method is acceptable, I can give it a try, because JlCompress also uses the default compression method.

cen1 commented 6 months ago

On point 1, I think using default arguments would still break the ABI which is not desirable. See CONTRIBUTING.md point 1.

lazyone233 commented 6 months ago

Okay, I understand. I will try to spend a few days to overload the functions and conduct testing. After everything is done, I will submit a pull request.

cen1 commented 11 hours ago

Implemented in #206