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