#ifndef IZ_ENCODER_H
#define IZ_ENCODER_H 1
#include <cstring>
#include "iz_p.h"
namespace IZ {
#define encodePixel(predictor) \
{ \
Pixel<> pix, pp; \
\
pix.readFrom(p); \
pp.predict(p, bpp, bpr, predictor::predict); \
pix -= pp; \
pix.forwardTransform(); \
p += bpp; \
pix.toUnsigned(); \
\
int nl = pix.numBits(); \
cx = (cx << CONTEXT_BITS) + nl; \
this->writeBits(dBits[cx & bitMask(2 * CONTEXT_BITS)], dCount[cx & bitMask(2 * CONTEXT_BITS)]); \
pix.writeBits(*this, nl); \
}
template <
int bpp = 3,
typename Predictor = Predictor3avgplane<>,
typename Code = U32
>
class ImageEncoder : public BitEncoder<Code>
{
public:
ImageEncoder() {
memcpy(dBits, staticdBits, sizeof(dBits));
memcpy(dCount, staticdCount, sizeof(dCount));
}
void encodeImagePixels(const Image &im) __attribute__((always_inline)) {
const int bpr = im.samplesPerLine();
const unsigned char *p = im.data();
int size = im.width() * im.height();
const unsigned char *pend = p + bpp * size;
unsigned int cx = (7 << CONTEXT_BITS) + 7;
encodePixel(Predictor0<>);
const unsigned char *endline = p + bpr - bpp;
while (p != endline) {
encodePixel(Predictor1x<>);
}
while (p != pend) {
encodePixel(Predictor1y<>);
const unsigned char *endline = p + bpr - bpp;
while (p != endline) {
encodePixel(Predictor);
}
}
}
void encodeImageSize(const Image &im) {
int w = im.width() - 1;
int h = im.height() - 1;
int b = IZ::numBits(w | h);
this->writeBits(b, 4);
this->writeBits(w, b);
this->writeBits(h, b);
this->flushCache();
}
private:
unsigned int dBits[1 << (2 * CONTEXT_BITS)];
unsigned int dCount[1 << (2 * CONTEXT_BITS)];
};
}
#endif