diff options
Diffstat (limited to 'Imaging/libImaging/BitDecode.c')
-rw-r--r-- | Imaging/libImaging/BitDecode.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/Imaging/libImaging/BitDecode.c b/Imaging/libImaging/BitDecode.c new file mode 100644 index 0000000..fef719e --- /dev/null +++ b/Imaging/libImaging/BitDecode.c @@ -0,0 +1,138 @@ +/* + * The Python Imaging Library. + * $Id: BitDecode.c 2278 2005-02-07 20:27:33Z fredrik $ + * + * decoder for packed bitfields (converts to floating point) + * + * history: + * 97-05-31 fl created (much more than originally intended) + * + * Copyright (c) Fredrik Lundh 1997. + * Copyright (c) Secret Labs AB 1997. + * + * See the README file for information on usage and redistribution. + */ + + +#include "Imaging.h" + +#include "Bit.h" + + +int +ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) +{ + BITSTATE* bitstate = state->context; + UINT8* ptr; + + if (state->state == 0) { + + /* Initialize context variables */ + + /* this decoder only works for float32 image buffers */ + if (im->type != IMAGING_TYPE_FLOAT32) { + state->errcode = IMAGING_CODEC_CONFIG; + return -1; + } + + /* sanity check */ + if (bitstate->bits < 1 || bitstate->bits >= 32) { + state->errcode = IMAGING_CODEC_CONFIG; + return -1; + } + + bitstate->mask = (1<<bitstate->bits)-1; + + if (bitstate->sign) + bitstate->signmask = (1<<(bitstate->bits-1)); + + /* check image orientation */ + if (state->ystep < 0) { + state->y = state->ysize-1; + state->ystep = -1; + } else + state->ystep = 1; + + state->state = 1; + + } + + ptr = buf; + + while (bytes > 0) { + + UINT8 byte = *ptr; + + ptr++; + bytes--; + + /* get a byte from the input stream and insert in the bit buffer */ + if (bitstate->fill&1) + /* fill MSB first */ + bitstate->bitbuffer |= (unsigned long) byte << bitstate->bitcount; + else + /* fill LSB first */ + bitstate->bitbuffer = (bitstate->bitbuffer << 8) | byte; + + bitstate->bitcount += 8; + + while (bitstate->bitcount >= bitstate->bits) { + + /* get a pixel from the bit buffer */ + unsigned long data; + FLOAT32 pixel; + + if (bitstate->fill&2) { + /* store LSB first */ + data = bitstate->bitbuffer & bitstate->mask; + if (bitstate->bitcount > 32) + /* bitbuffer overflow; restore it from last input byte */ + bitstate->bitbuffer = byte >> (8 - (bitstate->bitcount - + bitstate->bits)); + else + bitstate->bitbuffer >>= bitstate->bits; + } else + /* store MSB first */ + data = (bitstate->bitbuffer >> (bitstate->bitcount - + bitstate->bits)) + & bitstate->mask; + + bitstate->bitcount -= bitstate->bits; + + if (bitstate->lutsize > 0) { + /* map through lookup table */ + if (data <= 0) + pixel = bitstate->lut[0]; + else if (data >= bitstate->lutsize) + pixel = bitstate->lut[bitstate->lutsize-1]; + else + pixel = bitstate->lut[data]; + } else { + /* convert */ + if (data & bitstate->signmask) + /* image memory contains signed data */ + pixel = (FLOAT32) (INT32) (data | ~bitstate->mask); + else + pixel = (FLOAT32) data; + } + + *(FLOAT32*)(&im->image32[state->y][state->x]) = pixel; + + /* step forward */ + if (++state->x >= state->xsize) { + /* new line */ + state->y += state->ystep; + if (state->y < 0 || state->y >= state->ysize) { + /* end of file (errcode = 0) */ + return -1; + } + state->x = 0; + /* reset bit buffer */ + if (bitstate->pad > 0) + bitstate->bitcount = 0; + } + } + } + + return ptr - buf; +} |