[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