[FFmpeg-devel] [PATCH 2/2] avcodec/ildadec: ILDA Image Data Transfer Format decoder

Peter Ross pross at xvid.org
Mon Aug 22 13:00:10 EEST 2022


Signed-off-by: Peter Ross <pross at xvid.org>
---
 libavcodec/Makefile     |   1 +
 libavcodec/allcodecs.c  |   1 +
 libavcodec/codec_desc.c |   7 +
 libavcodec/codec_id.h   |   1 +
 libavcodec/ildadec.c    | 297 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 307 insertions(+)
 create mode 100644 libavcodec/ildadec.c

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index cb80f73d99..943144ef7d 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -435,6 +435,7 @@ OBJS-$(CONFIG_IDCIN_DECODER)           += idcinvideo.o
 OBJS-$(CONFIG_IDF_DECODER)             += bintext.o cga_data.o
 OBJS-$(CONFIG_IFF_ILBM_DECODER)        += iff.o
 OBJS-$(CONFIG_ILBC_DECODER)            += ilbcdec.o
+OBJS-$(CONFIG_ILDA_DECODER)            += ildadec.o
 OBJS-$(CONFIG_IMC_DECODER)             += imc.o
 OBJS-$(CONFIG_IMM4_DECODER)            += imm4.o
 OBJS-$(CONFIG_IMM5_DECODER)            += imm5.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 6939a4e25f..42a891bf77 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -171,6 +171,7 @@ extern const FFCodec ff_huffyuv_decoder;
 extern const FFCodec ff_hymt_decoder;
 extern const FFCodec ff_idcin_decoder;
 extern const FFCodec ff_iff_ilbm_decoder;
+extern const FFCodec ff_ilda_decoder;
 extern const FFCodec ff_imm4_decoder;
 extern const FFCodec ff_imm5_decoder;
 extern const FFCodec ff_indeo2_decoder;
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 06dfe55d0f..177a25a5ce 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1909,6 +1909,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("WBMP (Wireless Application Protocol Bitmap) image"),
         .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
     },
