EXRTileAttribute tile_attr; /* header data attribute of tile */
int is_tile; /* 0 if scanline, 1 if tile */
+ int is_luma;/* 1 if there is an Y plane */
+
GetByteContext gb;
const uint8_t *buf;
int buf_size;
static int b44_uncompress(EXRContext *s, const uint8_t *src, int compressed_size,
int uncompressed_size, EXRThreadData *td) {
const int8_t *sr = src;
- int stayToUncompress = compressed_size;
- int nbB44BlockW, nbB44BlockH;
- int indexHgX, indexHgY, indexOut, indexTmp;
- uint16_t tmpBuffer[16]; /* B44 use 4x4 half float pixel */
+ int stay_to_uncompress = compressed_size;
+ int nb_b44_block_w, nb_b44_block_h;
+ int index_tl_x, index_tl_y, index_out, index_tmp;
+ uint16_t tmp_buffer[16]; /* B44 use 4x4 half float pixel */
int c, iY, iX, y, x;
int target_channel_offset = 0;
/* calc B44 block count */
- nbB44BlockW = td->xsize / 4;
+ nb_b44_block_w = td->xsize / 4;
if ((td->xsize % 4) != 0)
- nbB44BlockW++;
+ nb_b44_block_w++;
- nbB44BlockH = td->ysize / 4;
+ nb_b44_block_h = td->ysize / 4;
if ((td->ysize % 4) != 0)
- nbB44BlockH++;
+ nb_b44_block_h++;
for (c = 0; c < s->nb_channels; c++) {
if (s->channels[c].pixel_type == EXR_HALF) {/* B44 only compress half float data */
- for (iY = 0; iY < nbB44BlockH; iY++) {
- for (iX = 0; iX < nbB44BlockW; iX++) {/* For each B44 block */
- if (stayToUncompress < 3) {
- av_log(s, AV_LOG_ERROR, "Not enough data for B44A block: %d", stayToUncompress);
+ for (iY = 0; iY < nb_b44_block_h; iY++) {
+ for (iX = 0; iX < nb_b44_block_w; iX++) {/* For each B44 block */
+ if (stay_to_uncompress < 3) {
+ av_log(s, AV_LOG_ERROR, "Not enough data for B44A block: %d", stay_to_uncompress);
return AVERROR_INVALIDDATA;
}
- if (src[compressed_size - stayToUncompress + 2] == 0xfc) { /* B44A block */
- unpack_3(sr, tmpBuffer);
+ if (src[compressed_size - stay_to_uncompress + 2] == 0xfc) { /* B44A block */
+ unpack_3(sr, tmp_buffer);
sr += 3;
- stayToUncompress -= 3;
+ stay_to_uncompress -= 3;
} else {/* B44 Block */
- if (stayToUncompress < 14) {
- av_log(s, AV_LOG_ERROR, "Not enough data for B44 block: %d", stayToUncompress);
+ if (stay_to_uncompress < 14) {
+ av_log(s, AV_LOG_ERROR, "Not enough data for B44 block: %d", stay_to_uncompress);
return AVERROR_INVALIDDATA;
}
- unpack_14(sr, tmpBuffer);
+ unpack_14(sr, tmp_buffer);
sr += 14;
- stayToUncompress -= 14;
+ stay_to_uncompress -= 14;
}
/* copy data to uncompress buffer (B44 block can exceed target resolution)*/
- indexHgX = iX * 4;
- indexHgY = iY * 4;
-
- for (y = indexHgY; y < FFMIN(indexHgY + 4, td->ysize); y++) {
- for (x = indexHgX; x < FFMIN(indexHgX + 4, td->xsize); x++) {
- indexOut = target_channel_offset * td->xsize + y * td->channel_line_size + 2 * x;
- indexTmp = (y-indexHgY) * 4 + (x-indexHgX);
- td->uncompressed_data[indexOut] = tmpBuffer[indexTmp] & 0xff;
- td->uncompressed_data[indexOut + 1] = tmpBuffer[indexTmp] >> 8;
+ index_tl_x = iX * 4;
+ index_tl_y = iY * 4;
+
+ for (y = index_tl_y; y < FFMIN(index_tl_y + 4, td->ysize); y++) {
+ for (x = index_tl_x; x < FFMIN(index_tl_x + 4, td->xsize); x++) {
+ index_out = target_channel_offset * td->xsize + y * td->channel_line_size + 2 * x;
+ index_tmp = (y-index_tl_y) * 4 + (x-index_tl_x);
+ td->uncompressed_data[index_out] = tmp_buffer[index_tmp] & 0xff;
+ td->uncompressed_data[index_out + 1] = tmp_buffer[index_tmp] >> 8;
}
}
}
}
target_channel_offset += 2;
} else {/* Float or UINT 32 channel */
- if (stayToUncompress < td->ysize * td->xsize * 4) {
- av_log(s, AV_LOG_ERROR, "Not enough data for uncompress channel: %d", stayToUncompress);
+ if (stay_to_uncompress < td->ysize * td->xsize * 4) {
+ av_log(s, AV_LOG_ERROR, "Not enough data for uncompress channel: %d", stay_to_uncompress);
return AVERROR_INVALIDDATA;
}
for (y = 0; y < td->ysize; y++) {
- indexOut = target_channel_offset * td->xsize + y * td->channel_line_size;
- memcpy(&td->uncompressed_data[indexOut], sr, td->xsize * 4);
+ index_out = target_channel_offset * td->xsize + y * td->channel_line_size;
+ memcpy(&td->uncompressed_data[index_out], sr, td->xsize * 4);
sr += td->xsize * 4;
}
target_channel_offset += 4;
- stayToUncompress -= td->ysize * td->xsize * 4;
+ stay_to_uncompress -= td->ysize * td->xsize * 4;
}
}
int axmax = (avctx->width - (s->xmax + 1)) * 2 * s->desc->nb_components; /* nb pixel to add at the right of the datawindow */
int bxmin = s->xmin * 2 * s->desc->nb_components; /* nb pixel to add at the left of the datawindow */
int i, x, buf_size = s->buf_size;
+ int c, rgb_channel_count;
float one_gamma = 1.0f / s->gamma;
avpriv_trc_function trc_func = avpriv_get_trc_function_from_trc(s->apply_trc_type);
int ret;
src = td->uncompressed_data;
}
- channel_buffer[0] = src + td->xsize * s->channel_offsets[0];
- channel_buffer[1] = src + td->xsize * s->channel_offsets[1];
- channel_buffer[2] = src + td->xsize * s->channel_offsets[2];
+ if (!s->is_luma) {
+ channel_buffer[0] = src + td->xsize * s->channel_offsets[0];
+ channel_buffer[1] = src + td->xsize * s->channel_offsets[1];
+ channel_buffer[2] = src + td->xsize * s->channel_offsets[2];
+ rgb_channel_count = 3;
+ } else { /* put y data in the first channel_buffer */
+ channel_buffer[0] = src + td->xsize * s->channel_offsets[1];
+ rgb_channel_count = 1;
+ }
if (s->channel_offsets[3] >= 0)
channel_buffer[3] = src + td->xsize * s->channel_offsets[3];
for (i = 0;
i < td->ysize; i++, ptr += p->linesize[0]) {
- const uint8_t *r, *g, *b, *a;
+ const uint8_t * a;
+ const uint8_t *rgb[3];
+
+ for (c = 0; c < rgb_channel_count; c++){
+ rgb[c] = channel_buffer[c];
+ }
- r = channel_buffer[0];
- g = channel_buffer[1];
- b = channel_buffer[2];
if (channel_buffer[3])
a = channel_buffer[3];
if (trc_func) {
for (x = 0; x < td->xsize; x++) {
union av_intfloat32 t;
- t.i = bytestream_get_le32(&r);
- t.f = trc_func(t.f);
- *ptr_x++ = exr_flt2uint(t.i);
- t.i = bytestream_get_le32(&g);
- t.f = trc_func(t.f);
- *ptr_x++ = exr_flt2uint(t.i);
-
- t.i = bytestream_get_le32(&b);
- t.f = trc_func(t.f);
- *ptr_x++ = exr_flt2uint(t.i);
+ for (c = 0; c < rgb_channel_count; c++) {
+ t.i = bytestream_get_le32(&rgb[c]);
+ t.f = trc_func(t.f);
+ *ptr_x++ = exr_flt2uint(t.i);
+ }
if (channel_buffer[3])
*ptr_x++ = exr_flt2uint(bytestream_get_le32(&a));
}
} else {
for (x = 0; x < td->xsize; x++) {
union av_intfloat32 t;
- t.i = bytestream_get_le32(&r);
- if (t.f > 0.0f) /* avoid negative values */
- t.f = powf(t.f, one_gamma);
- *ptr_x++ = exr_flt2uint(t.i);
-
- t.i = bytestream_get_le32(&g);
- if (t.f > 0.0f)
- t.f = powf(t.f, one_gamma);
- *ptr_x++ = exr_flt2uint(t.i);
-
- t.i = bytestream_get_le32(&b);
- if (t.f > 0.0f)
- t.f = powf(t.f, one_gamma);
- *ptr_x++ = exr_flt2uint(t.i);
+ int c;
+
+ for (c = 0; c < rgb_channel_count; c++) {
+ t.i = bytestream_get_le32(&rgb[c]);
+ if (t.f > 0.0f) /* avoid negative values */
+ t.f = powf(t.f, one_gamma);
+ *ptr_x++ = exr_flt2uint(t.i);
+ }
+
if (channel_buffer[3])
*ptr_x++ = exr_flt2uint(bytestream_get_le32(&a));
}
} else {
// 16-bit
for (x = 0; x < td->xsize; x++) {
- *ptr_x++ = s->gamma_table[bytestream_get_le16(&r)];
- *ptr_x++ = s->gamma_table[bytestream_get_le16(&g)];
- *ptr_x++ = s->gamma_table[bytestream_get_le16(&b)];
+ int c;
+ for (c = 0; c < rgb_channel_count; c++) {
+ *ptr_x++ = s->gamma_table[bytestream_get_le16(&rgb[c])];
+ }
+
if (channel_buffer[3])
*ptr_x++ = exr_halflt2uint(bytestream_get_le16(&a));
}
s->tile_attr.xSize = -1;
s->tile_attr.ySize = -1;
s->is_tile = 0;
+ s->is_luma = 0;
if (bytestream2_get_bytes_left(&s->gb) < 10) {
av_log(s->avctx, AV_LOG_ERROR, "Header too short to parse.\n");
if (layer_match) { /* only search channel if the layer match is valid */
if (!strcmp(ch_gb.buffer, "R") ||
!strcmp(ch_gb.buffer, "X") ||
- !strcmp(ch_gb.buffer, "U"))
+ !strcmp(ch_gb.buffer, "U")) {
channel_index = 0;
- else if (!strcmp(ch_gb.buffer, "G") ||
- !strcmp(ch_gb.buffer, "Y") ||
- !strcmp(ch_gb.buffer, "V"))
+ s->is_luma = 0;
+ } else if (!strcmp(ch_gb.buffer, "G") ||
+ !strcmp(ch_gb.buffer, "V")) {
+ channel_index = 1;
+ s->is_luma = 0;
+ } else if (!strcmp(ch_gb.buffer, "Y")) {
channel_index = 1;
- else if (!strcmp(ch_gb.buffer, "B") ||
- !strcmp(ch_gb.buffer, "Z") ||
- !strcmp(ch_gb.buffer, "W"))
- channel_index = 2;
- else if (!strcmp(ch_gb.buffer, "A"))
+ s->is_luma = 1;
+ } else if (!strcmp(ch_gb.buffer, "B") ||
+ !strcmp(ch_gb.buffer, "Z") ||
+ !strcmp(ch_gb.buffer, "W")){
+ channel_index = 2;
+ s->is_luma = 0;
+ } else if (!strcmp(ch_gb.buffer, "A")) {
channel_index = 3;
- else
+ } else {
av_log(s->avctx, AV_LOG_WARNING,
"Unsupported channel %.256s.\n", ch_gb.buffer);
+ }
}
/* skip until you get a 0 */
bytestream2_skip(&ch_gb, 4);
xsub = bytestream2_get_le32(&ch_gb);
ysub = bytestream2_get_le32(&ch_gb);
+
if (xsub != 1 || ysub != 1) {
avpriv_report_missing_feature(s->avctx,
"Subsampling %dx%d",
/* Check if all channels are set with an offset or if the channels
* are causing an overflow */
- if (FFMIN3(s->channel_offsets[0],
- s->channel_offsets[1],
- s->channel_offsets[2]) < 0) {
- if (s->channel_offsets[0] < 0)
- av_log(s->avctx, AV_LOG_ERROR, "Missing red channel.\n");
- if (s->channel_offsets[1] < 0)
- av_log(s->avctx, AV_LOG_ERROR, "Missing green channel.\n");
- if (s->channel_offsets[2] < 0)
- av_log(s->avctx, AV_LOG_ERROR, "Missing blue channel.\n");
- return AVERROR_INVALIDDATA;
+ if (!s->is_luma){/* if we expected to have at least 3 channels */
+ if (FFMIN3(s->channel_offsets[0],
+ s->channel_offsets[1],
+ s->channel_offsets[2]) < 0) {
+ if (s->channel_offsets[0] < 0)
+ av_log(s->avctx, AV_LOG_ERROR, "Missing red channel.\n");
+ if (s->channel_offsets[1] < 0)
+ av_log(s->avctx, AV_LOG_ERROR, "Missing green channel.\n");
+ if (s->channel_offsets[2] < 0)
+ av_log(s->avctx, AV_LOG_ERROR, "Missing blue channel.\n");
+ return AVERROR_INVALIDDATA;
+ }
}
// skip one last byte and update main gb
switch (s->pixel_type) {
case EXR_FLOAT:
case EXR_HALF:
- if (s->channel_offsets[3] >= 0)
- avctx->pix_fmt = AV_PIX_FMT_RGBA64;
- else
- avctx->pix_fmt = AV_PIX_FMT_RGB48;
+ if (s->channel_offsets[3] >= 0) {
+ if (!s->is_luma) {
+ avctx->pix_fmt = AV_PIX_FMT_RGBA64;
+ } else {
+ avctx->pix_fmt = AV_PIX_FMT_YA16;
+ }
+ } else {
+ if (!s->is_luma) {
+ avctx->pix_fmt = AV_PIX_FMT_RGB48;
+ } else {
+ avctx->pix_fmt = AV_PIX_FMT_GRAY16;
+ }
+ }
break;
case EXR_UINT:
avpriv_request_sample(avctx, "32-bit unsigned int");