Subversion Repositories Kolibri OS

Rev

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.     if(buf1[0] != 'P')
  67.         return AVERROR_INVALIDDATA;
  68.     s->type= buf1[1]-'0';
  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 < 256) {
  126.                 avctx->pix_fmt = AV_PIX_FMT_GRAY8A;
  127.             } else {
  128.                 avctx->pix_fmt = AV_PIX_FMT_YA16;
  129.             }
  130.         } else if (depth == 3) {
  131.             if (maxval < 256) {
  132.                 avctx->pix_fmt = AV_PIX_FMT_RGB24;
  133.             } else {
  134.                 avctx->pix_fmt = AV_PIX_FMT_RGB48;
  135.             }
  136.         } else if (depth == 4) {
  137.             if (maxval < 256) {
  138.                 avctx->pix_fmt = AV_PIX_FMT_RGBA;
  139.             } else {
  140.                 avctx->pix_fmt = AV_PIX_FMT_RGBA64;
  141.             }
  142.         } else {
  143.             return AVERROR_INVALIDDATA;
  144.         }
  145.         return 0;
  146.     } else {
  147.         return AVERROR_INVALIDDATA;
  148.     }
  149.     pnm_get(s, buf1, sizeof(buf1));
  150.     w = atoi(buf1);
  151.     pnm_get(s, buf1, sizeof(buf1));
  152.     h = atoi(buf1);
  153.     if(w <= 0 || h <= 0 || av_image_check_size(w, h, 0, avctx) || s->bytestream >= s->bytestream_end)
  154.         return AVERROR_INVALIDDATA;
  155.  
  156.     avctx->width  = w;
  157.     avctx->height = h;
  158.  
  159.     if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE && avctx->pix_fmt != AV_PIX_FMT_MONOBLACK) {
  160.         pnm_get(s, buf1, sizeof(buf1));
  161.         s->maxval = atoi(buf1);
  162.         if (s->maxval <= 0) {
  163.             av_log(avctx, AV_LOG_ERROR, "Invalid maxval: %d\n", s->maxval);
  164.             s->maxval = 255;
  165.         }
  166.         if (s->maxval >= 256) {
  167.             if (avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
  168.                 avctx->pix_fmt = AV_PIX_FMT_GRAY16;
  169.             } else if (avctx->pix_fmt == AV_PIX_FMT_RGB24) {
  170.                 avctx->pix_fmt = AV_PIX_FMT_RGB48;
  171.             } else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P && s->maxval < 65536) {
  172.                 if (s->maxval < 512)
  173.                     avctx->pix_fmt = AV_PIX_FMT_YUV420P9;
  174.                 else if (s->maxval < 1024)
  175.                     avctx->pix_fmt = AV_PIX_FMT_YUV420P10;
  176.                 else
  177.                     avctx->pix_fmt = AV_PIX_FMT_YUV420P16;
  178.             } else {
  179.                 av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format\n");
  180.                 avctx->pix_fmt = AV_PIX_FMT_NONE;
  181.                 return AVERROR_INVALIDDATA;
  182.             }
  183.         }
  184.     }else
  185.         s->maxval=1;
  186.     /* more check if YUV420 */
  187.     if (av_pix_fmt_desc_get(avctx->pix_fmt)->flags & AV_PIX_FMT_FLAG_PLANAR) {
  188.         if ((avctx->width & 1) != 0)
  189.             return AVERROR_INVALIDDATA;
  190.         h = (avctx->height * 2);
  191.         if ((h % 3) != 0)
  192.             return AVERROR_INVALIDDATA;
  193.         h /= 3;
  194.         avctx->height = h;
  195.     }
  196.     return 0;
  197. }
  198.