X-Git-Url: https://iam.tj/gitweb/gitweb.cgi?p=firmware_extractor.git;a=blobdiff_plain;f=lzw_decode.c;fp=lzw_decode.c;h=e33156039ee40f65c6e184e12eafa8117551cea0;hp=0000000000000000000000000000000000000000;hb=1693f804f61fb9856114c39185ea3eb46e3f93e5;hpb=471193f5356782a85ea6378fd4355db97930d122 diff --git a/lzw_decode.c b/lzw_decode.c new file mode 100644 index 0000000..e331560 --- /dev/null +++ b/lzw_decode.c @@ -0,0 +1,212 @@ +/* + * LZW decoder + * Copyright (c) 2003 Fabrice Bellard. + * Copyright (c) 2006 Konstantin Shishkov. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifdef COMPRESSED_CONFIG_FILE + +#include "cms_lzw.h" + + + +static const uint16_t mask[17] = +{ + 0x0000, 0x0001, 0x0003, 0x0007, + 0x000F, 0x001F, 0x003F, 0x007F, + 0x00FF, 0x01FF, 0x03FF, 0x07FF, + 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF +}; + + +enum FF_LZW_MODES{ + FF_LZW_GIF, + FF_LZW_TIFF +}; + + +/* get one code from stream */ +static int lzw_get_code(LZWDecoderState *s) +{ + int c; + + /* always use TIFF mode */ + + while (s->bbits < s->cursize) { + s->bbuf = (s->bbuf << 8) | (*s->pbuf++); + s->bbits += 8; + } + // printf("TIFF: bbuf=0x%08x bbits=%d cursize=%d\n", s->bbuf, s->bbits, s->cursize); + c = s->bbuf >> (s->bbits - s->cursize); + + s->bbits -= s->cursize; + + // printf("bbits=%d c=0x%08x curmask=0x%08x\n", s->bbits, c, s->curmask); + return c & s->curmask; +} + + +void ff_lzw_decode_tail(LZWDecoderState *s) +{ + /* always use TIFF mode */ + s->pbuf= s->ebuf; +} + + +CmsRet cmsLzw_initDecoder(LZWDecoderState **p, UINT8 *inbuf, UINT32 inbuf_size) +{ + LZWDecoderState *s; + int mode = FF_LZW_TIFF; /* always use TIFF mode */ + int csize = 8; /* the encoder side has this hardcoded, so hardcode here too */ + + *p = (LZWDecoderState *) cmsMem_alloc(sizeof(LZWDecoderState), ALLOC_ZEROIZE); + if (*p == NULL) + { + cmsLog_error("could not allocate %d bytes for decoder state", sizeof(LZWDecoderState)); + return CMSRET_RESOURCE_EXCEEDED; + } + else + { + cmsLog_debug("%d bytes allocated for decoder state", sizeof(LZWDecoderState)); + } + + s = *p; + + /* read buffer */ + s->pbuf = inbuf; + s->ebuf = s->pbuf + inbuf_size; + s->bbuf = 0; + s->bbits = 0; + s->bs = 0; + + /* decoder */ + s->codesize = csize; + s->cursize = s->codesize + 1; + s->curmask = mask[s->cursize]; + s->top_slot = 1 << s->cursize; + s->clear_code = 1 << s->codesize; + s->end_code = s->clear_code + 1; + s->slot = s->newcodes = s->clear_code + 2; + s->oc = s->fc = -1; + s->sp = s->stack; + + s->mode = mode; + s->extra_slot = (s->mode == FF_LZW_TIFF); + + return CMSRET_SUCCESS; +} + + +SINT32 cmsLzw_decode(LZWDecoderState *s, UINT8 *outbuf, UINT32 outlen) +{ + UINT32 l; + int c, code, oc, fc; + uint8_t *sp; + + if (s->end_code < 0) + return -1; + + l = outlen; + sp = s->sp; + oc = s->oc; + fc = s->fc; + + for (;;) { + + while (sp > s->stack) { + // printf("transfer stack to buf, sp=0x%02x buf=%p\n", *sp, outbuf); + *outbuf++ = *(--sp); + if ((--l) == 0) + goto the_end; + } + + c = lzw_get_code(s); + if (c == s->end_code) { + cmsLog_debug("got end code %d", c); + break; + } else if (c == s->clear_code) { + cmsLog_debug("got clear code %d", c); + s->cursize = s->codesize + 1; + s->curmask = mask[s->cursize]; + s->slot = s->newcodes; + s->top_slot = 1 << s->cursize; + fc= oc= -1; + } else { + code = c; + // printf("got valid code %d (0x%02x)\n", c, c); + + if (code == s->slot && fc>=0) { + *sp++ = fc; + code = oc; + }else if(code >= s->slot) { + cmsLog_error("code %d greater than slot %d", code, s->slot); + break; + } + + while (code >= s->newcodes) { + // printf("transfer suffix to to sp \n"); + *sp++ = s->suffix[code]; + code = s->prefix[code]; + } + + // printf("sp=%p gets code %d\n", sp, code); + *sp++ = code; + + + if (s->slot < s->top_slot && oc>=0) { + // printf("suffix[%d]=%d prefix[%d]=%d\n", s->slot, code, s->slot, oc); + s->suffix[s->slot] = code; + s->prefix[s->slot++] = oc; + } + fc = code; + oc = c; + + if (s->slot >= s->top_slot - s->extra_slot) { + if (s->cursize < LZW_MAXBITS) { + s->top_slot <<= 1; + s->curmask = mask[++s->cursize]; + // printf("new top_slot=0x%x curmask=0x%x\n", s->top_slot, s->curmask); + } + } + } + } // end of for loop + + + s->end_code = -1; + the_end: + s->sp = sp; + s->oc = oc; + s->fc = fc; + + cmsLog_debug("about to return, outlen=%d l=%d\n", outlen, l); + return outlen - l; +} + + + +void cmsLzw_cleanupDecoder(LZWDecoderState **s) +{ + cmsMem_free(*s); + *s = NULL; +} + + + +#endif /* COMPRESSED_CONFIG_FILE */