【问题标题】:Can zlib remove padding without compressing the rest of the file?zlib 可以在不压缩文件其余部分的情况下删除填充吗?
【发布时间】:2021-05-19 16:43:43
【问题描述】:

我正在寻找一种使用 zlib-1.2.5 应用特定压缩策略的方法。 我需要强制 zlib 打包文件而不实际压缩它。我要压缩的唯一部分是文件末尾的 0 填充,以便输出文件没有它。输入文件的大小范围从 1MB 到 1GB,填充为 512B。 这可以通过 zlib 实现吗?

编辑:

我正在编写的代码基于 Unreal Engine 4: https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Source/Runtime/Core/Private/Misc/Compression.cpp

static bool appCompressMemoryZLIB(void* CompressedBuffer, int32& CompressedSize, const void* UncompressedBuffer, int32 UncompressedSize, int32 BitWindow, int32 CompLevel)
{
    DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Compress Memory ZLIB"), STAT_appCompressMemoryZLIB, STATGROUP_Compression);

    ensureMsgf(CompLevel >= Z_DEFAULT_COMPRESSION, TEXT("CompLevel must be >= Z_DEFAULT_COMPRESSION"));
    ensureMsgf(CompLevel <= Z_BEST_COMPRESSION, TEXT("CompLevel must be <= Z_BEST_COMPRESSION"));

    CompLevel = FMath::Clamp(CompLevel, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION);

    // Zlib wants to use unsigned long.
    unsigned long ZCompressedSize = CompressedSize;
    unsigned long ZUncompressedSize = UncompressedSize;
    bool bOperationSucceeded = false;

    // Compress data
    // If using the default Zlib bit window, use the zlib routines, otherwise go manual with deflate2
    if (BitWindow == 0 || BitWindow == DEFAULT_ZLIB_BIT_WINDOW)
    {
        bOperationSucceeded = compress2((uint8*)CompressedBuffer, &ZCompressedSize, (const uint8*)UncompressedBuffer, ZUncompressedSize, CompLevel) == Z_OK ? true : false;
    }
    else
    {
        z_stream stream;
        stream.next_in = (Bytef*)UncompressedBuffer;
        stream.avail_in = (uInt)ZUncompressedSize;
        stream.next_out = (Bytef*)CompressedBuffer;
        stream.avail_out = (uInt)ZCompressedSize;
        stream.zalloc = &zalloc;
        stream.zfree = &zfree;
        stream.opaque = Z_NULL;

        if (ensure(Z_OK == deflateInit2(&stream, CompLevel, Z_DEFLATED, BitWindow, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)))
        {
            if (ensure(Z_STREAM_END == deflate(&stream, Z_FINISH)))
            {
                ZCompressedSize = stream.total_out;
                if (ensure(Z_OK == deflateEnd(&stream)))
                {
                    bOperationSucceeded = true;
                }
            }
            else
            {
                deflateEnd(&stream);
            }
        }
    }

    // Propagate compressed size from intermediate variable back into out variable.
    CompressedSize = ZCompressedSize;
    return bOperationSucceeded;
}

使用参数:输入缓冲区大小 = 65kB,CompLevel=Z_DEFAULT_COMPRESSION,MAX_MEM_LEVEL=9,BitWindow=15

【问题讨论】:

  • 填充到下一个512B的倍数还是总是512B?无论哪种方式,您都可以计算出来。你想完成什么?
  • 直到下一个 512B。
  • UnrealPak (Unreal Engine 4) 使用 zlib 来压缩资源。资产由第三方软件创建(失控)。多个资产打包到一个 pak 文件中。 Pak 文件由部署后端处理(失控)。部署后端不喜欢二进制文件中的长 0 区域,因此我们必须对其进行修剪。虚幻引擎默认不压缩 pak 文件,所以最简单的方法就是压缩它们。但是这种中断差异修补 - 资产上的微小变化会破坏整个 pak 文件。
  • 所以我想重新配置 zlib 以使用非常轻的压缩进行打包,这只会消除每个资产中的零并保持文件的其余部分不变。

标签: c++ compression zlib


【解决方案1】:

不,没有。

如果您只想在最后去除零,那是微不足道的。这是几行代码。你不需要 zlib 的 18,000 行代码来做到这一点。

如果您还想将这些零恢复到另一端的文件(“解压缩”),那也很简单。只需发送已删除的零的计数,并将该计数附加到末尾的几个字节中。另一方面,用那么多零字节替换该计数。还有几行代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-14
    相关资源
    最近更新 更多