Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * PNM image format
  3.  * Copyright (c) 2002, 2003 Fabrice Bellard
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. #include <stdlib.h>
  23. #include <string.h>
  24.  
  25. #include "libavutil/imgutils.h"
  26. #include "avcodec.h"
  27. #include "pnm.h"
  28.  
  29. static inline int pnm_space(int c)
  30. {
  31.     return c == ' ' || c == '\n' || c == '\r' || c == '\t';
  32. }
  33.  
  34. static void pnm_get(PNMContext *sc, char *str, int buf_size)
  35. {
  36.     char *s;
  37.     int c;
  38.  
  39.     /* skip spaces and comments */
  40.     while (sc->bytestream < sc->bytestream_end) {
  41.         c = *sc->bytestream++;
  42.         if (c == '#')  {
  43.             while (c != '\n' && sc->bytestream < sc->bytestream_end) {
  44.                 c = *sc->bytestream++;
  45.             }
  46.         } else if (!pnm_space(c)) {
  47.             break;
  48.         }
  49.     }
  50.  
  51.     s = str;
  52.     while (sc->bytestream < sc->bytestream_end && !pnm_space(c)) {
  53.         if ((s - str)  < buf_size - 1)
  54.             *s++ = c;
  55.         c = *sc->bytestream++;
  56.     }
  57.     *s = '\0';
  58. }
  59.  
  60. int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s)
  61. {
  62.     char buf1[32], tuple_type[32];
  63.     int h, w, depth, maxval;
  64.  
  65.     pnm_get(s, buf1, sizeof(buf1));
  66.     s->type= buf1[1]-'0';
  67.     if(buf1[0] != 'P')
  68.         return AVERROR_INVALIDDATA;
  69.  
  70.     if (s->type==1 || s->type==4) {
  71.         avctx->pix_fmt = AV_PIX_FMT_MONOWHITE;
  72.     } else if (s->type==2 || s->type==5) {
  73.         if (avctx->codec_id == AV_CODEC_ID_PGMYUV)
  74.             avctx->pix_fmt = AV_PIX_FMT_YUV420P;
  75.         else
  76.             avctx->pix_fmt = AV_PIX_FMT_GRAY8;
  77.     } else if (s->type==3 || s->type==6) {
  78.         avctx->pix_fmt = AV_PIX_FMT_RGB24;
  79.     } else if (s->type==7) {
  80.         w      = -1;
  81.         h      = -1;
  82.         maxval = -1;
  83.         depth  = -1;
  84.         tuple_type[0] = '\0';
  85.         for (;;) {
  86.             pnm_get(s, buf1, sizeof(buf1));
  87.             if (!strcmp(buf1, "WIDTH")) {
  88.                 pnm_get(s, buf1, sizeof(buf1));
  89.                 w = strtol(buf1, NULL, 10);
  90.             } else if (!strcmp(buf1, "HEIGHT")) {
  91.                 pnm_get(s, buf1, sizeof(buf1));
  92.                 h = strtol(buf1, NULL, 10);
  93.             } else if (!strcmp(buf1, "DEPTH")) {
  94.                 pnm_get(s, buf1, sizeof(buf1));
  95.                 depth = strtol(buf1, NULL, 10);
  96.             } else if (!strcmp(buf1, "MAXVAL")) {
  97.                 pnm_get(s, buf1, sizeof(buf1));
  98.                 maxval = strtol(buf1, NULL, 10);
  99.             } else if (!strcmp(buf1, "TUPLTYPE") ||
  100.                        /* libavcodec used to write invalid files */
  101.                        !strcmp(buf1, "TUPLETYPE")) {
  102.                 pnm_get(s, tuple_type, sizeof(tuple_type));
  103.             } else if (!strcmp(buf1, "ENDHDR")) {
  104.                 break;
  105.             } else {
  106.                 return AVERROR_INVALIDDATA;
  107.             }
  108.         }
  109.         /* check that all tags are present */
  110.         if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '\0' || av_image_check_size(w, h, 0, avctx) || s->bytestream >= s->bytestream_end)
  111.             return AVERROR_INVALIDDATA;
  112.  
  113.         avctx->width  = w;
  114.         avctx->height = h;
  115.         s->maxval     = maxval;
  116.         if (depth == 1) {
  117.             if (maxval == 1) {
  118.                 avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
  119.             } else if (maxval < 256) {
  120.                 avctx->pix_fmt = AV_PIX_FMT_GRAY8;
  121.             } else {
  122.                 avctx->pix_fmt = AV_PIX_FMT_GRAY16;
  123.             }
  124.         } else if (depth == 2) {
  125.             if (maxval == 255)
  126.                 avctx->pix_fmt = AV_PIX_FMT_GRAY8A;
  127.         } else if (depth == 3) {
  128.             if (maxval < 256) {
  129.                 avctx->pix_fmt = AV_PIX_FMT_RGB24;
  130.             } else {
  131.                 avctx->pix_fmt = AV_PIX_FMT_RGB48;
  132.             }
  133.         } else if (depth == 4) {
  134.             if (maxval < 256) {
  135.                 avctx->pix_fmt = AV_PIX_FMT_RGBA;
  136.             } else {
  137.                 avctx->pix_fmt = AV_PIX_FMT_RGBA64;
  138.             }
  139.         } else {
  140.             return AVERROR_INVALIDDATA;
  141.         }
  142.         return 0;
  143.     } else {
  144.         return AVERROR_INVALIDDATA;
  145.     }
  146.     pnm_get(s, buf1, sizeof(buf1));
  147.     w = atoi(buf1);
  148.     pnm_get(s, buf1, sizeof(buf1));
  149.     h = atoi(buf1);
  150.     if(w <= 0 || h <= 0 || av_image_check_size(w, h, 0, avctx) || s->bytestream >= s->bytestream_end)
  151.         return AVERROR_INVALIDDATA;
  152.  
  153.     avctx->width  = w;
  154.     avctx->height = h;
  155.  
  156.     if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE && avctx->pix_fmt != AV_PIX_FMT_MONOBLACK) {
  157.         pnm_get(s, buf1, sizeof(buf1));
  158.         s->maxval = atoi(buf1);
  159.         if (s->maxval <= 0) {
  160.             av_log(avctx, AV_LOG_ERROR, "Invalid maxval: %d\n", s->maxval);
  161.             s->maxval = 255;
  162.         }
  163.         if (s->maxval >= 256) {
  164.             if (avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
  165.                 avctx->pix_fmt = AV_PIX_FMT_GRAY16;
  166.             } else if (avctx->pix_fmt == AV_PIX_FMT_RGB24) {
  167.                 avctx->pix_fmt = AV_PIX_FMT_RGB48;
  168.             } else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P && s->maxval < 65536) {
  169.                 if (s->maxval < 512)
  170.                     avctx->pix_fmt = AV_PIX_FMT_YUV420P9;
  171.                 else if (s->maxval < 1024)
  172.                     avctx->pix_fmt = AV_PIX_FMT_YUV420P10;
  173.                 else
  174.                     avctx->pix_fmt = AV_PIX_FMT_YUV420P16;
  175.             } else {
  176.                 av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format\n");
  177.                 avctx->pix_fmt = AV_PIX_FMT_NONE;
  178.                 return AVERROR_INVALIDDATA;
  179.             }
  180.         }
  181.     }else
  182.         s->maxval=1;
  183.     /* more check if YUV420 */
  184.     if (av_pix_fmt_desc_get(avctx->pix_fmt)->flags & AV_PIX_FMT_FLAG_PLANAR) {
  185.         if ((avctx->width & 1) != 0)
  186.             return AVERROR_INVALIDDATA;
  187.         h = (avctx->height * 2);
  188.         if ((h % 3) != 0)
  189.             return AVERROR_INVALIDDATA;
  190.         h /= 3;
  191.         avctx->height = h;
  192.     }
  193.     return 0;
  194. }
  195.