+    {
+        .id        = AV_CODEC_ID_ILDA,
+        .type      = AVMEDIA_TYPE_VIDEO,
+        .name      = "ilda",
+        .long_name = NULL_IF_CONFIG_SMALL("ILDA Image Data Transfer Format"),
+        .props     = AV_CODEC_PROP_LOSSY,
+    },
 
     /* various PCM "codecs" */
     {
diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h
index 2247bc0309..0152cc57a8 100644
--- a/libavcodec/codec_id.h
+++ b/libavcodec/codec_id.h
@@ -318,6 +318,7 @@ enum AVCodecID {
     AV_CODEC_ID_PHM,
     AV_CODEC_ID_RADIANCE_HDR,
     AV_CODEC_ID_WBMP,
+    AV_CODEC_ID_ILDA,
 
     /* various PCM "codecs" */
     AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
diff --git a/libavcodec/ildadec.c b/libavcodec/ildadec.c
new file mode 100644
index 0000000000..b5810c911d
--- /dev/null
+++ b/libavcodec/ildadec.c
@@ -0,0 +1,297 @@
+/*
+ * ILDA Image Data Transfer Format decoder
+ * Copyright (C) 2020 Peter Ross <pross at xvid.org>
+ *
+ * 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
+ */
+
+/**
+ * @file
+ * ILDA Image Data Transfer Format decoder
+ */
+
+#include "libavutil/attributes.h"
+#include "libavutil/common.h"
+#include "libavutil/frame.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/internal.h"
+#include "libavutil/intreadwrite.h"
+#include "avcodec.h"
+#include "codec_internal.h"
+#include "internal.h"
+#include "mathops.h"
+
+static const uint8_t default_palette[64][3]={
+    {255,0,0},
+    {255,16,0},
+    {255,32,0},
+    {255,48,0},
+    {255,64,0},
+    {255,80,0},
+    {255,96,0},
+    {255,112,0},
+    {255,128,0},
+    {255,144,0},
+    {255,160,0},
+    {255,176,0},
+    {255,192,0},
+    {255,208,0},
+    {255,224,0},
+    {255,240,0},
+    {255,255,0},
+    {224,255,0},
+    {192,255,0},
+    {160,255,0},
+    {128,255,0},
+    {96,255,0},
+    {64,255,0},
+    {32,255,0},
+    {0,255,0},
+    {0,255,36},
+    {0,255,73},
+    {0,255,109},
+    {0,255,146},
+    {0,255,182},
+    {0,255,219},
+    {0,255,255},
+    {0,227,255},
+    {0,198,255},
+    {0,170,255},
+    {0,142,255},
+    {0,113,255},
+    {0,85,255},
+    {0,56,255},
+    {0,28,255},
+    {0,0,255},
+    {32,0,255},
+    {64,0,255},
+    {96,0,255},
+    {128,0,255},
+    {160,0,255},
+    {192,0,255},
+    {224,0,255},
+    {255,0,255},
+    {255,32,255},
+    {255,64,255},
+    {255,96,255},
+    {255,128,255},
+    {255,160,255},
+    {255,192,255},
+    {255,224,255},
+    {255,255,255},
+    {255,224,224},
+    {255,192,192},
+    {255,160,160},
+    {255,128,128},
+    {255,96,96},
+    {255,64,64},
+    {255,32,32},
+};
+
+typedef struct {
+    AVFrame * frame;
+    uint8_t palette[256][3];
+} ILDAContext;
+
+static av_cold int decode_init(AVCodecContext *avctx)
+{
+    ILDAContext *s = avctx->priv_data;
+
+    if (!avctx->width || !avctx->height) {
+        int ret = ff_set_dimensions(avctx, 1024, 1024);
+        if (ret < 0)
+            return ret;
+    }
+
+    avctx->pix_fmt = AV_PIX_FMT_RGB24;
+
+    s->frame = av_frame_alloc();
+    if (!s->frame)
+        return AVERROR(ENOMEM);
+
+    memcpy(s->palette, default_palette, sizeof(default_palette));
+    memset(s->palette + FF_ARRAY_ELEMS(default_palette), 0xFF, sizeof(s->palette) - sizeof(default_palette));
+    return 0;
+};
+
+static void draw_point(uint8_t *const pixels, int linesize, int width, int height,
+                      int x, int y,
+                      const uint8_t *const rgbcolor)
+{
+    for (int j = FFMAX(y - 1, 0); j < FFMIN(y + 1, height); j++)
+        for (int i = FFMAX(x - 1, 0); i < FFMIN(x + 1, width); i++) {
+            pixels[j * linesize + i * 3 + 0] = rgbcolor[0];
+            pixels[j * linesize + i * 3 + 1] = rgbcolor[1];
+            pixels[j * linesize + i * 3 + 2] = rgbcolor[2];
+         }
+
+}
+
+static void draw_line(uint8_t *const pixels, int linesize,
+                      int x0, int y0, int x1, int y1, const uint8_t *const rgbcolor)
+{
+    int dx  = FFABS(x1 - x0), sx = x0 < x1 ? 1 : -1;
+    int dy  = FFABS(y1 - y0), sy = y0 < y1 ? 1 : -1;
+    int err = (dx > dy ? dx : -dy) / 2, e2;
+
+    for (;;) {
+        pixels[y0 * linesize + x0 * 3 + 0] = rgbcolor[0];
+        pixels[y0 * linesize + x0 * 3 + 1] = rgbcolor[1];
+        pixels[y0 * linesize + x0 * 3 + 2] = rgbcolor[2];
+
+        if (x0 == x1 && y0 == y1)
+            break;
+
+        e2 = err;
+
+        if (e2 >-dx) {
+            err -= dy;
+            x0 += sx;
+        }
+
+        if (e2 < dy) {
+            err += dx;
+            y0 += sy;
+        }
+    }
+}
+
+static int decode_indexed(AVCodecContext *avctx, const uint8_t *buf,
+                          const uint8_t *buf_end, int nb_entries, int zaxis, int truecolor)
+{
+    ILDAContext *s = avctx->priv_data;
+    int ret, x0, y0;
+    uint8_t * dst;
+
+    ret = ff_reget_buffer(avctx, s->frame, 0);
+    if (ret < 0)
+        return ret;
+
+    dst = s->frame->data[0];
+    for (int i = 0; i < avctx->height; i++) {
+        memset(dst, 0, avctx->width * 3);
+        dst += s->frame->linesize[0];
+    }
+
+    if (nb_entries < 2 || buf_end - buf < 6 + zaxis + truecolor)
+        return 0;
+
+#define coord(x)  sign_extend(AV_RB16(buf + x), 16)
+#define get_x     ((32768 + coord(0)) * avctx->width) / 65536
+#define get_y     (-(coord(2) - 32767) * avctx->height) / 65536
+
+    x0 = get_x;
+    y0 = get_y;
+    buf += 6 + zaxis + truecolor;
+
+    for (int i = 1; i < nb_entries && buf_end - buf >= 6 + zaxis + truecolor; i++) {
+        int x1 = get_x;
+        int y1 = get_y;
+        uint8_t rgb[3];
+        uint8_t * color;
+        if (truecolor) {
+            rgb[0] = buf[7 + zaxis];
+            rgb[1] = buf[6 + zaxis];
+            rgb[2] = buf[5 + zaxis];
+            color = rgb;
+        } else
+            color = s->palette[buf[5 + zaxis]];
+
+        if (!(buf[4 + zaxis] & 0x40)) {
+            if (x0 != x1 || y0 != y1)
+                draw_line(s->frame->data[0], s->frame->linesize[0], x0, y0, x1, y1, color);
+            else
+                draw_point(s->frame->data[0], s->frame->linesize[0], avctx->width, avctx->height, x0, y0, color);
+        }
+
+        x0 = x1;
+        y0 = y1;
+
+        buf += 6 + zaxis + truecolor;
+    }
+    return 0;
+}
+
+static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
+                        int *got_frame, AVPacket *avpkt)
+{
+    ILDAContext *s = avctx->priv_data;
+    uint8_t *buf = avpkt->data;
+    int buf_size = avpkt->size;
+    const uint8_t *buf_end   = buf + buf_size;
+    int ret, format, nb_entries;
+
+    if (buf_size < 32)
+        return -1;
+
+    format = buf[7];
+    nb_entries = AV_RB16(buf + 24);
+
+    buf += 32;
+
+    switch (format) {
+    case 0:
+        ret = decode_indexed(avctx, buf, buf_end, nb_entries, 2, 0);
+        break;
+    case 1:
+        ret = decode_indexed(avctx, buf, buf_end, nb_entries, 0, 0);
+        break;
+    case 2:
+        memcpy(s->palette, buf, FFMIN((buf_end - buf) / 3, nb_entries) * 3);
+        return buf_size;
+    case 4:
+        ret = decode_indexed(avctx, buf, buf_end, nb_entries, 2, 2);
+        break;
+    case 5:
+        ret = decode_indexed(avctx, buf, buf_end, nb_entries, 0, 2);
+        break;
+    default:
+        avpriv_request_sample(avctx, "unsupported format %d", format);
+        return buf_size;
+    }
+
+    if (ret < 0)
+        return ret;
+
+    *got_frame = 1;
+
+    ret = av_frame_ref(rframe, s->frame);
+    if (ret < 0)
+        return ret;
+
+    return buf_size;
+}
+
+static av_cold int decode_close(AVCodecContext *avctx)
+{
+    ILDAContext *s = avctx->priv_data;
+
+    av_frame_free(&s->frame);
+    return 0;
+}
+
+const FFCodec ff_ilda_decoder = {
+    .p.name         = "anm",
+    .p.long_name    = NULL_IF_CONFIG_SMALL("ILDA Image Data Transfer Format"),
+    .p.type         = AVMEDIA_TYPE_VIDEO,
+    .p.id           = AV_CODEC_ID_ILDA,
+    .priv_data_size = sizeof(ILDAContext),
+    .init           = decode_init,
+    .close          = decode_close,
+    FF_CODEC_DECODE_CB(decode_frame),
+    .p.capabilities = AV_CODEC_CAP_DR1,
+};
-- 
2.35.1

-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20220822/43fb2ebe/attachment.sig>


More information about the ffmpeg-devel mailing list