#include "stdafx.h" // decompress CT Raw dump format int CCTRawCodec::DecompressDump(PUBYTE buf, int len) { CapsPack cpk; PCAPSPACK pk; // free all buffers Free(); // check dump header int hlen = sizeof(CapsRaw); if (len < hlen) return imgeShort; wh.cr = *(PCAPSRAW)buf; Swap((PUDWORD)&wh.cr, sizeof(CapsRaw)); // check dump size int tlen = wh.cr.time; int rlen = wh.cr.raw; if (len < hlen + tlen + rlen) return imgeShort; // check density information PUBYTE denbuf = buf + hlen; pk = GetPackHeader(&cpk, denbuf, tlen); if (!pk) return imgeDensityHeader; // check track information PUBYTE trkbuf = denbuf + tlen; pk = GetPackHeader(&cpk, trkbuf, rlen); if (!pk) return imgeTrackHeader; int err; // decompress density information wh.cdbuf = denbuf; wh.cdlen = tlen; if (!(err = DecompressDensity(1))) err = DecompressDensity(); wh.cdbuf = NULL; if (err) return err; // decompress track data wh.ctbuf = trkbuf; wh.ctlen = rlen; if (!(err = DecompressTrack(1))) err = DecompressTrack(); wh.ctbuf = NULL; return err; } // decompress or verify compressed CT Raw density information int CCTRawCodec::DecompressDensity(int verify) { CapsPack cpk; // in decompress mode free result buffer first if (!verify) FreeUncompressedDensity(); // get density header PCAPSPACK pk = GetPackHeader(&cpk, wh.cdbuf, wh.cdlen); if (!pk) return imgeDensityHeader; // check crc on compressed data in verify mode if (verify) if (pk->ccrc != CalcCRC(wh.cdbuf + sizeof(CapsPack), pk->csize)) return imgeDensityStream; // decompress density data PUDWORD dst = DecompressDensity(wh.cdbuf, wh.cdlen); int res = imgeOk; if (verify) { // in verify mode get density data in target format Swap(dst, pk->usize); // check crc on uncompressed data if (pk->ucrc != CalcCRC((PUBYTE)dst, pk->usize)) res = imgeDensityData; // free density data delete[] dst; } else { // in decompress mode save density data wh.timbuf = dst; wh.timlen = pk->usize >> 2; } return res; } // decompress CT Raw density information PUDWORD CCTRawCodec::DecompressDensity(PUBYTE src, int slen, PUDWORD dst) { CapsPack cpk; // get density header PCAPSPACK pk = GetPackHeader(&cpk, src, slen); if (!pk) return NULL; // use caller supplied buffer or allocate a new one PUDWORD buf = dst; if (!buf && pk->usize) buf = new UDWORD[pk->usize >> 2]; // buffer pointer to end of destionation and source buffer PUDWORD mem = buf + (pk->usize >> 2); src += slen; // decode the data, see compressor for encoding while (mem > buf) { int size, ofs; UBYTE cb0 = *--src; switch (cb0 & 0x03) { // data block case 0x0: // 12 or 4 bit size if (cb0 & 0x08) size = ((cb0 << 4) & 0xf00) | (*--src); else size = (cb0 >> 4) + 1; if (cb0 & 0x04) { // 4 bytes per value while (size--) { UDWORD data; data = (*--src); data = (data << 8) | (*--src); data = (data << 8) | (*--src); data = (data << 8) | (*--src); *--mem = data; } } else { // 1 byte per value while (size--) *--mem = *--src; } continue; // copy block, 8 bit offset, 6 bit size case 0x1: size = (cb0 >> 2) + 1; ofs = (*--src) + 1; break; // copy block, 16 bit offset, 6 bit size case 0x2: size = (cb0 >> 2) + 1; ofs = (*--src); ofs = (ofs << 8) | (*--src); break; // copy block, 16 bit offset, 14 bit size case 0x3: size = ((cb0 << 6) & 0x3f00) | (*--src); ofs = (*--src); ofs = (ofs << 8) | (*--src); break; } // copy decoded data while (size--) { mem--; *mem = mem[ofs]; } } return buf; } // decompress or verify compressed CT Raw track information int CCTRawCodec::DecompressTrack(int verify) { CapsPack cpk; CapsWH cwh; // in decompress mode free result buffer first if (!verify) FreeUncompressedTrack(); // get track header PCAPSPACK pk = GetPackHeader(&cpk, wh.ctbuf, wh.ctlen); if (!pk) return imgeTrackHeader; // check crc on compressed data in verify mode if (verify) if (pk->ccrc != CalcCRC(wh.ctbuf + sizeof(CapsPack), pk->csize)) return imgeTrackStream; // decompress track data PCAPSWH wb = DecompressTrack(&cwh, wh.ctbuf, wh.ctlen); int res = imgeOk; if (verify) { // in verify mode check crc on uncompressed data if (pk->ucrc != CalcCRC(wb->rawbuf, wb->rawlen)) res = imgeTrackData; // free track data FreeUncompressedTrack(wb); } else { // in decompress mode save track data wh.rawbuf = wb->rawbuf; wh.rawlen = wb->rawlen; for (int trk = 0; trk < CAPS_MTRS; trk++) { wh.trkbuf[trk] = wb->trkbuf[trk]; wh.trklen[trk] = wb->trklen[trk]; } wh.trkcnt = wb->trkcnt; } return res; } // decompress CT Raw track information PCAPSWH CCTRawCodec::DecompressTrack(PCAPSWH w, PUBYTE src, int slen, PUBYTE dst) { CapsPack cpk; // get track header PCAPSPACK pk = GetPackHeader(&cpk, src, slen); if (!pk) return NULL; // use caller supplied buffer or allocate a new one w->rawbuf = NULL; FreeUncompressedTrack(w); w->rawlen = pk->usize; w->rawbuf = dst; if (!w->rawbuf && w->rawlen) w->rawbuf = new UBYTE[w->rawlen]; // read track number w->ctmem = src + sizeof(CapsPack); w->trkcnt = CTR(w, 1); // read track sizes and calculate track buffer positions dst = w->rawbuf; for (int trk = 0; trk < w->trkcnt; trk++) { w->trklen[trk] = CTR(w, 2); w->trkbuf[trk] = dst; dst += w->trklen[trk]; } // first track is stored if (w->trkcnt) { w->txsrc = w->trkbuf[0]; w->txlen = w->trklen[0]; memmove(w->txsrc, w->ctmem, w->txlen); w->ctmem += w->txlen; } // other tracks are compressed as deltas against the stored track for (w->txact = 1; w->txact < w->trkcnt; w->txact++) DecompressTrackData(w); return w; } // decompress CT Raw track data void CCTRawCodec::DecompressTrackData(PCAPSWH w) { // source stream PUBYTE src = w->ctmem; // destination buffer PUBYTE dst = w->trkbuf[w->txact]; // end of destination buffer PUBYTE max = dst + w->trklen[w->txact]; // first, stored track PUBYTE mem = w->txsrc; // decode the data, see compressor for encoding while (dst < max) { UDWORD size = *src++; if (size & 0x80) { // copy block // 3 bit shift int shift = size >> 4 & 7; // 12 bit size size = ((size & 0xf) << 8) | (*src++); // 16 bit offset UDWORD ofs = *src++; ofs = (ofs << 8) | (*src++); PUBYTE buf = mem + ofs; if (shift) { // bitshift copy ofs = *buf++; while (size--) { ofs = (ofs << 8) | (*buf++); *dst++ = (UBYTE)(ofs >> shift); } } else { // simple copy while (size--) *dst++ = *buf++; } } else { // data block, 15 bit size size = (size << 8) | (*src++); while (size--) *dst++ = *src++; } } // update the source stream position w->ctmem = src; } // get CT Raw pack format header in host format and test integrity PCAPSPACK CCTRawCodec::GetPackHeader(PCAPSPACK cpk, PUBYTE src, int slen) { // check header size if (!src || slensign))) return NULL; // copy header to result memcpy(cpk, src, sizeof(CapsPack)); // change header crc to host format and check crc Swap(&cpk->hcrc, sizeof(cpk->hcrc)); UDWORD hcrc = cpk->hcrc; cpk->hcrc = 0; if (hcrc != CalcCRC((PUBYTE)cpk, sizeof(CapsPack))) return NULL; // change header to host format Swap(PUDWORD(PUBYTE(cpk) + sizeof(cpk->sign)), sizeof(CapsPack) - sizeof(cpk->sign)); // buffer length must match the size of header and compressed data size if ((UDWORD)slen != sizeof(CapsPack) + cpk->csize) return NULL; return cpk; } // read up to a dword value from CT Raw stream, update stream position UDWORD CCTRawCodec::CTR(PCAPSWH w, int size) { UDWORD res = 0; for (; size; size--) { res <<= 8; res |= *w->ctmem++; } return res; }