Esempio n. 1
0
/* If dest is NULL, return uncompressed length in *destLen. */
int tinf_gzip_uncompress(void *dest, unsigned int *destLen,
                         const void *source, unsigned int sourceLen)
{
    unsigned char *src = (unsigned char *)source;
    unsigned char *dst = (unsigned char *)dest;
    unsigned char *start;
    unsigned int dlen, crc32;
    int res;
    unsigned char flg;

    /* -- check format -- */

    /* check id bytes */
    if (src[0] != 0x1f || src[1] != 0x8b) return TINF_DATA_ERROR;

    /* check method is deflate */
    if (src[2] != 8) return TINF_DATA_ERROR;

    /* get flag byte */
    flg = src[3];

    /* check that reserved bits are zero */
    if (flg & 0xe0) return TINF_DATA_ERROR;

    /* -- find start of compressed data -- */

    /* skip base header of 10 bytes */
    start = src + 10;

    /* skip extra data if present */
    if (flg & FEXTRA)
    {
       unsigned int xlen = start[1];
       xlen = 256*xlen + start[0];
       start += xlen + 2;
    }

    /* skip file name if present */
    if (flg & FNAME) { while (*start) ++start; ++start; }

    /* skip file comment if present */
    if (flg & FCOMMENT) { while (*start) ++start; ++start; }

    /* check header crc if present */
    if (flg & FHCRC)
    {
       unsigned int hcrc = start[1];
       hcrc = 256*hcrc + start[0];

       if (hcrc != (tinf_crc32(src, start - src) & 0x0000ffff))
          return TINF_DATA_ERROR;

       start += 2;
    }

    /* -- get decompressed length -- */

    dlen =            src[sourceLen - 1];
    dlen = 256*dlen + src[sourceLen - 2];
    dlen = 256*dlen + src[sourceLen - 3];
    dlen = 256*dlen + src[sourceLen - 4];

    if (!dst) {
      *destLen = dlen;
      return TINF_OK;
    }

    /* -- get crc32 of decompressed data -- */

    crc32 =             src[sourceLen - 5];
    crc32 = 256*crc32 + src[sourceLen - 6];
    crc32 = 256*crc32 + src[sourceLen - 7];
    crc32 = 256*crc32 + src[sourceLen - 8];

    /* -- decompress data -- */

    res = tinf_uncompress(dst, destLen, start, src + sourceLen - start - 8);

    if (res != TINF_OK) return TINF_DATA_ERROR;

    if (*destLen != dlen) return TINF_DATA_ERROR;

    /* -- check CRC32 checksum -- */

    if (crc32 != tinf_crc32(dst, dlen)) return TINF_DATA_ERROR;

    return TINF_OK;
}
Esempio n. 2
0
bool CEL_CHUNK::readCompressedPixels(std::ifstream & s, PIXELTYPE pixelFormat, DWORD sourceLen) {
    bool result = s & width && s & height;
    if (!result) {
        return result;
    }
    DWORD dim = width * height;
    pixels.resize(dim);
    sourceLen -= 4; /* width, height */
    std::vector<BYTE> source(sourceLen);
    s.read((char*) source.data() /*zlib header*/, sourceLen);

    result = s.good();
    if (!result) {
        return result;
    }

    DWORD expectedLen = dim;
    switch (pixelFormat) {
    case INDEXED: {
        break;
    }
    case GRAYSCALE: {
        expectedLen *= 2;
        break;
    }
    case RGBA: {
        expectedLen *= 4;
        break;
    }
    default:
        result = false;
    }
    std::vector<BYTE> uncompressed(expectedLen);
    DWORD destLen;
    auto outcome = tinf_uncompress(uncompressed.data(), &destLen, source.data() + 2, sourceLen - 2 - 4/*zlib header, crc*/);
    result = result && TINF_OK == outcome;

    result = result && destLen == expectedLen;

    if (!result)
        return result;
    switch (pixelFormat) {
    case INDEXED: {
        for (DWORD i = 0; i < dim; i++) {
            pixels[i].INDEXED = uncompressed[i];
        }
        break;
    }
    case GRAYSCALE: {
        for (DWORD i = 0; i < dim; i++) {
            pixels[i].GRAYSCALE[0] = uncompressed[2 * i];
            pixels[i].GRAYSCALE[1] = uncompressed[2 * i + 1];
        }
        break;
    }
    case RGBA: {
        for (DWORD i = 0; i < dim; i++) {
            pixels[i].RGBA[0] = uncompressed[4 * i];
            pixels[i].RGBA[1] = uncompressed[4 * i + 1];
            pixels[i].RGBA[2] = uncompressed[4 * i + 2];
            pixels[i].RGBA[3] = uncompressed[4 * i + 3];
        }
        break;
    }
    }
    return result;
}