| |
| |
| #include "tiffiop.h" |
| #include <assert.h> |
| #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; |
| tif->tif_encodestrip = 0; |
| tif->tif_encodetile = 0; |
| return 1; |
| } |
| |
| |
| static int Toonz1Decode(TIFF *tif, tidataval_t *buffer, tsize_t bytes, |
| tsample_t s) { |
| int enc, dec; |
| short bitspersample; |
| |
| 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"); |
| |
| |
| |
| |
| 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; |
| } |
| |
| |
| |
| 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; |
| } |
| |
| |
| |
| 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 |
| |
| |
| |
| |
| |
| 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; |
| case 4: return 8 * n_pix + 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; |
| |
| |
| 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 |
| |
| } |
| |
| 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; |
| |
| |
| 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; |
| |
| |
| |
| 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 |
| |