#include "stdafx.h"
#include "ezw.h"
/////////////////////////////////////////compress/decompress/////////////////////////////////////////////////////
unsigned int EZW::compress(unsigned char* dest, const unsigned char* sour, unsigned int w, unsigned int h)
{
const char hdr[] = "EZW1";
pdest = dest;
width = w / 8;
height = h / 8;
width8 = w;
unsigned int p125prcnt = (unsigned int)(0.125f * float(8 * width * 8 * height)); //zerotree = dest, spectra = sour
//store LL band
storeLband(sour); //pdest = dest+(width*height)
//make EZW header
struct EZWHDR* phdr = (struct EZWHDR*)pdest;
positions = pdest + sizeof(EZWHDR);
*positions = 0;
coeffs = pdest + sizeof(EZWHDR) + p125prcnt;
pbits = 0;
posnum = 0;
cffnum = 0;
storeHband(sour + width, sour + 2*width, sour + 4*width);
storeHband(sour + height*width8, sour + 2*height*width8, sour + 4*height*width8);
storeHband(sour + height*width8 + width, sour + 2*height*width8 + 2*width, sour + 4*height*width8 + 4*width);
if (posnum % 8)
posnum += (8 - posnum % 8);
posnum /= 8;
if (posnum < p125prcnt)
mmxmemcpy(pdest + sizeof(EZWHDR) + posnum, coeffs - cffnum, cffnum);
else
return 0;
memcpy(phdr->hdr, hdr, 4);
phdr->poffset = posnum;
return width * height + sizeof(EZWHDR) + posnum + cffnum;
}
unsigned int EZW::compress(char* dest, const char* sour, unsigned int w, unsigned int h)
{
const char hdr[] = "EZW1";
pdest = (unsigned char *)dest;
width = w / 8;
height = h / 8;
width8 = w;
unsigned int p125prcnt = (unsigned int)(0.125f * float(8 * width * 8 * height)); //zerotree = dest, spectra = sour
//store LL band
storeLband((const unsigned char *)sour); //pdest = dest+(width*height)
//make EZW header
struct EZWHDR* phdr = (struct EZWHDR*)pdest;
positions = pdest + sizeof(EZWHDR);
*positions = 0;
coeffs = pdest + sizeof(EZWHDR) + p125prcnt;
pbits = 0;
posnum = 0;
cffnum = 0;
storeHband(sour + width, sour + 2*width, sour + 4*width);
storeHband(sour + height*width8, sour + 2*height*width8, sour + 4*height*width8);
storeHband(sour + height*width8 + width, sour + 2*height*width8 + 2*width, sour + 4*height*width8 + 4*width);
if (posnum % 8) posnum += (8 - posnum % 8);
posnum /= 8;
if (posnum < p125prcnt)
mmxmemcpy(pdest + sizeof(EZWHDR) + posnum, coeffs - cffnum, cffnum);
else
return 0;
memcpy(phdr->hdr, hdr, 4);
phdr->poffset = posnum;
return width*height + sizeof(EZWHDR) + posnum + cffnum;
}
unsigned int EZW::decompress(unsigned char* dest, unsigned char* sour, unsigned int w, unsigned int h)
{
const char hdr[] = "EZW1";
psour = sour;
width = w / 8;
height = h / 8;
width8 = w;
mmxmemset(dest, w*h, 128); //128 -> char in set mmx intrinsic
readLband(dest);
struct EZWHDR* phdr = (struct EZWHDR*)psour;
if (memcmp(phdr->hdr, hdr, 4) != 0) return 0;
positions = psour + sizeof(EZWHDR);
coeffs = psour + sizeof(EZWHDR) + phdr->poffset;
pbits = 0;
posnum = 0;
cffnum = 0;
readHband(dest + width, dest + 2*width, dest + 4*width);
readHband(dest + height*width8, dest + 2*height*width8, dest + 4*height*width8);
readHband(dest + height*width8 + width, dest + 2*height*width8 + 2*width, dest + 4*height*width8 + 4*width);
return int(psour - sour);
}
unsigned int EZW::decompress(char* dest, char* sour, unsigned int w, unsigned int h)
{
const char hdr[] = "EZW1";
psour = (unsigned char *)sour;
width = w / 8;
height = h / 8;
width8 = w;
mmxmemset((unsigned char *)dest, w*h, 0);
readLband((unsigned char *)dest);
struct EZWHDR* phdr = (struct EZWHDR*)psour;
if (memcmp(phdr->hdr, hdr, 4) != 0) return 0;
positions = psour + sizeof(EZWHDR);
coeffs = psour + sizeof(EZWHDR) + phdr->poffset;
pbits = 0;
posnum = 0;
cffnum = 0;
readHband(dest + width, dest + 2*width, dest + 4*width);
readHband(dest + height*width8, dest + 2*height*width8, dest + 4*height*width8);
readHband(dest + height*width8 + width, dest + 2*height*width8 + 2*width, dest + 4*height*width8 + 4*width);
return int(coeffs - (const unsigned char *)sour);
}
/////////////////////////////////////////compress/decompress/////////////////////////////////////////////////////
//////////////////////////////////store LL,HH bands//////////////////////////////////////////////////////
void EZW::storeLband(const unsigned char* sour)
{
for (unsigned int j = 0; j < height; j++) {
const __m64* msour = (__m64*)sour;
__m64* mdest = (__m64*)pdest;
for (unsigned int i = 0; i < width / 8; i++)
*mdest++ = *msour++;
pdest += 8 * (width / 8);
if (width % 8) {
for (unsigned int i = width - width % 8; i < width; i++)
*pdest++ = sour[i];
}
sour += width8;
}
_mm_empty();
}
void EZW::storeHband(const unsigned char* a, const unsigned char* b, const unsigned char* c)
{
const unsigned char* A0;
const unsigned char* B0, *B1;
const unsigned char* C0, *C1, *C2, *C3;
for (unsigned int i = 0; i < height; i++) {
A0 = a;
B0 = b;
B1 = B0 + width8;
C0 = c;
C1 = C0 + width8;
C2 = C1 + width8;
C3 = C2 + width8;
for (unsigned int j = 0; j < width; j++) {
if (*A0 != 128 || checkBband(B0, B1)) {
setbits(1);
setcoeffs(*A0);
if (*B0 != 128) {
setbits(1);
setcoeffs(*B0);
if (*C0 != 128) {
setbits(1);
setcoeffs(*C0);
} else
setbits(0);
if (*(C0 + 1) != 128) {
setbits(1);
setcoeffs(*(C0 + 1));
} else
setbits(0);
if (*C1 != 128) {
setbits(1);
setcoeffs(*C1);
} else
setbits(0);
if (*(C1 + 1) != 128) {
setbits(1);
setcoeffs(*(C1 + 1));
} else
setbits(0);
} else
setbits(0);
if (*(B0 + 1) != 128) {
setbits(1);
setcoeffs(*(B0 + 1));
if (*(C0 + 2) != 128) {
setbits(1);
setcoeffs(*(C0 + 2));
} else
setbits(0);
if (*(C0 + 3) != 128) {
setbits(1);
setcoeffs(*(C0 + 3));
} else
setbits(0);
if (*(C1 + 2) != 128) {
setbits(1);
setcoeffs(*(C1 + 2));
} else
setbits(0);
if (*(C1 + 3) != 128) {
setbits(1);
setcoeffs(*(C1 + 3));
} else
setbits(0);
} else
setbits(0);
if (*B1 != 128) {
setbits(1);
setcoeffs(*B1);
if (*C2 != 128) {
setbits(1);
setcoeffs(*C2);
} else
setbits(0);
if (*(C2 + 1) != 128) {
setbits(1);
setcoeffs(*(C2 + 1));
} else
setbits(0);
if (*C3 != 128) {
setbits(1);
setcoeffs(*C3);
} else
setbits(0);
if (*(C3 + 1) != 128) {
setbits(1);
setcoeffs(*(C3 + 1));
} else
setbits(0);
} else
setbits(0);
if (*(B1 + 1) != 128) {
setbits(1);
setcoeffs(*(B1 + 1));
if (*(C2 + 2) != 128) {
setbits(1);
setcoeffs(*(C2 + 2));
} else
setbits(0);
if (*(C2 + 3) != 128) {
setbits(1);
setcoeffs(*(C2 + 3));
} else
setbits(0);
if (*(C3 + 2) != 128) {
setbits(1);
setcoeffs(*(C3 + 2));
} else
setbits(0);
if (*(C3 + 3) != 128) {
setbits(1);
setcoeffs(*(C3 + 3));
} else
setbits(0);
} else
setbits(0);
} else
setbits(0);
A0++;
B0 += 2;
B1 += 2;
C0 += 4;
C1 += 4;
C2 += 4;
C3 += 4;
}//for( unsigned int j = 0; j < width; j++ ) {
a += width8;
b += 2 * width8;
c += 4 * width8;
}//for( unsigned int i = 0; i < height; i++ )
}
void EZW::storeHband(const char* a, const char* b, const char* c)
{
const char* A0;
const char* B0, *B1;
const char* C0, *C1, *C2, *C3;
for (unsigned int i = 0; i < height; i++) {
A0 = a;
B0 = b;
B1 = B0 + width8;
C0 = c;
C1 = C0 + width8;
C2 = C1 + width8;
C3 = C2 + width8;
for (unsigned int j = 0; j < width; j++) {
if (*A0 != 0 || checkBband(B0, B1)) {
setbits(1);
setcoeffs(*A0);
if (*B0 != 0) {
setbits(1);
setcoeffs(*B0);
if (*C0 != 0) {
setbits(1);
setcoeffs(*C0);
} else
setbits(0);
if (*(C0 + 1) != 0) {
setbits(1);
setcoeffs(*(C0 + 1));
} else
setbits(0);
if (*C1 != 0) {
setbits(1);
setcoeffs(*C1);
} else
setbits(0);
if (*(C1 + 1) != 0) {
setbits(1);
setcoeffs(*(C1 + 1));
} else
setbits(0);
} else
setbits(0);
if (*(B0 + 1) != 0) {
setbits(1);
setcoeffs(*(B0 + 1));
if (*(C0 + 2) != 0) {
setbits(1);
setcoeffs(*(C0 + 2));
} else
setbits(0);
if (*(C0 + 3) != 0) {
setbits(1);
setcoeffs(*(C0 + 3));
} else
setbits(0);
if (*(C1 + 2) != 0) {
setbits(1);
setcoeffs(*(C1 + 2));
} else
setbits(0);
if (*(C1 + 3) != 0) {
setbits(1);
setcoeffs(*(C1 + 3));
} else
setbits(0);
} else
setbits(0);
if (*B1 != 0) {
setbits(1);
setcoeffs(*B1);
if (*C2 != 0) {
setbits(1);
setcoeffs(*C2);
} else
setbits(0);
if (*(C2 + 1) != 0) {
setbits(1);
setcoeffs(*(C2 + 1));
} else
setbits(0);
if (*C3 != 0) {
setbits(1);
setcoeffs(*C3);
} else
setbits(0);
if (*(C3 + 1) != 0) {
setbits(1);
setcoeffs(*(C3 + 1));
} else
setbits(0);
} else
setbits(0);
if (*(B1 + 1) != 0) {
setbits(1);
setcoeffs(*(B1 + 1));
if (*(C2 + 2) != 0) {
setbits(1);
setcoeffs(*(C2 + 2));
} else
setbits(0);
if (*(C2 + 3) != 0) {
setbits(1);
setcoeffs(*(C2 + 3));
} else
setbits(0);
if (*(C3 + 2) != 0) {
setbits(1);
setcoeffs(*(C3 + 2));
} else
setbits(0);
if (*(C3 + 3) != 0) {
setbits(1);
setcoeffs(*(C3 + 3));
} else
setbits(0);
} else
setbits(0);
} else
setbits(0);
A0++;
B0 += 2;
B1 += 2;
C0 += 4;
C1 += 4;
C2 += 4;
C3 += 4;
}//for( unsigned int j = 0; j < width; j++ ) {
a += width8;
b += 2 * width8;
c += 4 * width8;
}//for( unsigned int i = 0; i < height; i++ )
}
//////////////////////////////////store LL,HH bands//////////////////////////////////////////////////////
//////////////////////////////////read LL,HH bands///////////////////////////////////////////////////////
void EZW::readLband(unsigned char* dest)
{
for (unsigned int j = 0; j < height; j++) {
__m64* mdest = (__m64 *)dest;
__m64* msour = (__m64 *)psour;
for (unsigned int i = 0; i < width / 8; i++)
*mdest++ = *msour++;
psour += 8 * (width / 8);
if (width % 8) {
for (unsigned int i = width - width % 8; i < width; i++)
dest[i] = *psour++;
}
dest += width8;
}
_mm_empty();
}
void EZW::readHband(unsigned char* a, unsigned char* b, unsigned char* c)
{
unsigned char* A0;
unsigned char* B0, *B1;
unsigned char* C0, *C1, *C2, *C3;
for (unsigned int i = 0; i < height; i++) {
A0 = a;
B0 = b;
B1 = B0 + width8;
C0 = c;
C1 = C0 + width8;
C2 = C1 + width8;
C3 = C2 + width8;
for (unsigned int j = 0; j < width; j++) {
if (getbits() != 0) {
*A0 = getcoeffs();
if (getbits() != 0) {
*B0 = getcoeffs();
if (getbits() != 0)
*C0 = getcoeffs();
if (getbits() != 0)
*(C0 + 1) = getcoeffs();
if (getbits() != 0)
*C1 = getcoeffs();
if (getbits())
*(C1 + 1) = getcoeffs();
}
if (getbits() != 0) {
*(B0 + 1) = getcoeffs();
if (getbits() != 0)
*(C0 + 2) = getcoeffs();
if (getbits() != 0)
*(C0 + 3) = getcoeffs();
if (getbits() != 0)
*(C1 + 2) = getcoeffs();
if (getbits() != 0)
*(C1 + 3) = getcoeffs();
}
if (getbits() != 0) {
*B1 = getcoeffs();
if (getbits() != 0)
*C2 = getcoeffs();
if (getbits() != 0)
*(C2 + 1) = getcoeffs();
if (getbits() != 0)
*C3 = getcoeffs();
if (getbits() != 0)
*(C3 + 1) = getcoeffs();
}
if (getbits() != 0) {
*(B1 + 1) = getcoeffs();
if (getbits() != 0)
*(C2 + 2) = getcoeffs();
if (getbits() != 0)
*(C2 + 3) = getcoeffs();
if (getbits() != 0)
*(C3 + 2) = getcoeffs();
if (getbits() != 0)
*(C3 + 3) = getcoeffs();
}
}
A0++;
B0 += 2;
B1 += 2;
C0 += 4;
C1 += 4;
C2 += 4;
C3 += 4;
}//for( unsigned int j = 0; j < width; j++ ) {
a += width8;
b += 2 * width8;
c += 4 * width8;
}//for( unsigned int i = 0; i < height; i++ ) {
}
void EZW::readHband(char* a, char* b, char* c)
{
char* A0;
char* B0, *B1;
char* C0, *C1, *C2, *C3;
for (unsigned int i = 0; i < height; i++) {
A0 = a;
B0 = b;
B1 = B0 + width8;
C0 = c;
C1 = C0 + width8;
C2 = C1 + width8;
C3 = C2 + width8;
for (unsigned int j = 0; j < width; j++) {
if (getbits() != 0) {
*A0 = (char)getcoeffs();
if (getbits() != 0) {
*B0 = (char)getcoeffs();
if (getbits() != 0)
*C0 = (char)getcoeffs();
if (getbits() != 0)
*(C0 + 1) = (char)getcoeffs();
if (getbits() != 0)
*C1 = (char)getcoeffs();
if (getbits())
*(C1 + 1) = (char)getcoeffs();
}
if (getbits() != 0) {
*(B0 + 1) = (char)getcoeffs();
if (getbits() != 0)
*(C0 + 2) = (char)getcoeffs();
if (getbits() != 0)
*(C0 + 3) = (char)getcoeffs();
if (getbits() != 0)
*(C1 + 2) = (char)getcoeffs();
if (getbits() != 0)
*(C1 + 3) = (char)getcoeffs();
}
if (getbits() != 0) {
*B1 = (char)getcoeffs();
if (getbits() != 0)
*C2 = (char)getcoeffs();
if (getbits() != 0)
*(C2 + 1) = (char)getcoeffs();
if (getbits() != 0)
*C3 = (char)getcoeffs();
if (getbits() != 0)
*(C3 + 1) = (char)getcoeffs();
}
if (getbits() != 0) {
*(B1 + 1) = (char)getcoeffs();
if (getbits() != 0)
*(C2 + 2) = (char)getcoeffs();
if (getbits() != 0)
*(C2 + 3) = (char)getcoeffs();
if (getbits() != 0)
*(C3 + 2) = (char)getcoeffs();
if (getbits() != 0)
*(C3 + 3) = (char)getcoeffs();
}
}
A0++;
B0 += 2;
B1 += 2;
C0 += 4;
C1 += 4;
C2 += 4;
C3 += 4;
}//for( unsigned int j = 0; j < width; j++ ) {
a += width8;
b += 2 * width8;
c += 4 * width8;
}//for( unsigned int i = 0; i < height; i++ ) {
}
//////////////////////////////////read LL,HH bands///////////////////////////////////////////////////////
/////////////////////////////////mmx routines////////////////////////////////////////////////////////////
void EZW::mmxmemset(unsigned char* dest, unsigned int size, unsigned char c) const
{
__m64 val;
__m64* mdest = (__m64 *)dest;
val = _mm_setr_pi8(c, c, c, c, c, c, c, c);
for (unsigned int i = 0; i < size / 8; i++)
*mdest++ = val;
if (size % 8) {
dest = (unsigned char *)mdest;
for (unsigned int i = 0; i < size % 8; i++)
*dest++ = c;
}
_mm_empty();
}
void EZW::mmxmemcpy(unsigned char* dest, const unsigned char* sour, unsigned int size) const
{
__m64* mdest = (__m64 *)dest;
__m64* msour = (__m64 *)sour;
for (unsigned int i = 0; i < size / 8; i++)
*mdest++ = *msour++;
if (size % 8) {
dest = (unsigned char *)mdest;
sour = (unsigned char *)msour;
for (unsigned int i = 0; i < size % 8; i++)
*dest++ = *sour++;
}
_mm_empty();
}
/////////////////////////////////mmx routines////////////////////////////////////////////////////////////