File size: 4,739 Bytes
8b83ace | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | /* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/*
* Copyright 2023-2023 The Khronos Group Inc.
* Copyright 2023-2023 RasterGrid Kft.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file
* @~English
*
* @brief Wrapper functions for ZLIB compression/decompression using miniz.
*
* @author Daniel Rakos, RasterGrid
*/
#include "ktx.h"
#include "ktxint.h"
#include <assert.h>
#if !KTX_FEATURE_WRITE
// The reader does not link with the basisu components that already include a
// definition of miniz so we include it here explicitly.
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wextra"
#pragma GCC diagnostic ignored "-Wmisleading-indentation"
#endif
#include "basisu/encoder/basisu_miniz.h"
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#else
// Otherwise we only declare the interfaces and link with the basisu version.
// This is needed because while miniz is defined as a header in basisu it's
// not declaring the functions as static or inline, hence causing multiple
// conflicting definitions at link-time.
namespace buminiz {
typedef unsigned long mz_ulong;
enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 };
mz_ulong mz_compressBound(mz_ulong source_len);
int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level);
int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
}
#endif
using namespace buminiz;
extern "C" {
/**
* @internal
* @~English
* @brief Returns upper bound for compresses data using miniz (ZLIB).
*
* @param srcLength source data length
*
* @author Daniel Rakos, RasterGrid
*/
ktx_size_t ktxCompressZLIBBounds(ktx_size_t srcLength) {
return mz_compressBound((mz_ulong)srcLength);
}
/**
* @internal
* @~English
* @brief Compresses data using miniz (ZLIB)
*
* @param pDest destination data buffer
* @param pDestLength destination data buffer size
* (filled with written byte count on success)
* @param pSrc source data buffer
* @param srcLength source data size
* @param level compression level (between 1 and 9)
*
* @author Daniel Rakos, RasterGrid
*/
KTX_error_code ktxCompressZLIBInt(unsigned char* pDest,
ktx_size_t* pDestLength,
const unsigned char* pSrc,
ktx_size_t srcLength,
ktx_uint32_t level) {
if ((srcLength | *pDestLength) > 0xFFFFFFFFU) return KTX_INVALID_VALUE;
mz_ulong mzCompressedSize = (mz_ulong)*pDestLength;
int status = mz_compress2(pDest, &mzCompressedSize, pSrc, (mz_ulong)srcLength, level);
switch (status) {
case MZ_OK:
*pDestLength = mzCompressedSize;
return KTX_SUCCESS;
case MZ_PARAM_ERROR:
return KTX_INVALID_VALUE;
case MZ_BUF_ERROR:
#ifdef DEBUG
assert(false && "Deflate dstSize too small.");
#endif
return KTX_OUT_OF_MEMORY;
case MZ_MEM_ERROR:
#ifdef DEBUG
assert(false && "Deflate workspace too small.");
#endif
return KTX_OUT_OF_MEMORY;
default:
// The remaining errors look like they should only
// occur during decompression but just in case.
#ifdef DEBUG
assert(true);
#endif
return KTX_INVALID_OPERATION;
}
}
/**
* @internal
* @~English
* @brief Uncompresses data using miniz (ZLIB)
*
* @param pDest destination data buffer
* @param pDestLength destination data buffer size
* (filled with written byte count on success)
* @param pSrc source data buffer
* @param srcLength source data size
*
* @author Daniel Rakos, RasterGrid
*/
KTX_error_code ktxUncompressZLIBInt(unsigned char* pDest,
ktx_size_t* pDestLength,
const unsigned char* pSrc,
ktx_size_t srcLength) {
if ((srcLength | *pDestLength) > 0xFFFFFFFFU) return KTX_INVALID_VALUE;
mz_ulong mzUncompressedSize = (mz_ulong)*pDestLength;
int status = mz_uncompress(pDest, &mzUncompressedSize, pSrc, (mz_ulong)srcLength);
switch (status) {
case MZ_OK:
*pDestLength = mzUncompressedSize;
return KTX_SUCCESS;
case MZ_BUF_ERROR:
return KTX_DECOMPRESS_LENGTH_ERROR; // buffer too small
case MZ_MEM_ERROR:
return KTX_OUT_OF_MEMORY;
default:
return KTX_FILE_DATA_ERROR;
}
}
}
|