From fa373f0b8a7f2d99ec63b2a9e95ab8630eacef82 Mon Sep 17 00:00:00 2001 From: Dario Date: Sat, 27 Jul 2024 16:39:56 -0300 Subject: [PATCH] Patch miniz instead to allow specifying the compression method. --- src/contrib/miniz/miniz.c | 7 +- src/contrib/miniz/miniz.h | 2 +- src/tools/texture_packer/texture_packer.cpp | 86 +++------------------ 3 files changed, 16 insertions(+), 79 deletions(-) diff --git a/src/contrib/miniz/miniz.c b/src/contrib/miniz/miniz.c index 8d0032f..b37a067 100644 --- a/src/contrib/miniz/miniz.c +++ b/src/contrib/miniz/miniz.c @@ -6198,12 +6198,13 @@ static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_fil mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32) { - return mz_zip_writer_add_mem_ex_v2(pZip, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, uncomp_size, uncomp_crc32, NULL, NULL, 0, NULL, 0); + return mz_zip_writer_add_mem_ex_v2(pZip, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, uncomp_size, uncomp_crc32, NULL, NULL, 0, NULL, 0, MZ_DEFLATED); } mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified, - const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len) + const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len, + mz_uint16 compression_method) { mz_uint16 method = 0, dos_time = 0, dos_date = 0; mz_uint level, ext_attributes = 0, num_alignment_padding_bytes; @@ -6344,7 +6345,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) { - method = MZ_DEFLATED; + method = compression_method; } if (pState->m_zip64) diff --git a/src/contrib/miniz/miniz.h b/src/contrib/miniz/miniz.h index 9fcfffc..f54d01b 100644 --- a/src/contrib/miniz/miniz.h +++ b/src/contrib/miniz/miniz.h @@ -1359,7 +1359,7 @@ MINIZ_EXPORT mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char * MINIZ_EXPORT mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified, const char *user_extra_data_local, mz_uint user_extra_data_local_len, - const char *user_extra_data_central, mz_uint user_extra_data_central_len); + const char *user_extra_data_central, mz_uint user_extra_data_central_len, mz_uint16 compression_method); /* Adds the contents of a file to an archive. This function also records the disk file's modified time into the archive. */ /* File data is supplied via a read callback function. User mz_zip_writer_add_(c)file to add a file directly.*/ diff --git a/src/tools/texture_packer/texture_packer.cpp b/src/tools/texture_packer/texture_packer.cpp index a8e13c9..02fe015 100644 --- a/src/tools/texture_packer/texture_packer.cpp +++ b/src/tools/texture_packer/texture_packer.cpp @@ -384,6 +384,7 @@ int main(int argc, char *argv[]) { compressionFailed = false; + mz_uint16 compressionMethod = MZ_ZSTD; if (args.hasOption("deflate", "d")) { fprintf(stdout, "Using deflate for compression.\n"); useZstd = false; @@ -391,6 +392,7 @@ int main(int argc, char *argv[]) { } else if (args.hasOption("store", "d")) { fprintf(stdout, "Disabling compression.\n"); + compressionMethod = MZ_DEFLATED; useZstd = false; useCompression = false; } @@ -436,7 +438,7 @@ int main(int argc, char *argv[]) { std::filesystem::path packPath = searchDirectory / packName; std::string packPathStr = packPath.u8string(); mz_zip_archive zipArchive = {}; - if (!mz_zip_writer_init_file(&zipArchive, packPathStr.c_str(), 0)) { + if (!mz_zip_writer_init_file_v2(&zipArchive, packPathStr.c_str(), 0, MZ_ZIP_FLAG_WRITE_ZIP64)) { fprintf(stderr, "Failed to open %s for writing.\n", packPathStr.c_str()); return 1; } @@ -490,7 +492,7 @@ int main(int argc, char *argv[]) { if (!output.zipPath.empty()) { mz_uint flags = useCompression ? MZ_ZIP_FLAG_COMPRESSED_DATA : 0; - if (!mz_zip_writer_add_mem_ex(&zipArchive, output.zipPath.c_str(), output.fileData.data(), output.fileData.size(), nullptr, 0, flags, useCompression ? output.uncompressedSize : 0, output.checksum)) { + if (!mz_zip_writer_add_mem_ex_v2(&zipArchive, output.zipPath.c_str(), output.fileData.data(), output.fileData.size(), nullptr, 0, flags, useCompression ? output.uncompressedSize : 0, output.checksum, nullptr, nullptr, 0, nullptr, 0, compressionMethod)) { fprintf(stderr, "Failed to add %s to pack.\n", output.zipPath.c_str()); compressionFailed = true; } @@ -509,83 +511,17 @@ int main(int argc, char *argv[]) { } if (!compressionFailed) { - mz_zip_writer_finalize_archive(&zipArchive); - } - - mz_zip_writer_end(&zipArchive); - - // Since miniz doesn't provide a way to write the compression method out, we just read the file and store all the offsets where we need to patch the compression method. - if (useCompression && useZstd) { - fprintf(stdout, "Reading pack...\n"); - zipArchive = {}; - if (mz_zip_reader_init_file(&zipArchive, packPathStr.c_str(), MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) { - std::vector localHeaderOffsets; - std::vector centralDirOffsets; - uint32_t fileCount = mz_zip_reader_get_num_files(&zipArchive); - mz_zip_archive_file_stat fileStat = {}; - for (uint32_t i = 0; i < fileCount; i++) { - if (!mz_zip_reader_file_stat(&zipArchive, i, &fileStat)) { - fprintf(stderr, "Failed to open %s for reading.\n", packPathStr.c_str()); - compressionFailed = false; - break; - } - - localHeaderOffsets.emplace_back(fileStat.m_local_header_ofs); - centralDirOffsets.emplace_back(zipArchive.m_central_directory_file_ofs + fileStat.m_central_dir_ofs); - } - - mz_zip_reader_end(&zipArchive); - - if (!compressionFailed) { - fprintf(stdout, "Patching zstd compression method into headers...\n"); - - std::fstream zipStream(packPath, std::ios::binary | std::ios::in | std::ios::out); - if (zipStream.is_open()) { - auto patchMethod = [&](size_t absoluteOffset) { - // Validate that the method is being patched at the offset. - uint16_t readMethod = 0; - zipStream.seekg(absoluteOffset); - zipStream.read(reinterpret_cast(&readMethod), sizeof(readMethod)); - if (readMethod != MZ_DEFLATED) { - fprintf(stderr, "Failed to patch compression method.\n"); - compressionFailed = false; - return false; - } - - // Write the patched method. - const uint16_t writeMethod = MZ_ZSTD; - zipStream.seekg(absoluteOffset); - zipStream.write(reinterpret_cast(&writeMethod), sizeof(writeMethod)); - return true; - }; - - for (uint32_t offset : localHeaderOffsets) { - if (!patchMethod(offset + MZ_ZIP_LDH_METHOD_OFS)) { - break; - } - } - - for (uint32_t offset : centralDirOffsets) { - if (!patchMethod(offset + MZ_ZIP_CDH_METHOD_OFS)) { - break; - } - } - - zipStream.seekg(0, std::ios::end); - zipStream.close(); - } - else { - fprintf(stderr, "Failed to open %s for reading and writing.\n", packPathStr.c_str()); - compressionFailed = false; - } - } - } - else { - fprintf(stderr, "Failed to open %s for reading.\n", packPathStr.c_str()); + if (!mz_zip_writer_finalize_archive(&zipArchive)) { + fprintf(stderr, "Failed to finalize archive %s.\n", packPathStr.c_str()); compressionFailed = true; } } + if (!mz_zip_writer_end(&zipArchive)) { + fprintf(stderr, "Failed to close %s for writing.\n", packPathStr.c_str()); + compressionFailed = true; + } + if (compressionFailed) { std::filesystem::remove(packPath); fprintf(stderr, "Pack creation has failed.\n");