Libav
|
00001 /* 00002 * PNM image format 00003 * Copyright (c) 2002, 2003 Fabrice Bellard 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "avcodec.h" 00023 #include "pnm.h" 00024 00025 static inline int pnm_space(int c) 00026 { 00027 return c == ' ' || c == '\n' || c == '\r' || c == '\t'; 00028 } 00029 00030 static void pnm_get(PNMContext *sc, char *str, int buf_size) 00031 { 00032 char *s; 00033 int c; 00034 00035 /* skip spaces and comments */ 00036 for (;;) { 00037 c = *sc->bytestream++; 00038 if (c == '#') { 00039 do { 00040 c = *sc->bytestream++; 00041 } while (c != '\n' && sc->bytestream < sc->bytestream_end); 00042 } else if (!pnm_space(c)) { 00043 break; 00044 } 00045 } 00046 00047 s = str; 00048 while (sc->bytestream < sc->bytestream_end && !pnm_space(c)) { 00049 if ((s - str) < buf_size - 1) 00050 *s++ = c; 00051 c = *sc->bytestream++; 00052 } 00053 *s = '\0'; 00054 } 00055 00056 int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s) 00057 { 00058 char buf1[32], tuple_type[32]; 00059 int h, w, depth, maxval; 00060 00061 pnm_get(s, buf1, sizeof(buf1)); 00062 s->type= buf1[1]-'0'; 00063 if(buf1[0] != 'P') 00064 return -1; 00065 00066 if (s->type==1 || s->type==4) { 00067 avctx->pix_fmt = PIX_FMT_MONOWHITE; 00068 } else if (s->type==2 || s->type==5) { 00069 if (avctx->codec_id == CODEC_ID_PGMYUV) 00070 avctx->pix_fmt = PIX_FMT_YUV420P; 00071 else 00072 avctx->pix_fmt = PIX_FMT_GRAY8; 00073 } else if (s->type==3 || s->type==6) { 00074 avctx->pix_fmt = PIX_FMT_RGB24; 00075 } else if (s->type==7) { 00076 w = -1; 00077 h = -1; 00078 maxval = -1; 00079 depth = -1; 00080 tuple_type[0] = '\0'; 00081 for (;;) { 00082 pnm_get(s, buf1, sizeof(buf1)); 00083 if (!strcmp(buf1, "WIDTH")) { 00084 pnm_get(s, buf1, sizeof(buf1)); 00085 w = strtol(buf1, NULL, 10); 00086 } else if (!strcmp(buf1, "HEIGHT")) { 00087 pnm_get(s, buf1, sizeof(buf1)); 00088 h = strtol(buf1, NULL, 10); 00089 } else if (!strcmp(buf1, "DEPTH")) { 00090 pnm_get(s, buf1, sizeof(buf1)); 00091 depth = strtol(buf1, NULL, 10); 00092 } else if (!strcmp(buf1, "MAXVAL")) { 00093 pnm_get(s, buf1, sizeof(buf1)); 00094 maxval = strtol(buf1, NULL, 10); 00095 } else if (!strcmp(buf1, "TUPLETYPE")) { 00096 pnm_get(s, tuple_type, sizeof(tuple_type)); 00097 } else if (!strcmp(buf1, "ENDHDR")) { 00098 break; 00099 } else { 00100 return -1; 00101 } 00102 } 00103 /* check that all tags are present */ 00104 if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '\0' || avcodec_check_dimensions(avctx, w, h)) 00105 return -1; 00106 00107 avctx->width = w; 00108 avctx->height = h; 00109 if (depth == 1) { 00110 if (maxval == 1) 00111 avctx->pix_fmt = PIX_FMT_MONOWHITE; 00112 else 00113 avctx->pix_fmt = PIX_FMT_GRAY8; 00114 } else if (depth == 3) { 00115 if (maxval < 256) { 00116 avctx->pix_fmt = PIX_FMT_RGB24; 00117 } else { 00118 av_log(avctx, AV_LOG_ERROR, "16-bit components are only supported for grayscale\n"); 00119 avctx->pix_fmt = PIX_FMT_NONE; 00120 return -1; 00121 } 00122 } else if (depth == 4) { 00123 avctx->pix_fmt = PIX_FMT_RGB32; 00124 } else { 00125 return -1; 00126 } 00127 return 0; 00128 } else { 00129 return -1; 00130 } 00131 pnm_get(s, buf1, sizeof(buf1)); 00132 avctx->width = atoi(buf1); 00133 if (avctx->width <= 0) 00134 return -1; 00135 pnm_get(s, buf1, sizeof(buf1)); 00136 avctx->height = atoi(buf1); 00137 if(avcodec_check_dimensions(avctx, avctx->width, avctx->height)) 00138 return -1; 00139 if (avctx->pix_fmt != PIX_FMT_MONOWHITE) { 00140 pnm_get(s, buf1, sizeof(buf1)); 00141 s->maxval = atoi(buf1); 00142 if (s->maxval >= 256) { 00143 if (avctx->pix_fmt == PIX_FMT_GRAY8) { 00144 avctx->pix_fmt = PIX_FMT_GRAY16BE; 00145 if (s->maxval != 65535) 00146 avctx->pix_fmt = PIX_FMT_GRAY16; 00147 } else if (avctx->pix_fmt == PIX_FMT_RGB24) { 00148 if (s->maxval > 255) 00149 avctx->pix_fmt = PIX_FMT_RGB48BE; 00150 } else { 00151 av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format\n"); 00152 avctx->pix_fmt = PIX_FMT_NONE; 00153 return -1; 00154 } 00155 } 00156 }else 00157 s->maxval=1; 00158 /* more check if YUV420 */ 00159 if (avctx->pix_fmt == PIX_FMT_YUV420P) { 00160 if ((avctx->width & 1) != 0) 00161 return -1; 00162 h = (avctx->height * 2); 00163 if ((h % 3) != 0) 00164 return -1; 00165 h /= 3; 00166 avctx->height = h; 00167 } 00168 return 0; 00169 } 00170 00171 av_cold int ff_pnm_end(AVCodecContext *avctx) 00172 { 00173 PNMContext *s = avctx->priv_data; 00174 00175 if (s->picture.data[0]) 00176 avctx->release_buffer(avctx, &s->picture); 00177 00178 return 0; 00179 } 00180 00181 av_cold int ff_pnm_init(AVCodecContext *avctx) 00182 { 00183 PNMContext *s = avctx->priv_data; 00184 00185 avcodec_get_frame_defaults((AVFrame*)&s->picture); 00186 avctx->coded_frame = (AVFrame*)&s->picture; 00187 00188 return 0; 00189 }