00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdlib.h>
00023 #include <string.h>
00024
00025 #include "libavutil/imgutils.h"
00026 #include "avcodec.h"
00027 #include "pnm.h"
00028
00029 static inline int pnm_space(int c)
00030 {
00031 return c == ' ' || c == '\n' || c == '\r' || c == '\t';
00032 }
00033
00034 static void pnm_get(PNMContext *sc, char *str, int buf_size)
00035 {
00036 char *s;
00037 int c;
00038
00039
00040 while (sc->bytestream < sc->bytestream_end) {
00041 c = *sc->bytestream++;
00042 if (c == '#') {
00043 while (c != '\n' && sc->bytestream < sc->bytestream_end) {
00044 c = *sc->bytestream++;
00045 }
00046 } else if (!pnm_space(c)) {
00047 break;
00048 }
00049 }
00050
00051 s = str;
00052 while (sc->bytestream < sc->bytestream_end && !pnm_space(c)) {
00053 if ((s - str) < buf_size - 1)
00054 *s++ = c;
00055 c = *sc->bytestream++;
00056 }
00057 *s = '\0';
00058 }
00059
00060 int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s)
00061 {
00062 char buf1[32], tuple_type[32];
00063 int h, w, depth, maxval;
00064
00065 pnm_get(s, buf1, sizeof(buf1));
00066 s->type= buf1[1]-'0';
00067 if(buf1[0] != 'P')
00068 return -1;
00069
00070 if (s->type==1 || s->type==4) {
00071 avctx->pix_fmt = AV_PIX_FMT_MONOWHITE;
00072 } else if (s->type==2 || s->type==5) {
00073 if (avctx->codec_id == AV_CODEC_ID_PGMYUV)
00074 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
00075 else
00076 avctx->pix_fmt = AV_PIX_FMT_GRAY8;
00077 } else if (s->type==3 || s->type==6) {
00078 avctx->pix_fmt = AV_PIX_FMT_RGB24;
00079 } else if (s->type==7) {
00080 w = -1;
00081 h = -1;
00082 maxval = -1;
00083 depth = -1;
00084 tuple_type[0] = '\0';
00085 for (;;) {
00086 pnm_get(s, buf1, sizeof(buf1));
00087 if (!strcmp(buf1, "WIDTH")) {
00088 pnm_get(s, buf1, sizeof(buf1));
00089 w = strtol(buf1, NULL, 10);
00090 } else if (!strcmp(buf1, "HEIGHT")) {
00091 pnm_get(s, buf1, sizeof(buf1));
00092 h = strtol(buf1, NULL, 10);
00093 } else if (!strcmp(buf1, "DEPTH")) {
00094 pnm_get(s, buf1, sizeof(buf1));
00095 depth = strtol(buf1, NULL, 10);
00096 } else if (!strcmp(buf1, "MAXVAL")) {
00097 pnm_get(s, buf1, sizeof(buf1));
00098 maxval = strtol(buf1, NULL, 10);
00099 } else if (!strcmp(buf1, "TUPLTYPE") ||
00100
00101 !strcmp(buf1, "TUPLETYPE")) {
00102 pnm_get(s, tuple_type, sizeof(tuple_type));
00103 } else if (!strcmp(buf1, "ENDHDR")) {
00104 break;
00105 } else {
00106 return -1;
00107 }
00108 }
00109
00110 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)
00111 return -1;
00112
00113 avctx->width = w;
00114 avctx->height = h;
00115 s->maxval = maxval;
00116 if (depth == 1) {
00117 if (maxval == 1) {
00118 avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
00119 } else if (maxval == 255) {
00120 avctx->pix_fmt = AV_PIX_FMT_GRAY8;
00121 } else {
00122 avctx->pix_fmt = AV_PIX_FMT_GRAY16BE;
00123 }
00124 } else if (depth == 2) {
00125 if (maxval == 255)
00126 avctx->pix_fmt = AV_PIX_FMT_GRAY8A;
00127 } else if (depth == 3) {
00128 if (maxval < 256) {
00129 avctx->pix_fmt = AV_PIX_FMT_RGB24;
00130 } else {
00131 avctx->pix_fmt = AV_PIX_FMT_RGB48BE;
00132 }
00133 } else if (depth == 4) {
00134 if (maxval < 256) {
00135 avctx->pix_fmt = AV_PIX_FMT_RGBA;
00136 } else {
00137 avctx->pix_fmt = AV_PIX_FMT_RGBA64BE;
00138 }
00139 } else {
00140 return -1;
00141 }
00142 return 0;
00143 } else {
00144 return -1;
00145 }
00146 pnm_get(s, buf1, sizeof(buf1));
00147 w = atoi(buf1);
00148 pnm_get(s, buf1, sizeof(buf1));
00149 h = atoi(buf1);
00150 if(w <= 0 || h <= 0 || av_image_check_size(w, h, 0, avctx) || s->bytestream >= s->bytestream_end)
00151 return -1;
00152
00153 avctx->width = w;
00154 avctx->height = h;
00155
00156 if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE && avctx->pix_fmt != AV_PIX_FMT_MONOBLACK) {
00157 pnm_get(s, buf1, sizeof(buf1));
00158 s->maxval = atoi(buf1);
00159 if (s->maxval <= 0) {
00160 av_log(avctx, AV_LOG_ERROR, "Invalid maxval: %d\n", s->maxval);
00161 s->maxval = 255;
00162 }
00163 if (s->maxval >= 256) {
00164 if (avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
00165 avctx->pix_fmt = AV_PIX_FMT_GRAY16BE;
00166 } else if (avctx->pix_fmt == AV_PIX_FMT_RGB24) {
00167 avctx->pix_fmt = AV_PIX_FMT_RGB48BE;
00168 } else {
00169 av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format\n");
00170 avctx->pix_fmt = AV_PIX_FMT_NONE;
00171 return -1;
00172 }
00173 }
00174 }else
00175 s->maxval=1;
00176
00177 if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
00178 if ((avctx->width & 1) != 0)
00179 return -1;
00180 h = (avctx->height * 2);
00181 if ((h % 3) != 0)
00182 return -1;
00183 h /= 3;
00184 avctx->height = h;
00185 }
00186 return 0;
00187 }
00188
00189 av_cold int ff_pnm_end(AVCodecContext *avctx)
00190 {
00191 PNMContext *s = avctx->priv_data;
00192
00193 if (s->picture.data[0])
00194 avctx->release_buffer(avctx, &s->picture);
00195
00196 return 0;
00197 }
00198
00199 av_cold int ff_pnm_init(AVCodecContext *avctx)
00200 {
00201 PNMContext *s = avctx->priv_data;
00202
00203 avcodec_get_frame_defaults(&s->picture);
00204 avctx->coded_frame = &s->picture;
00205
00206 return 0;
00207 }