【问题标题】:Swift Compression: doesn't decompress LZ4 imageSwift Compression:不解压缩 LZ4 图像
【发布时间】:2018-05-16 03:51:21
【问题描述】:

我正在尝试使用 Swift Compression 包解压缩 lz4 压缩的 png 图像,但代码以零大小退出。 我的代码如下,解压后的文件预计为240Kb。

[更新 2] 我在 Apple 的文档中偶然发现了这一点:

此处记录了框架,以便您可以轻松包装另一个 LZ4 编码器/解码器在必要时生成/使用相同的数据流。 LZ4 编码的缓冲区是一个块序列,每个块都开始 带有标题。有三种可能的标题:

压缩块头由八位字节 0x62、0x76、0x34 和 0x31,后跟解码(明文)数据的字节大小 由编码数据的块和大小(以字节为单位)表示 存储在块中。两个大小字段都存储为(可能 未对齐)32 位小端值。压缩块头是 紧接着是实际的 LZ4 编码数据流。

流标头的结尾由八位字节 0x62、0x76、0x34 和 0x24 并标记 LZ4 帧的结束。可能没有进一步的数据 超出此标头写入或读取。

所以我相应地添加了页眉和页脚,它可以工作。但是——总是有一个“但是”——,在解压缩之前我怎么知道“解码(明文)数据的字节大小”?

[更新 1]

我给你一个 LZ4 文件供你测试,以及从主包中解压它的代码用法。

使用 sw 压缩的 LZ4 文件“LZ4 命令行界面 64 位 v1.8.0,由 Yann Collet 提供”,可在 Internet 上广泛获取

https://drive.google.com/file/d/1eQ204LJs_xsHRwJ_jUcl1Up9NFo8monO/view?usp=sharing

LZ4解压用法

    if let url = Bundle.main.url(forResource: "TestImage300.png", withExtension: "lz4") {
        if let compressed = try? Data(contentsOf: url) {
            if let decompressed = compressed.lz4Decompress() {
                if let image = UIImage(data: decompressed) {
                    self.sourceImages.append(image)
                    print("Unittest: Decompressed image as \(image)")
                }
            }
        }
    }

LZ4 解压数据扩展码:

import Foundation
import Compression

extension Data {

    func lz4Decompress() -> Data? {
        let destinationBufferSize: size_t = 480000
        let destinationBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: destinationBufferSize)

        let sourceBufferSize = count

        let decompressed = withUnsafeBytes { (sourceBuffer: UnsafePointer<UInt8>) -> Data? in

            let size = compression_decode_buffer(
                destinationBuffer, destinationBufferSize,
                sourceBuffer, sourceBufferSize,
                nil,    // scratch buffer automatically handled
                COMPRESSION_LZ4
            )

            if size == 0 {
                print("Error ")
                return nil
            }

            print("Original compressed size: \(sourceBufferSize) | Decompressed size: \(size)")

            return Data(bytesNoCopy: destinationBuffer, count: size, deallocator: .free)
        }
        return decompressed
     }
}

【问题讨论】:

    标签: compression swift4 lz4


    【解决方案1】:
    let intArray: [Int8] =  [-16, 1, 1, 39, 0, 19, 11, -30, 7, 10, 29, 14, 0, 0, 0, 0, 96, 9, 6, 0, 1, 2, 0, 17, 14, 6, 0, 2, 2, 0, 18, 14, 7, 0, 65, 0, 0, 0, -51, 6, 0, 0, 2, 0, 0, 43, 0, 16, 2, 9, 0, -1, 13, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 10, 4, 0, 64, 33, -105, 58, 115, 0, 12, 2, 0, 80, 0, 0, 0, 0, 0]
    
            let uintArray = intArray.map { UInt8(bitPattern: $0) }
    

    // 对于可见性,uintArray unsigned 为 [240, 1, 1, 39, 0, 19, 11, 226, 7, 10, 29, 14, 0, 0, 0, 0, 96, 9, 6, 0, 1, 2, 0, 17, 14, 6, 0, 2, 2, 0, 18, 14, 7, 0, 65, 0, 0, 0, 205, 6, 0, 0, 2, 0, 0, 43, 0, 16, 2, 9, 0, 255, 13, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 10, 4, 0, 64, 33, 151, 58, 115, 0, 12, 2, 0, 80, 0, 0, 0, 0, 0]

            var encodedData = Data.init(bytes:uintArray)
    
            let decodedCapacity = 205
            let decodedDestinationBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: decodedCapacity)
    
            let decodedData = encodedData.withUnsafeBytes {
                (encodedSourceBuffer: UnsafePointer<UInt8>) -> Data? in
    
                let decodedCharCount = compression_decode_buffer(decodedDestinationBuffer,
                                                                 decodedCapacity,
                                                                 encodedSourceBuffer,
                                                                 encodedData.count,
                                                                 nil,
                                                                 COMPRESSION_LZ4_RAW)
    
                if decodedCharCount == 0 {
                    fatalError("Decoding failed.")
                }
    
                print("Before: \(encodedSourceBuffer) | After: \(decodedCharCount)")
    
                return Data(bytesNoCopy: decodedDestinationBuffer, count: decodedCharCount, deallocator: .free)
    
            }
    

    如果您没有在压缩中定义标头,则应使用 COMPRESSION_LZ4_RAW

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-31
      • 1970-01-01
      • 2016-05-01
      • 1970-01-01
      • 2013-08-07
      • 2014-02-03
      • 1970-01-01
      相关资源
      最近更新 更多