From patchwork Fri Mar 10 19:04:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paras X-Patchwork-Id: 2871 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.50.79 with SMTP id y76csp196561vsy; Fri, 10 Mar 2017 11:11:29 -0800 (PST) X-Received: by 10.223.160.115 with SMTP id l48mr18810149wrl.24.1489173089828; Fri, 10 Mar 2017 11:11:29 -0800 (PST) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id z140si357435wmd.80.2017.03.10.11.11.29; Fri, 10 Mar 2017 11:11:29 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 72594689721; Fri, 10 Mar 2017 21:11:12 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pg0-f65.google.com (mail-pg0-f65.google.com [74.125.83.65]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 39FED6882DC for ; Fri, 10 Mar 2017 21:11:06 +0200 (EET) Received: by mail-pg0-f65.google.com with SMTP id 25so11199248pgy.3 for ; Fri, 10 Mar 2017 11:11:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=AWCxqRUv6VtDh02fFicU18kb/hKoBCYMWB3z8GmYFmU=; b=WWehOHhUeaJ8zWRSJrZnDVPfAFN90riWIGEsmY2Is6jv2g9+r97HpDsQgUxNDRapHa kbQjqtrXdDNLokVuszBrylc7rqaEGqHmelWVJ0i1aYlwAcdTleY4PV2YXWCmj0t3KfZQ rJGrXG+7ilYQmXBeERrSnldMqIeZ4PNpX+0PXrPBnANlduxWCVCQyMWnZ5n5ocIrmbLq tV93jVIoufhnJ90ANbZhro4mjBzgMeiWV7Iu+C9CAPUYDdNPXlA+KivqemlTX8UOEvSy 2iLbhYK6g+AkBgnjpa0otZeO13J5FEN+7TFx2IemOkeIL9ggYytKK1B6fE4s0raSwTPE D8Qg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=AWCxqRUv6VtDh02fFicU18kb/hKoBCYMWB3z8GmYFmU=; b=RqeqJ8gT5JPSkUw0EyW9HuF6L2Jx08TqBYgIGX/mKpyuoJR14+fB54IoCYuMal932W DiXdCNqR0/71VtcT7UQ/JI70GQERfm4pqhWHFLE+E9HkKO89869TbGP6vSnSIa9+d6fS LJWim6EaxQII2YuuGma7i5QGQyQXN5qRQDg7jm1jbFbMT/Q6bFJ/6CTuqqsJgigdtNMC uoghnEHdzQTCqI/ZcsZvYAZ/f63gq3XOF9EC9dsCvbdgcbrBDSPrPOLi5CQY/DdQcuZN AkGcIfLcbV3tHOE2ZZ3czXLiCvo9e1SDXyvRmNXvfU56+T5eNe+mk54WRaynOIiq4wlE Ea+g== X-Gm-Message-State: AMke39m8xCeS9Pyp0XG746Js5rKINQvAJM9nutNOtqL2BaqRVNw/OD0mLnpTGxjBy9abzA== X-Received: by 10.84.196.164 with SMTP id l33mr28037958pld.0.1489172666351; Fri, 10 Mar 2017 11:04:26 -0800 (PST) Received: from dhcppc9.localdomain ([124.253.1.43]) by smtp.gmail.com with ESMTPSA id p4sm20178513pgd.50.2017.03.10.11.04.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 10 Mar 2017 11:04:25 -0800 (PST) From: Paras To: ffmpeg-devel@ffmpeg.org Date: Sat, 11 Mar 2017 00:34:18 +0530 Message-Id: <1489172658-29029-1-git-send-email-paraschadha18@gmail.com> X-Mailer: git-send-email 2.4.11 Subject: [FFmpeg-devel] [PATCH] Add XPM decoder X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Paras Chadha MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Paras Chadha Signed-off-by: Paras --- Changelog | 1 + doc/general.texi | 2 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/codec_desc.c | 7 + libavcodec/version.h | 4 +- libavcodec/xpmdec.c | 409 ++++++++++++++++++++++++++++++++++++++++++++++++ libavformat/img2.c | 1 + 9 files changed, 425 insertions(+), 2 deletions(-) create mode 100644 libavcodec/xpmdec.c diff --git a/Changelog b/Changelog index 13628ca..716b6ff 100644 --- a/Changelog +++ b/Changelog @@ -26,6 +26,7 @@ version : - native Opus encoder - ScreenPressor decoder - incomplete ClearVideo decoder +- XPM decoder version 3.2: - libopenmpt demuxer diff --git a/doc/general.texi b/doc/general.texi index 30450c0..83f54b3 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -607,6 +607,8 @@ following image formats are supported: @tab WebP image format, encoding supported through external library libwebp @item XBM @tab X @tab X @tab X BitMap image format +@item XPM @tab X @tab X + @tab X PixMap image format @item XFace @tab X @tab X @tab X-Face image format @item XWD @tab X @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 65ccbad..fc5fa1f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -645,6 +645,7 @@ OBJS-$(CONFIG_XAN_WC4_DECODER) += xxan.o OBJS-$(CONFIG_XBIN_DECODER) += bintext.o cga_data.o OBJS-$(CONFIG_XBM_DECODER) += xbmdec.o OBJS-$(CONFIG_XBM_ENCODER) += xbmenc.o +OBJS-$(CONFIG_XPM_DECODER) += xpmdec.o OBJS-$(CONFIG_XFACE_DECODER) += xfacedec.o xface.o OBJS-$(CONFIG_XFACE_ENCODER) += xfaceenc.o xface.o OBJS-$(CONFIG_XL_DECODER) += xl.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 074efd4..81208b2 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -376,6 +376,7 @@ static void register_all(void) REGISTER_DECODER(XAN_WC3, xan_wc3); REGISTER_DECODER(XAN_WC4, xan_wc4); REGISTER_ENCDEC (XBM, xbm); + REGISTER_DECODER (XPM, xpm); REGISTER_ENCDEC (XFACE, xface); REGISTER_DECODER(XL, xl); REGISTER_ENCDEC (XWD, xwd); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 30ac236..a862716 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -377,6 +377,7 @@ enum AVCodecID { AV_CODEC_ID_XWD, AV_CODEC_ID_CDXL, AV_CODEC_ID_XBM, + AV_CODEC_ID_XPM, AV_CODEC_ID_ZEROCODEC, AV_CODEC_ID_MSS1, AV_CODEC_ID_MSA1, diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 06bcfc3..88cfddb 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1591,6 +1591,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { + .id = AV_CODEC_ID_XPM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "xpm", + .long_name = NULL_IF_CONFIG_SMALL("XPM (X PixMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { .id = AV_CODEC_ID_XWD, .type = AVMEDIA_TYPE_VIDEO, .name = "xwd", diff --git a/libavcodec/version.h b/libavcodec/version.h index b00e011..3ed5a71 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 57 -#define LIBAVCODEC_VERSION_MINOR 82 -#define LIBAVCODEC_VERSION_MICRO 102 +#define LIBAVCODEC_VERSION_MINOR 83 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavcodec/xpmdec.c b/libavcodec/xpmdec.c new file mode 100644 index 0000000..635f25a --- /dev/null +++ b/libavcodec/xpmdec.c @@ -0,0 +1,409 @@ +/* + * XPM image format + * + * Copyright (c) 2012 Paul B Mahol + * Copyright (c) 2016 Paras Chadha + * + * 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 + */ + +#include "libavutil/parseutils.h" +#include "libavutil/avstring.h" +#include "avcodec.h" +#include "internal.h" + +typedef struct XPMContext { + uint32_t *pixels; + int pixels_size; +} XPMDecContext; + +typedef struct ColorEntry { + const char *name; ///< a string representing the name of the color + uint8_t rgb_color[3]; ///< RGB values for the color +} ColorEntry; + +static int color_table_compare(const void *lhs, const void *rhs) +{ + return av_strcasecmp(lhs, ((const ColorEntry *)rhs)->name); +} + +static const ColorEntry color_table[] = { + { "AliceBlue", { 0xF0, 0xF8, 0xFF } }, + { "AntiqueWhite", { 0xFA, 0xEB, 0xD7 } }, + { "Aqua", { 0x00, 0xFF, 0xFF } }, + { "Aquamarine", { 0x7F, 0xFF, 0xD4 } }, + { "Azure", { 0xF0, 0xFF, 0xFF } }, + { "Beige", { 0xF5, 0xF5, 0xDC } }, + { "Bisque", { 0xFF, 0xE4, 0xC4 } }, + { "Black", { 0x00, 0x00, 0x00 } }, + { "BlanchedAlmond", { 0xFF, 0xEB, 0xCD } }, + { "Blue", { 0x00, 0x00, 0xFF } }, + { "BlueViolet", { 0x8A, 0x2B, 0xE2 } }, + { "Brown", { 0xA5, 0x2A, 0x2A } }, + { "BurlyWood", { 0xDE, 0xB8, 0x87 } }, + { "CadetBlue", { 0x5F, 0x9E, 0xA0 } }, + { "Chartreuse", { 0x7F, 0xFF, 0x00 } }, + { "Chocolate", { 0xD2, 0x69, 0x1E } }, + { "Coral", { 0xFF, 0x7F, 0x50 } }, + { "CornflowerBlue", { 0x64, 0x95, 0xED } }, + { "Cornsilk", { 0xFF, 0xF8, 0xDC } }, + { "Crimson", { 0xDC, 0x14, 0x3C } }, + { "Cyan", { 0x00, 0xFF, 0xFF } }, + { "DarkBlue", { 0x00, 0x00, 0x8B } }, + { "DarkCyan", { 0x00, 0x8B, 0x8B } }, + { "DarkGoldenRod", { 0xB8, 0x86, 0x0B } }, + { "DarkGray", { 0xA9, 0xA9, 0xA9 } }, + { "DarkGreen", { 0x00, 0x64, 0x00 } }, + { "DarkKhaki", { 0xBD, 0xB7, 0x6B } }, + { "DarkMagenta", { 0x8B, 0x00, 0x8B } }, + { "DarkOliveGreen", { 0x55, 0x6B, 0x2F } }, + { "Darkorange", { 0xFF, 0x8C, 0x00 } }, + { "DarkOrchid", { 0x99, 0x32, 0xCC } }, + { "DarkRed", { 0x8B, 0x00, 0x00 } }, + { "DarkSalmon", { 0xE9, 0x96, 0x7A } }, + { "DarkSeaGreen", { 0x8F, 0xBC, 0x8F } }, + { "DarkSlateBlue", { 0x48, 0x3D, 0x8B } }, + { "DarkSlateGray", { 0x2F, 0x4F, 0x4F } }, + { "DarkTurquoise", { 0x00, 0xCE, 0xD1 } }, + { "DarkViolet", { 0x94, 0x00, 0xD3 } }, + { "DeepPink", { 0xFF, 0x14, 0x93 } }, + { "DeepSkyBlue", { 0x00, 0xBF, 0xFF } }, + { "DimGray", { 0x69, 0x69, 0x69 } }, + { "DodgerBlue", { 0x1E, 0x90, 0xFF } }, + { "FireBrick", { 0xB2, 0x22, 0x22 } }, + { "FloralWhite", { 0xFF, 0xFA, 0xF0 } }, + { "ForestGreen", { 0x22, 0x8B, 0x22 } }, + { "Fuchsia", { 0xFF, 0x00, 0xFF } }, + { "Gainsboro", { 0xDC, 0xDC, 0xDC } }, + { "GhostWhite", { 0xF8, 0xF8, 0xFF } }, + { "Gold", { 0xFF, 0xD7, 0x00 } }, + { "GoldenRod", { 0xDA, 0xA5, 0x20 } }, + { "Gray", { 0x80, 0x80, 0x80 } }, + { "Green", { 0x00, 0x80, 0x00 } }, + { "GreenYellow", { 0xAD, 0xFF, 0x2F } }, + { "HoneyDew", { 0xF0, 0xFF, 0xF0 } }, + { "HotPink", { 0xFF, 0x69, 0xB4 } }, + { "IndianRed", { 0xCD, 0x5C, 0x5C } }, + { "Indigo", { 0x4B, 0x00, 0x82 } }, + { "Ivory", { 0xFF, 0xFF, 0xF0 } }, + { "Khaki", { 0xF0, 0xE6, 0x8C } }, + { "Lavender", { 0xE6, 0xE6, 0xFA } }, + { "LavenderBlush", { 0xFF, 0xF0, 0xF5 } }, + { "LawnGreen", { 0x7C, 0xFC, 0x00 } }, + { "LemonChiffon", { 0xFF, 0xFA, 0xCD } }, + { "LightBlue", { 0xAD, 0xD8, 0xE6 } }, + { "LightCoral", { 0xF0, 0x80, 0x80 } }, + { "LightCyan", { 0xE0, 0xFF, 0xFF } }, + { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } }, + { "LightGreen", { 0x90, 0xEE, 0x90 } }, + { "LightGrey", { 0xD3, 0xD3, 0xD3 } }, + { "LightPink", { 0xFF, 0xB6, 0xC1 } }, + { "LightSalmon", { 0xFF, 0xA0, 0x7A } }, + { "LightSeaGreen", { 0x20, 0xB2, 0xAA } }, + { "LightSkyBlue", { 0x87, 0xCE, 0xFA } }, + { "LightSlateGray", { 0x77, 0x88, 0x99 } }, + { "LightSteelBlue", { 0xB0, 0xC4, 0xDE } }, + { "LightYellow", { 0xFF, 0xFF, 0xE0 } }, + { "Lime", { 0x00, 0xFF, 0x00 } }, + { "LimeGreen", { 0x32, 0xCD, 0x32 } }, + { "Linen", { 0xFA, 0xF0, 0xE6 } }, + { "Magenta", { 0xFF, 0x00, 0xFF } }, + { "Maroon", { 0x80, 0x00, 0x00 } }, + { "MediumAquaMarine", { 0x66, 0xCD, 0xAA } }, + { "MediumBlue", { 0x00, 0x00, 0xCD } }, + { "MediumOrchid", { 0xBA, 0x55, 0xD3 } }, + { "MediumPurple", { 0x93, 0x70, 0xD8 } }, + { "MediumSeaGreen", { 0x3C, 0xB3, 0x71 } }, + { "MediumSlateBlue", { 0x7B, 0x68, 0xEE } }, + { "MediumSpringGreen", { 0x00, 0xFA, 0x9A } }, + { "MediumTurquoise", { 0x48, 0xD1, 0xCC } }, + { "MediumVioletRed", { 0xC7, 0x15, 0x85 } }, + { "MidnightBlue", { 0x19, 0x19, 0x70 } }, + { "MintCream", { 0xF5, 0xFF, 0xFA } }, + { "MistyRose", { 0xFF, 0xE4, 0xE1 } }, + { "Moccasin", { 0xFF, 0xE4, 0xB5 } }, + { "NavajoWhite", { 0xFF, 0xDE, 0xAD } }, + { "Navy", { 0x00, 0x00, 0x80 } }, + { "OldLace", { 0xFD, 0xF5, 0xE6 } }, + { "Olive", { 0x80, 0x80, 0x00 } }, + { "OliveDrab", { 0x6B, 0x8E, 0x23 } }, + { "Orange", { 0xFF, 0xA5, 0x00 } }, + { "OrangeRed", { 0xFF, 0x45, 0x00 } }, + { "Orchid", { 0xDA, 0x70, 0xD6 } }, + { "PaleGoldenRod", { 0xEE, 0xE8, 0xAA } }, + { "PaleGreen", { 0x98, 0xFB, 0x98 } }, + { "PaleTurquoise", { 0xAF, 0xEE, 0xEE } }, + { "PaleVioletRed", { 0xD8, 0x70, 0x93 } }, + { "PapayaWhip", { 0xFF, 0xEF, 0xD5 } }, + { "PeachPuff", { 0xFF, 0xDA, 0xB9 } }, + { "Peru", { 0xCD, 0x85, 0x3F } }, + { "Pink", { 0xFF, 0xC0, 0xCB } }, + { "Plum", { 0xDD, 0xA0, 0xDD } }, + { "PowderBlue", { 0xB0, 0xE0, 0xE6 } }, + { "Purple", { 0x80, 0x00, 0x80 } }, + { "Red", { 0xFF, 0x00, 0x00 } }, + { "RosyBrown", { 0xBC, 0x8F, 0x8F } }, + { "RoyalBlue", { 0x41, 0x69, 0xE1 } }, + { "SaddleBrown", { 0x8B, 0x45, 0x13 } }, + { "Salmon", { 0xFA, 0x80, 0x72 } }, + { "SandyBrown", { 0xF4, 0xA4, 0x60 } }, + { "SeaGreen", { 0x2E, 0x8B, 0x57 } }, + { "SeaShell", { 0xFF, 0xF5, 0xEE } }, + { "Sienna", { 0xA0, 0x52, 0x2D } }, + { "Silver", { 0xC0, 0xC0, 0xC0 } }, + { "SkyBlue", { 0x87, 0xCE, 0xEB } }, + { "SlateBlue", { 0x6A, 0x5A, 0xCD } }, + { "SlateGray", { 0x70, 0x80, 0x90 } }, + { "Snow", { 0xFF, 0xFA, 0xFA } }, + { "SpringGreen", { 0x00, 0xFF, 0x7F } }, + { "SteelBlue", { 0x46, 0x82, 0xB4 } }, + { "Tan", { 0xD2, 0xB4, 0x8C } }, + { "Teal", { 0x00, 0x80, 0x80 } }, + { "Thistle", { 0xD8, 0xBF, 0xD8 } }, + { "Tomato", { 0xFF, 0x63, 0x47 } }, + { "Turquoise", { 0x40, 0xE0, 0xD0 } }, + { "Violet", { 0xEE, 0x82, 0xEE } }, + { "Wheat", { 0xF5, 0xDE, 0xB3 } }, + { "White", { 0xFF, 0xFF, 0xFF } }, + { "WhiteSmoke", { 0xF5, 0xF5, 0xF5 } }, + { "Yellow", { 0xFF, 0xFF, 0x00 } }, + { "YellowGreen", { 0x9A, 0xCD, 0x32 } }, +}; + +static int convert(uint8_t x) +{ + if (x >= 'a') + x -= 87; + else if (x >= 'A') + x -= 55; + else + x -= '0'; + return x; +} + +/* +** functions same as strcspn but ignores characters in reject if they are inside a C style comment... +** @param str, reject - same as that of strcspn +** @return length till any character in reject does not occur in str +*/ +static size_t mod_strcspn(const char *str, const char *rej){ + size_t v1, v2; + const char * ptr = str; + + v1 = strcspn(str, "/"); + v2 = strcspn(str, rej); + + while(v1rgb_color[2] | + (entry->rgb_color[1] << 8) | + (entry->rgb_color[0] << 16); + } + return ret; +} + +static int ascii2index(const uint8_t *cpixel, int cpp) +{ + const uint8_t *p = cpixel; + int n = 0, m = 1, i; + + for (i = 0; i < cpp; i++) { + if (*p < ' ' || *p > '~') + return AVERROR_INVALIDDATA; + n += (*p++ - ' ') * m; + m *= 95; + } + return n; +} + +static int xpm_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + XPMDecContext *x = avctx->priv_data; + AVFrame *p=data; + const uint8_t *end, *ptr = avpkt->data; + int ncolors, cpp, ret, i, j; + int64_t size; + uint32_t *dst; + + avctx->pix_fmt = AV_PIX_FMT_BGRA; + + end = avpkt->data + avpkt->size; + if (memcmp(ptr, "/* XPM */", 9)) { + av_log(avctx, AV_LOG_ERROR, "missing signature\n"); + return AVERROR_INVALIDDATA; + } + + ptr += mod_strcspn(ptr, "\""); + if (sscanf(ptr, "\"%u %u %u %u\",", + &avctx->width, &avctx->height, &ncolors, &cpp) != 4) { + av_log(avctx, AV_LOG_ERROR, "missing image parameters\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_set_dimensions(avctx, avctx->width, avctx->height)) < 0) + return ret; + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + + if (ncolors <= 0 || cpp <= 0) { + av_log(avctx, AV_LOG_ERROR, "invalid number of colors or chars per pixel\n"); + return AVERROR_INVALIDDATA; + } + + size = 1; + j = 1; + for(i=0;ipixels, &x->pixels_size, size); + if (!x->pixels) + return AVERROR(ENOMEM); + + ptr += mod_strcspn(ptr, ",") + 1; + for (i = 0; i < ncolors; i++) { + const uint8_t *index; + int len; + + ptr += mod_strcspn(ptr, "\"") + 1; + if (ptr + cpp > end) + return AVERROR_INVALIDDATA; + index = ptr; + ptr += cpp; + + ptr = strstr(ptr, "c "); + if (ptr) + ptr += 2; + else + return AVERROR_INVALIDDATA; + + len = strcspn(ptr, "\" "); + + if ((ret = ascii2index(index, cpp)) < 0) + return ret; + + x->pixels[ret] = hexstring_to_rgba(ptr, len); + + ptr += mod_strcspn(ptr, ",") + 1; + } + + for (i = 0; i < avctx->height; i++) { + dst = (uint32_t *)(p->data[0] + i * p->linesize[0]); + ptr += mod_strcspn(ptr, "\"") + 1; + for (j = 0; j < avctx->width; j++) { + if (ptr + cpp > end) + return AVERROR_INVALIDDATA; + ret = ascii2index(ptr, cpp); + *dst++ = x->pixels[ret]; + ptr += cpp; + } + ptr += mod_strcspn(ptr, ",") + 1; + } + + p->key_frame = 1; + p->pict_type = AV_PICTURE_TYPE_I; + + *got_frame = 1; + *(AVFrame *)data = *p; + + return avpkt->size; +} + +static av_cold int xpm_decode_close(AVCodecContext *avctx) +{ + XPMDecContext *x = avctx->priv_data; + av_freep(&x->pixels); + + return 0; +} + +AVCodec ff_xpm_decoder = { + .name = "xpm", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_XPM, + .priv_data_size = sizeof(XPMDecContext), + .close = xpm_decode_close, + .decode = xpm_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("XPM (X PixMap) image") +}; diff --git a/libavformat/img2.c b/libavformat/img2.c index f9f53ff..29df4f0 100644 --- a/libavformat/img2.c +++ b/libavformat/img2.c @@ -75,6 +75,7 @@ const IdStrMap ff_img_tags[] = { { AV_CODEC_ID_V210X, "yuv10" }, { AV_CODEC_ID_WEBP, "webp" }, { AV_CODEC_ID_XBM, "xbm" }, + { AV_CODEC_ID_XPM, "xpm" }, { AV_CODEC_ID_XFACE, "xface" }, { AV_CODEC_ID_XWD, "xwd" }, { AV_CODEC_ID_NONE, NULL }