diff --git a/toonz/sources/image/CMakeLists.txt b/toonz/sources/image/CMakeLists.txt index 06f463d..de8a302 100644 --- a/toonz/sources/image/CMakeLists.txt +++ b/toonz/sources/image/CMakeLists.txt @@ -68,6 +68,7 @@ if(NOT BUILD_TARGET_BSD) tif/tiio_tif.cpp tzp/tiio_plt.cpp tzp/tiio_tzp.cpp + tzp/toonzrle.cpp tzp/avl.c ) endif() diff --git a/toonz/sources/image/tzp/toonzrle.cpp b/toonz/sources/image/tzp/toonzrle.cpp new file mode 100644 index 0000000..adba281 --- /dev/null +++ b/toonz/sources/image/tzp/toonzrle.cpp @@ -0,0 +1,1426 @@ + + +#include "tiffiop.h" +#include +#include "toonztags.h" +#include "tnztypes.h" + +#ifndef UCHAR +#define UCHAR unsigned char +#endif + +#ifndef USHORT +#define USHORT unsigned short +#endif + +#ifndef UINT +#define UINT TUINT32 +#endif + +extern "C" { +static int tif_toonz1_decode_cm24(UCHAR* buf_in, int* buf_in_len, + TUINT32* buf_out); + +static int tif_toonz1_decode_cm16(UCHAR* buf_in, int* buf_in_len, + USHORT* buf_out, int tone_bits, + int color_offs, int color_bits, + int pencil_offs, int pencil_bits, + USHORT offset_mask); +static int Toonz1Decode(TIFF* tif, tidataval_t* buffer, tsize_t bytes, + tsample_t s); + +static int TIFFInitToonz1(TIFF* tif, int) { + tif->tif_decoderow = Toonz1Decode; + tif->tif_decodestrip = 0; + tif->tif_decodetile = 0; + tif->tif_encoderow = 0; // Toonz1Encode; + tif->tif_encodestrip = 0; + tif->tif_encodetile = 0; + return 1; +} +//-------------------- DECODE + +static int Toonz1Decode(TIFF* tif, tidataval_t* buffer, tsize_t bytes, + tsample_t s) { + int enc, dec; + short bitspersample; + // USHORT *palette; + int tone_bits, color_offs, color_bits, pencil_offs, pencil_bits; + USHORT offset_mask; + + if (!TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample)) assert(0); + enc = dec = 0; + switch (bitspersample) { + case 8: + assert(!"Not Implemented"); + /* +dec = tif_toonz1_decode_extra ((UCHAR *)tif->tif_rawcp, &enc, + (UCHAR *)buffer); +*/ + break; + + case 16: { + USHORT* palette; + USHORT paletteCount; + if (TIFFGetField(tif, TIFFTAG_TOONZPALETTE, &paletteCount, &palette)) { + tone_bits = palette[4]; + color_offs = palette[5]; + color_bits = palette[6]; + pencil_offs = palette[7]; + pencil_bits = palette[8]; + offset_mask = palette[9]; + } else { + tone_bits = 4; + color_offs = 4; + color_bits = 7; + pencil_offs = 11; + pencil_bits = 5; + offset_mask = 0; + } + dec = tif_toonz1_decode_cm16((UCHAR*)tif->tif_rawcp, &enc, (USHORT*)buffer, + tone_bits, color_offs, color_bits, pencil_offs, + pencil_bits, offset_mask); + } break; + + case 32: + dec = + tif_toonz1_decode_cm24((UCHAR*)tif->tif_rawcp, &enc, (TUINT32*)buffer); + break; + + default: + assert(0); + } + assert(enc); + assert(dec * bitspersample == bytes * 8); + tif->tif_rawcc += enc; + tif->tif_rawcp += enc; + + return 1; +} + +//-------------------- DECODE CM16 ---------------------------- + +static int tif_toonz1_decode_cm16(UCHAR* buf_in, int* buf_in_len, + USHORT* buf_out, int tone_bits, + int color_offs, int color_bits, + int pencil_offs, int pencil_bits, + USHORT offset_mask) + +{ + UCHAR* in; + USHORT* out; + int count, col_offs, pen_offs; + UINT inval, in0, in1, tmp, not_colmask, not_penmask; + UINT outval, maxtone, outval_maxtone; + +#define GET_IN0 (inval = *in++, in1 = inval & 0xF, in0 = inval >> 4) + + maxtone = (1U << tone_bits) - 1U; + col_offs = color_offs; + pen_offs = pencil_offs; + not_colmask = ~(((1U << color_bits) - 1U) << color_offs); + not_penmask = ~(((1U << pencil_bits) - 1U) << pencil_offs); + assert(maxtone <= 0xF); + outval = offset_mask; + outval_maxtone = outval | maxtone; + + in = buf_in; + out = buf_out; + + goto start_from_in0; + +count_out_and_start_from_in0: + outval_maxtone = outval | maxtone; + *out++ = (USHORT)outval_maxtone; + while (count--) *out++ = (USHORT)outval_maxtone; + +start_from_in0: + if (GET_IN0 == 0xF) { + switch (in1) { + case 0x0: + *out++ = (USHORT)(outval | maxtone); + goto start_from_in0; + break; + + case 0x1: + count = GET_IN0; + goto count_out_and_start_from_in1; + break; + + case 0x2: + count = *in++; + goto count_out_and_start_from_in0; + break; + + case 0x3: + count = *in++ << 4; + count += GET_IN0; + goto count_out_and_start_from_in1; + break; + + case 0x4: + count = *in++ << 8; + count += *in++; + goto count_out_and_start_from_in0; + break; + + case 0x5: + count = *in++ << 12; + count += *in++ << 4; + count += GET_IN0; + goto count_out_and_start_from_in1; + + break; + + case 0x6: + count = *in++ << 16; + count += *in++ << 8; + count += *in++; + goto count_out_and_start_from_in0; + + break; + + case 0x7: + count = *in++ << 20; + count += *in++ << 12; + count += *in++ << 4; + count += GET_IN0; + goto count_out_and_start_from_in1; + + break; + + case 0x8: + outval &= not_colmask; + goto start_from_in0; + + break; + + case 0x9: + outval &= not_penmask; + goto start_from_in0; + + break; + + case 0xA: + outval = outval & not_colmask | GET_IN0 << col_offs; + goto start_from_in1; + + break; + + case 0xB: + outval = outval & not_penmask | GET_IN0 << pen_offs; + goto start_from_in1; + + break; + + case 0xC: + outval = outval & not_colmask | *in++ << col_offs; + goto start_from_in0; + + break; + + case 0xD: + outval = outval & not_penmask | *in++ << pen_offs; + goto start_from_in0; + + break; + + case 0xE: + *out++ = (USHORT)(outval | maxtone); + goto end_rle_decoding; + + break; + + case 0xF: + switch (GET_IN0) { + case 0: + break; + case 1: + tmp = in1 << 12 | *in++ << 4; + *out++ = (USHORT)(tmp | GET_IN0); + break; + default: + goto rle_decoding_error; + } + goto end_rle_decoding; + + break; + default: + goto rle_decoding_error; + } + } else { + *out++ = (USHORT)(outval | in0); + goto start_from_in1; + } + +count_out_and_start_from_in1: + outval_maxtone = outval | maxtone; + *out++ = (USHORT)(outval_maxtone); + while (count--) *out++ = (USHORT)(outval_maxtone); + +start_from_in1: + if (in1 == 0xF) { + switch (GET_IN0) { + case 0x0: + *out++ = (USHORT)(outval | maxtone); + goto start_from_in1; + + break; + + case 0x1: + count = in1; + goto count_out_and_start_from_in0; + + break; + + case 0x2: + count = in1 << 4; + count += GET_IN0; + goto count_out_and_start_from_in1; + + break; + + case 0x3: + count = in1 << 8; + count += *in++; + goto count_out_and_start_from_in0; + + break; + + case 0x4: + count = in1 << 12; + count += *in++ << 4; + count += GET_IN0; + goto count_out_and_start_from_in1; + + break; + + case 0x5: + count = in1 << 16; + count += *in++ << 8; + count += *in++; + goto count_out_and_start_from_in0; + + break; + + case 0x6: + count = in1 << 20; + count += *in++ << 12; + count += *in++ << 4; + count += GET_IN0; + goto count_out_and_start_from_in1; + + break; + + case 0x7: + count = in1 << 24; + count += *in++ << 16; + count += *in++ << 8; + count += *in++; + goto count_out_and_start_from_in0; + + break; + + case 0x8: + outval &= not_colmask; + goto start_from_in1; + + break; + + case 0x9: + outval &= not_penmask; + goto start_from_in1; + + break; + + case 0xA: + outval = outval & not_colmask | in1 << col_offs; + goto start_from_in0; + + break; + + case 0xB: + outval = outval & not_penmask | in1 << pen_offs; + goto start_from_in0; + + break; + + case 0xC: + tmp = in1 << 4; + outval = outval & not_colmask | (tmp | GET_IN0) << col_offs; + goto start_from_in1; + + break; + + case 0xD: + tmp = in1 << 4; + outval = outval & not_penmask | (tmp | GET_IN0) << pen_offs; + goto start_from_in1; + + break; + + case 0xE: + *out++ = (USHORT)(outval | maxtone); + goto end_rle_decoding; + + break; + + case 0xF: + switch (in1) { + case 0: + break; + case 1: + tmp = *in++ << 8; + *out++ = (USHORT)(tmp | *in++); + break; + default: + goto rle_decoding_error; + } + goto end_rle_decoding; + + break; + default: + return 0; + } + } else { + *out++ = (USHORT)(outval | in1); + goto start_from_in0; + } + +end_rle_decoding: + if (buf_in_len) *buf_in_len = (int)(in - buf_in); + return (int)(out - buf_out); + +rle_decoding_error: + if (buf_in_len) *buf_in_len = 0; + return 0; +} + +//-------------------- DECODE CM24 ---------------------------- + +static int tif_toonz1_decode_cm24(UCHAR* buf_in, int* buf_in_len, + TUINT32* buf_out) { + UCHAR* in; + TUINT32* out; + int count; + TUINT32 inval, tmp; + TUINT32 outval, outval_maxtone; + const int col_offs = 8; + const int pen_offs = 16; + const int xub_offs = 24; + const TUINT32 not_colmask = 0xffff00ff; + const TUINT32 not_penmask = 0xff00ffff; + const TUINT32 not_xubmask = 0x00ffffff; + const TUINT32 maxtone = 0x000000ff; + + outval = 0; + outval_maxtone = outval | maxtone; + + in = buf_in; + out = buf_out; + + for (;;) { + inval = *in++; + switch (inval) { + case 0xF6: + outval = outval & not_xubmask | *in++ << xub_offs; + + break; + + case 0xF7: + count = *in++; + goto count_out; + + break; + + case 0xF8: + count = *in++ << 8; + count += *in++; + goto count_out; + + break; + + case 0xF9: + count = *in++ << 16; + count += *in++ << 8; + count += *in++; + goto count_out; + + break; + + case 0xFA: + outval &= not_colmask; + + break; + + case 0xFB: + outval &= not_penmask; + + break; + + case 0xFC: + outval = outval & not_colmask | *in++ << col_offs; + + break; + + case 0xFD: + outval = outval & not_penmask | *in++ << pen_offs; + + break; + + case 0xFE: + switch (*in++) { + case 0: + break; + case 1: + *out++ = outval | maxtone; + break; + + case 2: + tmp = *in++; + tmp = tmp << 8 | *in++; + tmp = tmp << 8 | *in++; + *out++ = tmp << 8 | *in++; + break; + + default: + goto rle_decoding_error; + } + goto end_rle_decoding; + + break; + + case 0xFF: + *out++ = outval | *in++; + + break; + + default: + *out++ = outval | inval; + } + continue; + + count_out: + outval_maxtone = outval | maxtone; + *out++ = outval_maxtone; + while (count--) *out++ = outval_maxtone; + } + +end_rle_decoding: + if (buf_in_len) *buf_in_len = (int)(in - buf_in); + return (int)(out - buf_out); + +rle_decoding_error: + if (buf_in_len) *buf_in_len = 0; + return 0; +} +} + +//============================================================================= + +namespace { + +class ToonzRleCodecRegisterer { + static TIFFCodec* m_codec; + +public: + ToonzRleCodecRegisterer() { + uint16 scheme = 32881; + const char* name = "TOONZ4RLE"; + m_codec = TIFFRegisterCODEC(scheme, name, &TIFFInitToonz1); + } + ~ToonzRleCodecRegisterer() { + TIFFUnRegisterCODEC(m_codec); + m_codec = 0; + } +}; + +TIFFCodec* ToonzRleCodecRegisterer::m_codec = 0; + +ToonzRleCodecRegisterer registerer; +} // namespace + +//============================================================================= + +#if 0 + +/* +Queste stanno qui piu' che altro per memoria... +*/ + +extern "C" { + + /*===========================================================================*/ + + /*---------------------------------------------------------------------------*/ + +#define GET_INVAL \ + { \ + inval = *in++; \ + remain--; \ + } +#define PUT_OUTVAL \ + { *out++ = (UCHAR)outval; } + +/*---------------------------------------------------------------------------*/ + + int tif_toonz1_safe_bytes_for_pixels(int n_pix, int pixbytes) + { + if (n_pix < 0) + return 0; + switch (pixbytes) + { + case 1: return 2 * n_pix + 1; + case 2: return 5 * n_pix + 2; /* == 2.5 * n_bytes + 2 */ + case 4: return 8 * n_pix + 6; /* == 2 * n_bytes + 6 */ + } + return 0; + } + + /*---------------------------------------------------------------------------*/ + + static int tif_toonz1_encode_cm16(USHORT* buf_in, int buf_in_len, + UCHAR* buf_out, + int tone_bits, + int color_offs, int color_bits, + int pencil_offs, int pencil_bits, + USHORT offset_mask) + { + int count, prevremain, remain; + UINT inval, outval; + UINT lastcol__, lastpen__, lastval, lastcolpen; + int col_offs, pen_offs; + UINT colpenmask, colmask, penmask, maxtone; + UINT incolpen, incol__, incol, inpen__, inpen, tone; + USHORT* in, save; + UCHAR* out; + + maxtone = (1U << tone_bits) - 1U; + col_offs = color_offs; + pen_offs = pencil_offs; + colmask = ((1U << color_bits) - 1U) << color_offs; + penmask = ((1U << pencil_bits) - 1U) << pencil_offs; + colpenmask = colmask | penmask; + + remain = buf_in_len; + lastcol__ = 0; + lastpen__ = 0; + lastval = offset_mask | maxtone; + lastcolpen = 0; + + in = buf_in; + out = buf_out; + + if (buf_in_len <= 1) + { + if (buf_in_len < 0) + return 0; + if (buf_in_len == 0) + { + outval = 0xFF; + PUT_OUTVAL + outval = 0x00; + PUT_OUTVAL + } + else + { + GET_INVAL + if (inval == (offset_mask | maxtone)) + { + outval = 0xFE; + PUT_OUTVAL + } + else + { + outval = 0xFF; + PUT_OUTVAL + outval = 0x10 | inval >> 12; + PUT_OUTVAL + outval = inval >> 4; + PUT_OUTVAL + outval = inval << 4; + PUT_OUTVAL + } + } + return out - buf_out; + } + + save = buf_in[buf_in_len - 1]; + buf_in[buf_in_len - 1] = buf_in[buf_in_len - 2] ^ colpenmask; + + GET_INVAL + + check_colpen_on_out0 : + incolpen = inval & colpenmask; + if (incolpen == lastcolpen) + goto check_tone_on_out0; + lastcolpen = incolpen; + if (!remain) + goto end_toonz1_encoding_on_out0; + + /*check_col_on_out0:*/ + incol__ = inval & colmask; + if (incol__ != lastcol__) + { + lastcol__ = incol__; + if (incol__ == 0) + { + outval = (0xF << 4) | 0x8; + PUT_OUTVAL + goto check_pen_on_out0; + } + else + { + incol = incol__ >> col_offs; + if (incol <= 0xF) + { + outval = (0xF << 4) | 0xA; + PUT_OUTVAL + outval = incol << 4; + goto check_pen_on_out1; + } + else + { + outval = (0xF << 4) | 0xC; + PUT_OUTVAL + outval = incol; + PUT_OUTVAL + goto check_pen_on_out0; + } + } + } + check_pen_on_out0: + inpen__ = inval & penmask; + if (inpen__ != lastpen__) + { + lastpen__ = inpen__; + if (inpen__ == 0) + { + outval = (0xF << 4) | 0x9; + PUT_OUTVAL + goto check_tone_on_out0; + } + else + { + inpen = inpen__ >> pen_offs; + if (inpen <= 0xF) + { + outval = (0xF << 4) | 0xB; + PUT_OUTVAL + outval = inpen << 4; + goto check_tone_on_out1; + } + else + { + outval = (0xF << 4) | 0xD; + PUT_OUTVAL + outval = inpen; + PUT_OUTVAL + goto check_tone_on_out0; + } + } + } + check_tone_on_out0: + tone = inval & maxtone; + if (tone == maxtone) + { + lastval = inval; + prevremain = remain; + do + GET_INVAL + while (inval == lastval); + count = prevremain - remain - 1; + if (count <= 0xF) + if (count == 0) + { + outval = (0xF << 4) | 0x0; + PUT_OUTVAL + goto check_colpen_on_out0; + } + else + { + outval = (0xF << 4) | 0x1; + PUT_OUTVAL + outval = count << 4; + goto check_colpen_on_out1; + } + else if (count <= 0xFF) + { + outval = (0xF << 4) | 0x2; + PUT_OUTVAL + outval = count; + PUT_OUTVAL + goto check_colpen_on_out0; + } + else if (count <= 0xFFF) + { + outval = (0xF << 4) | 0x3; + PUT_OUTVAL + outval = count >> 4; + PUT_OUTVAL + outval = count << 4; + goto check_colpen_on_out1; + } + else if (count <= 0xFFFF) + { + outval = (0xF << 4) | 0x4; + PUT_OUTVAL + outval = count >> 8; + PUT_OUTVAL + outval = count; + PUT_OUTVAL + goto check_colpen_on_out0; + } + else if (count <= 0xFFFFF) + { + outval = (0xF << 4) | 0x5; + PUT_OUTVAL + outval = count >> 12; + PUT_OUTVAL + outval = count >> 4; + PUT_OUTVAL + outval = count << 4; + goto check_colpen_on_out1; + } + else if (count <= 0xFFFFFF) + { + outval = (0xF << 4) | 0x6; + PUT_OUTVAL + outval = count >> 16; + PUT_OUTVAL + outval = count >> 8; + PUT_OUTVAL + outval = count; + PUT_OUTVAL + goto check_colpen_on_out0; + } + else if (count <= 0xFFFFFFF) + { + outval = (0xF << 4) | 0x7; + PUT_OUTVAL + outval = count >> 20; + PUT_OUTVAL + outval = count >> 12; + PUT_OUTVAL + outval = count >> 4; + PUT_OUTVAL + outval = count << 4; + goto check_colpen_on_out1; + } + else + { + buf_in[buf_in_len - 1] = save; + return 0; + } + } + else + { + outval = tone << 4; + GET_INVAL + /*goto check_colpen_on_out1;*/ + } + + check_colpen_on_out1: + incolpen = inval & colpenmask; + if (incolpen == lastcolpen) + goto check_tone_on_out1; + lastcolpen = incolpen; + if (!remain) + goto end_toonz1_encoding_on_out1; + + /*check_col_on_out1:*/ + incol__ = inval & colmask; + if (incol__ != lastcol__) + { + lastcol__ = incol__; + outval |= 0xF; + PUT_OUTVAL + if (incol__ == 0) + { + outval = 0x8 << 4; + goto check_pen_on_out1; + } + else + { + incol = incol__ >> col_offs; + if (incol <= 0xF) + { + outval = (0xA << 4) | incol; + PUT_OUTVAL + goto check_pen_on_out0; + } + else + { + outval = (0xC << 4) | (incol >> 4); + PUT_OUTVAL + outval = incol << 4; + goto check_pen_on_out1; + } + } + } + check_pen_on_out1: + inpen__ = inval & penmask; + if (inpen__ != lastpen__) + { + lastpen__ = inpen__; + outval |= 0xF; + PUT_OUTVAL + if (inpen__ == 0) + { + outval = 0x9 << 4; + goto check_tone_on_out1; + } + else + { + inpen = inpen__ >> pen_offs; + if (inpen <= 0xF) + { + outval = (0xB << 4) | inpen; + PUT_OUTVAL + goto check_tone_on_out0; + } + else + { + outval = (0xD << 4) | (inpen >> 4); + PUT_OUTVAL + outval = inpen << 4; + goto check_tone_on_out1; + } + } + } + check_tone_on_out1: + tone = inval & maxtone; + if (tone == maxtone) + { + lastval = inval; + prevremain = remain; + do + GET_INVAL + while (inval == lastval); + count = prevremain - remain - 1; + outval |= 0xF; + PUT_OUTVAL + if (count <= 0xF) + if (count == 0) + { + outval = 0x0 << 4; + goto check_colpen_on_out1; + } + else + { + outval = (0x1 << 4) | count; + PUT_OUTVAL + goto check_colpen_on_out0; + } + else if (count <= 0xFF) + { + outval = (0x2 << 4) | (count >> 4); + PUT_OUTVAL + outval = count << 4; + goto check_colpen_on_out1; + } + else if (count <= 0xFFF) + { + outval = (0x3 << 4) | (count >> 8); + PUT_OUTVAL + outval = count; + PUT_OUTVAL + goto check_colpen_on_out0; + } + else if (count <= 0xFFFF) + { + outval = (0x4 << 4) | (count >> 12); + PUT_OUTVAL + outval = count >> 4; + PUT_OUTVAL + outval = count << 4; + goto check_colpen_on_out1; + } + else if (count <= 0xFFFFF) + { + outval = (0x5 << 4) | (count >> 16); + PUT_OUTVAL + outval = count >> 8; + PUT_OUTVAL + outval = count; + PUT_OUTVAL + goto check_colpen_on_out0; + } + else if (count <= 0xFFFFFF) + { + outval = (0x6 << 4) | (count >> 20); + PUT_OUTVAL + outval = count >> 12; + PUT_OUTVAL + outval = count >> 4; + PUT_OUTVAL + outval = count << 4; + goto check_colpen_on_out1; + } + else if (count <= 0xFFFFFFF) + { + outval = (0x7 << 4) | (count >> 24); + PUT_OUTVAL + outval = count >> 16; + PUT_OUTVAL + outval = count >> 8; + PUT_OUTVAL + outval = count; + PUT_OUTVAL + goto check_colpen_on_out0; + } + else + { + buf_in[buf_in_len - 1] = save; + return 0; + } + } + else + { + outval |= tone; + PUT_OUTVAL + GET_INVAL + goto check_colpen_on_out0; + } + + end_toonz1_encoding_on_out0: + if (save == (in[-2] | maxtone)) + { + outval = 0xFE; + PUT_OUTVAL + } + else + { + outval = 0xFF; + PUT_OUTVAL + outval = 0x10 | save >> 12; + PUT_OUTVAL + outval = save >> 4; + PUT_OUTVAL + outval = save << 4; + PUT_OUTVAL + } + buf_in[buf_in_len - 1] = save; + return out - buf_out; + + end_toonz1_encoding_on_out1: + if (save == (in[-2] | maxtone)) + { + outval |= 0xF; + PUT_OUTVAL + outval = 0xE0; + PUT_OUTVAL + } + else + { + outval |= 0xF; + PUT_OUTVAL + outval = 0xF1; + PUT_OUTVAL + outval = save >> 8; + PUT_OUTVAL + outval = save; + PUT_OUTVAL + } + buf_in[buf_in_len - 1] = save; + return out - buf_out; + } + + /*---------------------------------------------------------------------------*/ + + static int tif_toonz1_encode_cm24(TUINT32* buf_in, int buf_in_len, + UCHAR* buf_out) + { + int count, prevremain, remain; + TUINT32 inval, outval; + TUINT32 lastcol__, lastpen__, lastxub__, lastval, lastenot; + TUINT32 inenot, incol__, incol, inpen__, inpen, inxub__, inxub, tone; + TUINT32* in, save; + UCHAR* out; + const int col_offs = 8; + const int pen_offs = 16; + const int xub_offs = 24; + const TUINT32 enotmask = 0xffffff00; + const TUINT32 colmask = 0x0000ff00; + const TUINT32 penmask = 0x00ff0000; + const TUINT32 xubmask = 0xff000000; + const TUINT32 maxtone = 0x000000ff; + + /* enot == ~tone , xub == extra upper byte */ + + remain = buf_in_len; + lastcol__ = 0; + lastpen__ = 0; + lastxub__ = 0; + lastval = maxtone; + lastenot = 0; + + in = buf_in; + out = buf_out; + + if (buf_in_len <= 1) + { + if (buf_in_len < 0) + return 0; + if (buf_in_len == 0) + { + outval = 0xFE; + PUT_OUTVAL + outval = 0x00; + PUT_OUTVAL + } + else + { + GET_INVAL + if (inval == maxtone) + { + outval = 0xFE; + PUT_OUTVAL + outval = 0x01; + PUT_OUTVAL + } + else + { + outval = 0xFE; + PUT_OUTVAL + outval = 0x02; + PUT_OUTVAL + outval = inval >> 24; + PUT_OUTVAL + outval = inval >> 16; + PUT_OUTVAL + outval = inval >> 8; + PUT_OUTVAL + outval = inval; + PUT_OUTVAL + } + } + return out - buf_out; + } + + save = buf_in[buf_in_len - 1]; + buf_in[buf_in_len - 1] = buf_in[buf_in_len - 2] ^ enotmask; + + GET_INVAL + + for (;;) + { + inenot = inval & enotmask; + if (inenot != lastenot) + { + lastenot = inenot; + if (!remain) + goto end_toonz1_encoding; + + incol__ = inval & colmask; + if (incol__ != lastcol__) + { + lastcol__ = incol__; + if (incol__ == 0) + { + outval = 0xFA; + PUT_OUTVAL + } + else + { + incol = incol__ >> col_offs; + outval = 0xFC; + PUT_OUTVAL + outval = incol; + PUT_OUTVAL + } + } + inpen__ = inval & penmask; + if (inpen__ != lastpen__) + { + lastpen__ = inpen__; + if (inpen__ == 0) + { + outval = 0xFB; + PUT_OUTVAL + } + else + { + inpen = inpen__ >> pen_offs; + outval = 0xFD; + PUT_OUTVAL + outval = inpen; + PUT_OUTVAL + } + } + inxub__ = inval & xubmask; + if (inxub__ != lastxub__) + { + lastxub__ = inxub__; + inxub = inxub__ >> xub_offs; + outval = 0xF6; + PUT_OUTVAL + outval = inxub; + PUT_OUTVAL + } + } + tone = inval & maxtone; + if (tone == maxtone) + { + lastval = inval; + prevremain = remain; + do + GET_INVAL + while (inval == lastval); + count = prevremain - remain - 1; + if (count <= 0xFF) + { + outval = 0xF7; + PUT_OUTVAL + outval = count; + PUT_OUTVAL + } + else if (count <= 0xFFFF) + { + outval = 0xF8; + PUT_OUTVAL + outval = count >> 8; + PUT_OUTVAL + outval = count; + PUT_OUTVAL + } + else + { + while (count > 0xFFFFFF) + { + outval = 0xF9; + PUT_OUTVAL + outval = 0xFF; + PUT_OUTVAL + outval = 0xFF; + PUT_OUTVAL + outval = 0xFF; + count -= 0xFFFFFF + 1; + } + outval = 0xF9; + PUT_OUTVAL + outval = count >> 16; + PUT_OUTVAL + outval = count >> 8; + PUT_OUTVAL + outval = count; + PUT_OUTVAL + } + } + else + { + if (tone < 0xF6) + { + outval = tone; + PUT_OUTVAL + } + else + { + outval = 0xFF; + PUT_OUTVAL + outval = tone; + PUT_OUTVAL + } + GET_INVAL + } + } + + end_toonz1_encoding: + if (save == (in[-2] | maxtone)) + { + outval = 0xFE; + PUT_OUTVAL + outval = 0x01; + PUT_OUTVAL + } + else + { + outval = 0xFE; + PUT_OUTVAL + outval = 0x02; + PUT_OUTVAL + outval = save >> 24; + PUT_OUTVAL + outval = save >> 16; + PUT_OUTVAL + outval = save >> 8; + PUT_OUTVAL + outval = save; + PUT_OUTVAL + } + buf_in[buf_in_len - 1] = save; + return out - buf_out; + } + + /*---------------------------------------------------------------------------*/ + + static int tif_toonz1_encode_extra(UCHAR* buf_in, int buf_in_len, + UCHAR* buf_out) + { + UCHAR* in, inval, lastval, save; + UCHAR* out; + int count, remain; + + remain = buf_in_len; + in = buf_in; + out = buf_out; + if (buf_in_len < 2) + { + if (!buf_in_len) + { + *out = 0; + return 1; + } + else + { + *out++ = 1; + *out++ = *in; + *out = 0; + return 3; + } + } + save = buf_in[buf_in_len - 1]; + buf_in[buf_in_len - 1] = buf_in[buf_in_len - 2] ^ 0xff; + + lastval = *buf_in; + count = 0; + for (;;) + { + GET_INVAL + if (inval == lastval) + count++; + else + { + while (count >> 15) + { + *out++ = 0xff; + *out++ = 0xff; + *out++ = lastval; + count -= 0x7fff; + } + if (count >> 7) + { + *out++ = 0x80 | count & 0x7f; + *out++ = count >> 7; + } + else + *out++ = count; + *out++ = lastval; + lastval = inval; + count = 1; + if (!remain) + break; + } + } + *out++ = 1; + *out++ = save; + *out++ = 0; + + buf_in[buf_in_len - 1] = save; + return out - buf_out; + } + + + static int tif_toonz1_decode_extra(UCHAR* buf_in, int* buf_in_len, + UCHAR* buf_out) + { + UCHAR* in, val; + UCHAR* out; + int count; + + in = buf_in; + out = buf_out; + for (;;) + { + count = (SCHAR)*in++; + if (count > 0) + { + val = *in++; + while (count--) + *out++ = val; + } + else if (count < 0) + { + count &= 0x7f; + count |= *in++ << 7; + val = *in++; + while (count--) + *out++ = val; + } + else + break; + } + if (buf_in_len) + *buf_in_len = in - buf_in; + return out - buf_out; + } + + /*---------------------------------------------------------------------------*/ + + + + /*---------------------------------------------------------------------------*/ + + static int + DECLARE4(Toonz1Encode, TIFF*, tif, u_char*, buffer, u_long, bytes, u_int, s) + { + int enc; + short bitspersample; + USHORT* palette; + int tone_bits, color_offs, color_bits, pencil_offs, pencil_bits; + USHORT offset_mask; + + if (!TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample)) + assert(0); + enc = 0; + switch (bitspersample) + { + case 8: + enc = tif_toonz1_encode_extra((UCHAR*)buffer, (int)bytes, + (UCHAR*)tif->tif_rawcp); + break; + + case 16: + if (TIFFGetField(tif, TIFFTAG_TOONZPALETTE, &palette)) + { + tone_bits = palette[4]; + color_offs = palette[5]; color_bits = palette[6]; + pencil_offs = palette[7]; pencil_bits = palette[8]; + offset_mask = palette[9]; + } + else + { + tone_bits = 4; + color_offs = 4; color_bits = 7; + pencil_offs = 11; pencil_bits = 5; + offset_mask = 0; + } + enc = tif_toonz1_encode_cm16((USHORT*)buffer, (int)(bytes >> 1), + (UCHAR*)tif->tif_rawcp, + tone_bits, + color_offs, color_bits, + pencil_offs, pencil_bits, offset_mask); + break; + + case 32: + enc = tif_toonz1_encode_cm24((TUINT32*)buffer, (int)(bytes >> 2), + (UCHAR*)tif->tif_rawcp); + break; + + default: + assert(0); + } + assert(enc); + tif->tif_rawcc += enc; + tif->tif_rawcp += enc; + if (tif->tif_rawcc >= tif->tif_rawdatasize) + if (!TIFFFlushData1(tif)) + return -1; + + return 1; + } + + + +} +#endif \ No newline at end of file