summaryrefslogtreecommitdiff
path: root/libavcodec/pnmdec.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2022-07-01 10:06:15 +0200
committerPaul B Mahol <onemda@gmail.com>2022-07-03 15:16:31 +0200
commitff1450e449f848ad4b37b3cf448315ba4581364e (patch)
tree4c6e245afa51c3ec58bb0865ed27f2940acf4f4a /libavcodec/pnmdec.c
parent33fe3b73c2d4dec674509de5dc48698895f0806b (diff)
avcodec: add PHM decoder and encoder
Diffstat (limited to 'libavcodec/pnmdec.c')
-rw-r--r--libavcodec/pnmdec.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/libavcodec/pnmdec.c b/libavcodec/pnmdec.c
index f2d9b7e4b6..bb2ce53496 100644
--- a/libavcodec/pnmdec.c
+++ b/libavcodec/pnmdec.c
@@ -26,6 +26,7 @@
#include "internal.h"
#include "put_bits.h"
#include "pnm.h"
+#include "half2float.h"
static void samplecpy(uint8_t *dst, const uint8_t *src, int n, int maxval)
{
@@ -258,6 +259,7 @@ static int pnm_decode_frame(AVCodecContext *avctx, AVFrame *p,
}
break;
case AV_PIX_FMT_GBRPF32:
+ if (!s->half) {
if (avctx->width * avctx->height * 12 > s->bytestream_end - s->bytestream)
return AVERROR_INVALIDDATA;
scale = 1.f / s->scale;
@@ -298,8 +300,68 @@ static int pnm_decode_frame(AVCodecContext *avctx, AVFrame *p,
b += p->linesize[1] / 4;
}
}
+ } else {
+ if (avctx->width * avctx->height * 6 > s->bytestream_end - s->bytestream)
+ return AVERROR_INVALIDDATA;
+ scale = 1.f / s->scale;
+ if (s->endian) {
+ float *r, *g, *b;
+
+ r = (float *)p->data[2];
+ g = (float *)p->data[0];
+ b = (float *)p->data[1];
+ for (int i = 0; i < avctx->height; i++) {
+ for (int j = 0; j < avctx->width; j++) {
+ r[j] = av_int2float(half2float(AV_RL16(s->bytestream+0),
+ s->mantissatable,
+ s->exponenttable,
+ s->offsettable)) * scale;
+ g[j] = av_int2float(half2float(AV_RL16(s->bytestream+2),
+ s->mantissatable,
+ s->exponenttable,
+ s->offsettable)) * scale;
+ b[j] = av_int2float(half2float(AV_RL16(s->bytestream+4),
+ s->mantissatable,
+ s->exponenttable,
+ s->offsettable)) * scale;
+ s->bytestream += 6;
+ }
+
+ r += p->linesize[2] / 4;
+ g += p->linesize[0] / 4;
+ b += p->linesize[1] / 4;
+ }
+ } else {
+ float *r, *g, *b;
+
+ r = (float *)p->data[2];
+ g = (float *)p->data[0];
+ b = (float *)p->data[1];
+ for (int i = 0; i < avctx->height; i++) {
+ for (int j = 0; j < avctx->width; j++) {
+ r[j] = av_int2float(half2float(AV_RB16(s->bytestream+0),
+ s->mantissatable,
+ s->exponenttable,
+ s->offsettable)) * scale;
+ g[j] = av_int2float(half2float(AV_RB16(s->bytestream+2),
+ s->mantissatable,
+ s->exponenttable,
+ s->offsettable)) * scale;
+ b[j] = av_int2float(half2float(AV_RB16(s->bytestream+4),
+ s->mantissatable,
+ s->exponenttable,
+ s->offsettable)) * scale;
+ s->bytestream += 6;
+ }
+
+ r += p->linesize[2] / 4;
+ g += p->linesize[0] / 4;
+ b += p->linesize[1] / 4;
+ }
+ } }
break;
case AV_PIX_FMT_GRAYF32:
+ if (!s->half) {
if (avctx->width * avctx->height * 4 > s->bytestream_end - s->bytestream)
return AVERROR_INVALIDDATA;
scale = 1.f / s->scale;
@@ -322,6 +384,36 @@ static int pnm_decode_frame(AVCodecContext *avctx, AVFrame *p,
g += p->linesize[0] / 4;
}
}
+ } else {
+ if (avctx->width * avctx->height * 2 > s->bytestream_end - s->bytestream)
+ return AVERROR_INVALIDDATA;
+ scale = 1.f / s->scale;
+ if (s->endian) {
+ float *g = (float *)p->data[0];
+ for (int i = 0; i < avctx->height; i++) {
+ for (int j = 0; j < avctx->width; j++) {
+ g[j] = av_int2float(half2float(AV_RL16(s->bytestream),
+ s->mantissatable,
+ s->exponenttable,
+ s->offsettable)) * scale;
+ s->bytestream += 2;
+ }
+ g += p->linesize[0] / 4;
+ }
+ } else {
+ float *g = (float *)p->data[0];
+ for (int i = 0; i < avctx->height; i++) {
+ for (int j = 0; j < avctx->width; j++) {
+ g[j] = av_int2float(half2float(AV_RB16(s->bytestream),
+ s->mantissatable,
+ s->exponenttable,
+ s->offsettable)) * scale;
+ s->bytestream += 2;
+ }
+ g += p->linesize[0] / 4;
+ }
+ }
+ }
break;
}
*got_frame = 1;
@@ -401,3 +493,25 @@ const FFCodec ff_pfm_decoder = {
FF_CODEC_DECODE_CB(pnm_decode_frame),
};
#endif
+
+#if CONFIG_PHM_DECODER
+static av_cold int phm_dec_init(AVCodecContext *avctx)
+{
+ PNMContext *s = avctx->priv_data;
+
+ half2float_table(s->mantissatable, s->exponenttable, s->offsettable);
+
+ return 0;
+}
+
+const FFCodec ff_phm_decoder = {
+ .p.name = "phm",
+ .p.long_name = NULL_IF_CONFIG_SMALL("PHM (Portable HalfFloatMap) image"),
+ .p.type = AVMEDIA_TYPE_VIDEO,
+ .p.id = AV_CODEC_ID_PHM,
+ .p.capabilities = AV_CODEC_CAP_DR1,
+ .priv_data_size = sizeof(PNMContext),
+ .init = phm_dec_init,
+ FF_CODEC_DECODE_CB(pnm_decode_frame),
+};
+#endif