#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; } //============================================================================= #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