summaryrefslogtreecommitdiff
path: root/libavformat/pnm.c
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2003-01-11 05:02:14 +0000
committerFabrice Bellard <fabrice@bellard.org>2003-01-11 05:02:14 +0000
commit87a0a6816f63c37fd6ea78ff8801e9f2d18e93f7 (patch)
tree7fef66f2bcce32f3d60bc8306e3c6de8df6524bf /libavformat/pnm.c
parentf746a0461694a8951d003395d79af8eba9dae5ed (diff)
added still image support
Originally committed as revision 1439 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat/pnm.c')
-rw-r--r--libavformat/pnm.c285
1 files changed, 285 insertions, 0 deletions
diff --git a/libavformat/pnm.c b/libavformat/pnm.c
new file mode 100644
index 0000000000..a0414c87d1
--- /dev/null
+++ b/libavformat/pnm.c
@@ -0,0 +1,285 @@
+/*
+ * PNM image format
+ * Copyright (c) 2002, 2003 Fabrice Bellard.
+ *
+ * This library 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 of the License, or (at your option) any later version.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "avformat.h"
+
+static inline int pnm_space(int c)
+{
+ return (c == ' ' || c == '\n' || c == '\r' || c == '\t');
+}
+
+static void pnm_get(ByteIOContext *f, char *str, int buf_size)
+{
+ char *s;
+ int c;
+
+ /* skip spaces and comments */
+ for(;;) {
+ c = url_fgetc(f);
+ if (c == '#') {
+ do {
+ c = url_fgetc(f);
+ } while (c != '\n' && c != URL_EOF);
+ } else if (!pnm_space(c)) {
+ break;
+ }
+ }
+
+ s = str;
+ while (c != URL_EOF && !pnm_space(c)) {
+ if ((s - str) < buf_size - 1)
+ *s++ = c;
+ c = url_fgetc(f);
+ }
+ *s = '\0';
+}
+
+static int pnm_read1(ByteIOContext *f,
+ int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque,
+ int allow_yuv)
+{
+ int i, n, linesize, h;
+ char buf1[32];
+ unsigned char *ptr;
+ AVImageInfo info1, *info = &info1;
+ int ret;
+
+ pnm_get(f, buf1, sizeof(buf1));
+ if (!strcmp(buf1, "P4")) {
+ info->pix_fmt = PIX_FMT_MONOWHITE;
+ } else if (!strcmp(buf1, "P5")) {
+ if (allow_yuv)
+ info->pix_fmt = PIX_FMT_YUV420P;
+ else
+ info->pix_fmt = PIX_FMT_GRAY8;
+ } else if (!strcmp(buf1, "P6")) {
+ info->pix_fmt = PIX_FMT_RGB24;
+ } else {
+ return AVERROR_INVALIDDATA;
+ }
+ pnm_get(f, buf1, sizeof(buf1));
+ info->width = atoi(buf1);
+ if (info->width <= 0)
+ return AVERROR_INVALIDDATA;
+ pnm_get(f, buf1, sizeof(buf1));
+ info->height = atoi(buf1);
+ if (info->height <= 0)
+ return AVERROR_INVALIDDATA;
+ if (info->pix_fmt != PIX_FMT_MONOWHITE) {
+ pnm_get(f, buf1, sizeof(buf1));
+ }
+
+ /* more check if YUV420 */
+ if (info->pix_fmt == PIX_FMT_YUV420P) {
+ if ((info->width & 1) != 0)
+ return AVERROR_INVALIDDATA;
+ h = (info->height * 2);
+ if ((h % 3) != 0)
+ return AVERROR_INVALIDDATA;
+ h /= 3;
+ info->height = h;
+ }
+
+ ret = alloc_cb(opaque, info);
+ if (ret)
+ return ret;
+
+ switch(info->pix_fmt) {
+ default:
+ return AVERROR_INVALIDDATA;
+ case PIX_FMT_RGB24:
+ n = info->width * 3;
+ goto do_read;
+ case PIX_FMT_GRAY8:
+ n = info->width;
+ goto do_read;
+ case PIX_FMT_MONOWHITE:
+ n = (info->width + 7) >> 3;
+ do_read:
+ ptr = info->pict.data[0];
+ linesize = info->pict.linesize[0];
+ for(i = 0; i < info->height; i++) {
+ get_buffer(f, ptr, n);
+ ptr += linesize;
+ }
+ break;
+ case PIX_FMT_YUV420P:
+ {
+ unsigned char *ptr1, *ptr2;
+
+ n = info->width;
+ ptr = info->pict.data[0];
+ linesize = info->pict.linesize[0];
+ for(i = 0; i < info->height; i++) {
+ get_buffer(f, ptr, n);
+ ptr += linesize;
+ }
+ ptr1 = info->pict.data[1];
+ ptr2 = info->pict.data[2];
+ n >>= 1;
+ h = info->height >> 1;
+ for(i = 0; i < h; i++) {
+ get_buffer(f, ptr1, n);
+ get_buffer(f, ptr2, n);
+ ptr1 += info->pict.linesize[1];
+ ptr2 += info->pict.linesize[2];
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+static int pnm_read(ByteIOContext *f,
+ int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
+{
+ return pnm_read1(f, alloc_cb, opaque, 0);
+}
+
+static int pgmyuv_read(ByteIOContext *f,
+ int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
+{
+ return pnm_read1(f, alloc_cb, opaque, 1);
+}
+
+static int pnm_write(ByteIOContext *pb, AVImageInfo *info)
+{
+ int i, h, h1, c, n, linesize;
+ char buf[100];
+ UINT8 *ptr, *ptr1, *ptr2;
+
+ h = info->height;
+ h1 = h;
+ switch(info->pix_fmt) {
+ case PIX_FMT_MONOWHITE:
+ c = '4';
+ n = (info->width + 7) >> 3;
+ break;
+ case PIX_FMT_GRAY8:
+ c = '5';
+ n = info->width;
+ break;
+ case PIX_FMT_RGB24:
+ c = '6';
+ n = info->width * 3;
+ break;
+ case PIX_FMT_YUV420P:
+ c = '5';
+ n = info->width;
+ h1 = (h * 3) / 2;
+ break;
+ default:
+ return AVERROR_INVALIDDATA;
+ }
+ snprintf(buf, sizeof(buf),
+ "P%c\n%d %d\n",
+ c, info->width, h1);
+ put_buffer(pb, buf, strlen(buf));
+ if (info->pix_fmt != PIX_FMT_MONOWHITE) {
+ snprintf(buf, sizeof(buf),
+ "%d\n", 255);
+ put_buffer(pb, buf, strlen(buf));
+ }
+
+ ptr = info->pict.data[0];
+ linesize = info->pict.linesize[0];
+ for(i=0;i<h;i++) {
+ put_buffer(pb, ptr, n);
+ ptr += linesize;
+ }
+
+ if (info->pix_fmt == PIX_FMT_YUV420P) {
+ h >>= 1;
+ n >>= 1;
+ ptr1 = info->pict.data[1];
+ ptr2 = info->pict.data[2];
+ for(i=0;i<h;i++) {
+ put_buffer(pb, ptr1, n);
+ put_buffer(pb, ptr2, n);
+ ptr1 += info->pict.linesize[1];
+ ptr2 += info->pict.linesize[2];
+ }
+ }
+ put_flush_packet(pb);
+ return 0;
+}
+
+static int pnm_probe(AVProbeData *pd)
+{
+ const char *p = pd->buf;
+ if (pd->buf_size >= 8 &&
+ p[0] == 'P' &&
+ p[1] >= '4' && p[1] <= '6' &&
+ p[2] == '\n')
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+static int pgmyuv_probe(AVProbeData *pd)
+{
+ if (match_ext(pd->filename, "pgmyuv"))
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+AVImageFormat pnm_image_format = {
+ "pnm",
+ NULL,
+ pnm_probe,
+ pnm_read,
+ 0,
+ NULL,
+};
+
+AVImageFormat pbm_image_format = {
+ "pbm",
+ "pbm",
+ NULL,
+ NULL,
+ (1 << PIX_FMT_MONOWHITE),
+ pnm_write,
+};
+
+AVImageFormat pgm_image_format = {
+ "pgm",
+ "pgm",
+ NULL,
+ NULL,
+ (1 << PIX_FMT_GRAY8),
+ pnm_write,
+};
+
+AVImageFormat ppm_image_format = {
+ "ppm",
+ "ppm",
+ NULL,
+ NULL,
+ (1 << PIX_FMT_RGB24),
+ pnm_write,
+};
+
+AVImageFormat pgmyuv_image_format = {
+ "pgmyuv",
+ NULL,
+ pgmyuv_probe,
+ pgmyuv_read,
+ (1 << PIX_FMT_YUV420P),
+ pnm_write,
+};