[FFmpeg-devel] Patch for libavcodec/exr.c implementing B44 compression technique
greeshma
greeshmabalabadra at gmail.com
Wed Mar 18 15:08:22 CET 2015
The .diff file is also attached henceforth.Please have a look.
diff --git a/libavcodec/exr.c b/libavcodec/exr.c
index 6251fb7..cc15a3a 100644
--- a/libavcodec/exr.c
+++ b/libavcodec/exr.c
@@ -770,6 +770,163 @@ static int piz_uncompress(EXRContext *s, const
uint8_t *src, int ssize,
return 0;
}
+
+/*
+
+*
+ * @file
+ * OpenEXR decoder
+ * Digital Ltd. LLC
+ * All rights reserved.
+ *
+ * For more information on the OpenEXR format, visit:
+ * http://openexr.com/
+
+implemetation of B44_uncompress method which is a lossy compression method
which the following features
+
+compression rate 32/14
+works only on channels of HALF .It'll not work on FLOAT and UINT
+the compression method is as follows: It interprets 32byte input data as
16 - 16 bit integers
+It divides it into blocks of 4 by 4 pixels.Itt compresses 16 into 14 bytes.
+*/
+
+static
+void unpack14 (const unsigned char b[14], unsigned short s[16])
+{
+ //
+ // Unpack a 14-byte block into 4 by 4 16-bit pixels.
+ //
+ unsigned short shift,bias;
+ #if defined (DEBUG)
+ assert (b[2] != 0xfc);
+ #endif
+ s[ 0] = (b[0] << 8) | b[1];
+ shift = (b[ 2] >> 2);
+ bias = (0x20 << shift);
+ s[ 4] = s[ 0] + ((((b[ 2] << 4) | (b[ 3] >> 4)) & 0x3f) << shift) -
bias;
+ s[ 8] = s[ 4] + ((((b[ 3] << 2) | (b[ 4] >> 6)) & 0x3f) << shift) -
bias;
+ s[12] = s[ 8] + ((b[ 4] & 0x3f) << shift) -
bias;
+ s[ 1] = s[ 0] + ((b[ 5] >> 2) << shift) -
bias;
+ s[ 5] = s[ 4] + ((((b[ 5] << 4) | (b[ 6] >> 4)) & 0x3f) << shift) -
bias;
+ s[ 9] = s[ 8] + ((((b[ 6] << 2) | (b[ 7] >> 6)) & 0x3f) << shift) -
bias;
+ s[13] = s[12] + ((b[ 7] & 0x3f) << shift) -
bias;
+ s[ 2] = s[ 1] + ((b[ 8] >> 2) << shift) -
bias;
+ s[ 6] = s[ 5] + ((((b[ 8] << 4) | (b[ 9] >> 4)) & 0x3f) << shift) -
bias;
+ s[10] = s[ 9] + ((((b[ 9] << 2) | (b[10] >> 6)) & 0x3f) << shift) -
bias;
+ s[14] = s[13] + ((b[10] & 0x3f) << shift) -
bias;
+ s[ 3] = s[ 2] + ((b[11] >> 2) << shift) -
bias;
+ s[ 7] = s[ 6] + ((((b[11] << 4) | (b[12] >> 4)) & 0x3f) << shift) -
bias;
+ s[11] = s[10] + ((((b[12] << 2) | (b[13] >> 6)) & 0x3f) << shift) -
bias;
+ s[15] = s[14] + ((b[13] & 0x3f) << shift) -
bias;
+ for (int i = 0; i < 16; ++i) {
+ if (s[i] & 0x8000)
+ s[i] &= 0x7fff;
+ else
+ s[i] = ~s[i];
+ }
+}
+
+
+
+static void unpack3 (const unsigned char b[3], unsigned short s[16])
+{
+ //
+ // Unpack a 3-byte block into 4 by 4 identical 16-bit pixels.
+ //
+ #if defined (DEBUG)
+ assert (b[2] == 0xfc);
+ #endif
+ s[0] = (b[0] << 8) | b[1];
+ if (s[0] & 0x8000)
+ s[0] &= 0x7fff;
+ else
+ s[0] = ~s[0];
+ for (int i = 1; i < 16; ++i)
+ s[i] = s[0];
+}
+
+
+
+static int b44_uncompress(EXRContext *s, const uint8_t *src,int
compressed_size, int uncompressed_size,
+EXRThreadData *td)
+{
+ unsigned long dest_len = uncompressed_size;
+ uint8_t *out;
+ int i, j;
+ //int c;
+ uint16_t *ptr;
+ uint16_t *tmp = (uint16_t *)td->tmp;
+ out = td->uncompressed_data;
+ if (uncompress(td->tmp, &dest_len, src, compressed_size) != Z_OK ||
+ dest_len != uncompressed_size)
+ return AVERROR_INVALIDDATA;
+ for (i = 0; i < s->nb_channels; i++) {
+ EXRChannel *channel = &s->channels[i];
+ int size = channel->pixel_type;
+ const char *inPtr=src;
+ int inSize = compressed_size;
+ ptr = tmp;
+ if (channel->pixel_type != EXR_HALF) {
+ //
+ // UINT or FLOAT channel.
+ //
+ int n = s->xdelta * s->ydelta * size * sizeof (unsigned short);
+ memcpy (ptr, inPtr, n);
+ inPtr += n;
+ inSize -= n;
+ continue;
+ } else {
+ //
+ //EXR_HALF Channel
+ for (int y=0; y < s->ydelta; y +=4 ) {
+ unsigned short *row0 = ptr + y * s->xdelta;
+ unsigned short *row1 = row0 + s->xdelta;
+ unsigned short *row2 = row1 + s->xdelta;
+ unsigned short *row3 = row2 + s->xdelta;
+ for (int x = 0; x < s->xdelta; x += 4) {
+ unsigned short stmp[16];
+ if (((const unsigned char *)inPtr)[2] == 0xfc) {
+ unpack3 ((const unsigned char *)inPtr, stmp);
+ inPtr += 3;
+ inSize -= 3;
+ } else {
+ unpack14 ((const unsigned char *)inPtr, stmp);
+ inPtr += 14;
+ inSize -= 14;
+ }
+ int num = (x + 3 < s->xdelta)? 4 * sizeof (unsigned
short) : (s->xdelta - x) * sizeof (unsigned short);
+ if (y + 3 < s->ydelta) {
+ memcpy (row0, &stmp[ 0], num);
+ memcpy (row1, &stmp[ 4], num);
+ memcpy (row2, &stmp[ 8], num);
+ memcpy (row3, &stmp[12], num);
+ } else {
+ memcpy (row0, &stmp[ 0], num);
+ if (y + 1 < s->ydelta)
+ memcpy (row1, &stmp[ 4], num);
+ if (y + 2 < s->ydelta)
+ memcpy (row2, &stmp[ 8], num);
+ }
+ row0 += 4;
+ row1 += 4;
+ row2 += 4;
+ row3 += 4;
+ }
+ }
+ }
+ }
+ for (i = 0; i < s->ysize; i++) {
+ for (j = 0; j < s->nb_channels; j++) {
+ uint16_t *in = tmp + j * s->xdelta * s->ysize + i * s->xdelta;
+ memcpy(out, in, s->xdelta * 2);
+ out += s->xdelta * 2;
+ }
+ }
+ return 0;
+}
+
+
static int pxr24_uncompress(EXRContext *s, const uint8_t *src,
int compressed_size, int uncompressed_size,
EXRThreadData *td)
@@ -888,6 +1045,8 @@ static int decode_block(AVCodecContext *avctx, void
*tdata,
break;
case EXR_RLE:
ret = rle_uncompress(src, data_size, uncompressed_size, td);
+ case EXR_B44:
+ ret = b44_uncompress(s, src, data_size, uncompressed_size, td);
}
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "decode_block() failed.\n");
@@ -1282,6 +1441,7 @@ static int decode_frame(AVCodecContext *avctx, void
*data,
s->scan_lines_per_block = 16;
break;
case EXR_PIZ:
+ case EXR_B44:
s->scan_lines_per_block = 32;
break;
default:
Greeshma Balabhadra
-------------- next part --------------
diff --git a/libavcodec/exr.c b/libavcodec/exr.c
index 6251fb7..cc15a3a 100644
--- a/libavcodec/exr.c
+++ b/libavcodec/exr.c
@@ -770,6 +770,163 @@ static int piz_uncompress(EXRContext *s, const uint8_t *src, int ssize,
return 0;
}
+
+/*
+
+*
+ * @file
+ * OpenEXR decoder
+ * Digital Ltd. LLC
+ * All rights reserved.
+ *
+ * For more information on the OpenEXR format, visit:
+ * http://openexr.com/
+
+implemetation of B44_uncompress method which is a lossy compression method which the following features
+
+compression rate 32/14
+works only on channels of HALF .It'll not work on FLOAT and UINT
+the compression method is as follows: It interprets 32byte input data as 16 - 16 bit integers
+It divides it into blocks of 4 by 4 pixels.Itt compresses 16 into 14 bytes.
+*/
+
+static
+void unpack14 (const unsigned char b[14], unsigned short s[16])
+{
+ //
+ // Unpack a 14-byte block into 4 by 4 16-bit pixels.
+ //
+ unsigned short shift,bias;
+ #if defined (DEBUG)
+ assert (b[2] != 0xfc);
+ #endif
+ s[ 0] = (b[0] << 8) | b[1];
+ shift = (b[ 2] >> 2);
+ bias = (0x20 << shift);
+ s[ 4] = s[ 0] + ((((b[ 2] << 4) | (b[ 3] >> 4)) & 0x3f) << shift) - bias;
+ s[ 8] = s[ 4] + ((((b[ 3] << 2) | (b[ 4] >> 6)) & 0x3f) << shift) - bias;
+ s[12] = s[ 8] + ((b[ 4] & 0x3f) << shift) - bias;
+ s[ 1] = s[ 0] + ((b[ 5] >> 2) << shift) - bias;
+ s[ 5] = s[ 4] + ((((b[ 5] << 4) | (b[ 6] >> 4)) & 0x3f) << shift) - bias;
+ s[ 9] = s[ 8] + ((((b[ 6] << 2) | (b[ 7] >> 6)) & 0x3f) << shift) - bias;
+ s[13] = s[12] + ((b[ 7] & 0x3f) << shift) - bias;
+ s[ 2] = s[ 1] + ((b[ 8] >> 2) << shift) - bias;
+ s[ 6] = s[ 5] + ((((b[ 8] << 4) | (b[ 9] >> 4)) & 0x3f) << shift) - bias;
+ s[10] = s[ 9] + ((((b[ 9] << 2) | (b[10] >> 6)) & 0x3f) << shift) - bias;
+ s[14] = s[13] + ((b[10] & 0x3f) << shift) - bias;
+ s[ 3] = s[ 2] + ((b[11] >> 2) << shift) - bias;
+ s[ 7] = s[ 6] + ((((b[11] << 4) | (b[12] >> 4)) & 0x3f) << shift) - bias;
+ s[11] = s[10] + ((((b[12] << 2) | (b[13] >> 6)) & 0x3f) << shift) - bias;
+ s[15] = s[14] + ((b[13] & 0x3f) << shift) - bias;
+ for (int i = 0; i < 16; ++i) {
+ if (s[i] & 0x8000)
+ s[i] &= 0x7fff;
+ else
+ s[i] = ~s[i];
+ }
+}
+
+
+
+static void unpack3 (const unsigned char b[3], unsigned short s[16])
+{
+ //
+ // Unpack a 3-byte block into 4 by 4 identical 16-bit pixels.
+ //
+ #if defined (DEBUG)
+ assert (b[2] == 0xfc);
+ #endif
+ s[0] = (b[0] << 8) | b[1];
+ if (s[0] & 0x8000)
+ s[0] &= 0x7fff;
+ else
+ s[0] = ~s[0];
+ for (int i = 1; i < 16; ++i)
+ s[i] = s[0];
+}
+
+
+
+static int b44_uncompress(EXRContext *s, const uint8_t *src,int compressed_size, int uncompressed_size,
+EXRThreadData *td)
+{
+ unsigned long dest_len = uncompressed_size;
+ uint8_t *out;
+ int i, j;
+ //int c;
+ uint16_t *ptr;
+ uint16_t *tmp = (uint16_t *)td->tmp;
+ out = td->uncompressed_data;
+ if (uncompress(td->tmp, &dest_len, src, compressed_size) != Z_OK ||
+ dest_len != uncompressed_size)
+ return AVERROR_INVALIDDATA;
+ for (i = 0; i < s->nb_channels; i++) {
+ EXRChannel *channel = &s->channels[i];
+ int size = channel->pixel_type;
+ const char *inPtr=src;
+ int inSize = compressed_size;
+ ptr = tmp;
+ if (channel->pixel_type != EXR_HALF) {
+ //
+ // UINT or FLOAT channel.
+ //
+ int n = s->xdelta * s->ydelta * size * sizeof (unsigned short);
+ memcpy (ptr, inPtr, n);
+ inPtr += n;
+ inSize -= n;
+ continue;
+ } else {
+ //
+ //EXR_HALF Channel
+ for (int y=0; y < s->ydelta; y +=4 ) {
+ unsigned short *row0 = ptr + y * s->xdelta;
+ unsigned short *row1 = row0 + s->xdelta;
+ unsigned short *row2 = row1 + s->xdelta;
+ unsigned short *row3 = row2 + s->xdelta;
+ for (int x = 0; x < s->xdelta; x += 4) {
+ unsigned short stmp[16];
+ if (((const unsigned char *)inPtr)[2] == 0xfc) {
+ unpack3 ((const unsigned char *)inPtr, stmp);
+ inPtr += 3;
+ inSize -= 3;
+ } else {
+ unpack14 ((const unsigned char *)inPtr, stmp);
+ inPtr += 14;
+ inSize -= 14;
+ }
+ int num = (x + 3 < s->xdelta)? 4 * sizeof (unsigned short) : (s->xdelta - x) * sizeof (unsigned short);
+ if (y + 3 < s->ydelta) {
+ memcpy (row0, &stmp[ 0], num);
+ memcpy (row1, &stmp[ 4], num);
+ memcpy (row2, &stmp[ 8], num);
+ memcpy (row3, &stmp[12], num);
+ } else {
+ memcpy (row0, &stmp[ 0], num);
+ if (y + 1 < s->ydelta)
+ memcpy (row1, &stmp[ 4], num);
+ if (y + 2 < s->ydelta)
+ memcpy (row2, &stmp[ 8], num);
+ }
+ row0 += 4;
+ row1 += 4;
+ row2 += 4;
+ row3 += 4;
+ }
+ }
+ }
+ }
+ for (i = 0; i < s->ysize; i++) {
+ for (j = 0; j < s->nb_channels; j++) {
+ uint16_t *in = tmp + j * s->xdelta * s->ysize + i * s->xdelta;
+ memcpy(out, in, s->xdelta * 2);
+ out += s->xdelta * 2;
+ }
+ }
+ return 0;
+}
+
+
static int pxr24_uncompress(EXRContext *s, const uint8_t *src,
int compressed_size, int uncompressed_size,
EXRThreadData *td)
@@ -888,6 +1045,8 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
break;
case EXR_RLE:
ret = rle_uncompress(src, data_size, uncompressed_size, td);
+ case EXR_B44:
+ ret = b44_uncompress(s, src, data_size, uncompressed_size, td);
}
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "decode_block() failed.\n");
@@ -1282,6 +1441,7 @@ static int decode_frame(AVCodecContext *avctx, void *data,
s->scan_lines_per_block = 16;
break;
case EXR_PIZ:
+ case EXR_B44:
s->scan_lines_per_block = 32;
break;
default:
More information about the ffmpeg-devel
mailing list