00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "avcodec.h"
00022 #include "pnm.h"
00023
00024 static inline int pnm_space(int c)
00025 {
00026 return c == ' ' || c == '\n' || c == '\r' || c == '\t';
00027 }
00028
00029 static void pnm_get(PNMContext *sc, char *str, int buf_size)
00030 {
00031 char *s;
00032 int c;
00033
00034
00035 for(;;) {
00036 c = *sc->bytestream++;
00037 if (c == '#') {
00038 do {
00039 c = *sc->bytestream++;
00040 } while (c != '\n' && sc->bytestream < sc->bytestream_end);
00041 } else if (!pnm_space(c)) {
00042 break;
00043 }
00044 }
00045
00046 s = str;
00047 while (sc->bytestream < sc->bytestream_end && !pnm_space(c)) {
00048 if ((s - str) < buf_size - 1)
00049 *s++ = c;
00050 c = *sc->bytestream++;
00051 }
00052 *s = '\0';
00053 }
00054
00055 int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s){
00056 char buf1[32], tuple_type[32];
00057 int h, w, depth, maxval;
00058
00059 pnm_get(s, buf1, sizeof(buf1));
00060 if (!strcmp(buf1, "P4")) {
00061 avctx->pix_fmt = PIX_FMT_MONOWHITE;
00062 } else if (!strcmp(buf1, "P5")) {
00063 if (avctx->codec_id == CODEC_ID_PGMYUV)
00064 avctx->pix_fmt = PIX_FMT_YUV420P;
00065 else
00066 avctx->pix_fmt = PIX_FMT_GRAY8;
00067 } else if (!strcmp(buf1, "P6")) {
00068 avctx->pix_fmt = PIX_FMT_RGB24;
00069 } else if (!strcmp(buf1, "P7")) {
00070 w = -1;
00071 h = -1;
00072 maxval = -1;
00073 depth = -1;
00074 tuple_type[0] = '\0';
00075 for(;;) {
00076 pnm_get(s, buf1, sizeof(buf1));
00077 if (!strcmp(buf1, "WIDTH")) {
00078 pnm_get(s, buf1, sizeof(buf1));
00079 w = strtol(buf1, NULL, 10);
00080 } else if (!strcmp(buf1, "HEIGHT")) {
00081 pnm_get(s, buf1, sizeof(buf1));
00082 h = strtol(buf1, NULL, 10);
00083 } else if (!strcmp(buf1, "DEPTH")) {
00084 pnm_get(s, buf1, sizeof(buf1));
00085 depth = strtol(buf1, NULL, 10);
00086 } else if (!strcmp(buf1, "MAXVAL")) {
00087 pnm_get(s, buf1, sizeof(buf1));
00088 maxval = strtol(buf1, NULL, 10);
00089 } else if (!strcmp(buf1, "TUPLETYPE")) {
00090 pnm_get(s, tuple_type, sizeof(tuple_type));
00091 } else if (!strcmp(buf1, "ENDHDR")) {
00092 break;
00093 } else {
00094 return -1;
00095 }
00096 }
00097
00098 if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '\0' || avcodec_check_dimensions(avctx, w, h))
00099 return -1;
00100
00101 avctx->width = w;
00102 avctx->height = h;
00103 if (depth == 1) {
00104 if (maxval == 1)
00105 avctx->pix_fmt = PIX_FMT_MONOWHITE;
00106 else
00107 avctx->pix_fmt = PIX_FMT_GRAY8;
00108 } else if (depth == 3) {
00109 if (maxval < 256) {
00110 avctx->pix_fmt = PIX_FMT_RGB24;
00111 } else {
00112 av_log(avctx, AV_LOG_ERROR, "16-bit components are only supported for grayscale\n");
00113 avctx->pix_fmt = PIX_FMT_NONE;
00114 return -1;
00115 }
00116 } else if (depth == 4) {
00117 avctx->pix_fmt = PIX_FMT_RGB32;
00118 } else {
00119 return -1;
00120 }
00121 return 0;
00122 } else {
00123 return -1;
00124 }
00125 pnm_get(s, buf1, sizeof(buf1));
00126 avctx->width = atoi(buf1);
00127 if (avctx->width <= 0)
00128 return -1;
00129 pnm_get(s, buf1, sizeof(buf1));
00130 avctx->height = atoi(buf1);
00131 if(avcodec_check_dimensions(avctx, avctx->width, avctx->height))
00132 return -1;
00133 if (avctx->pix_fmt != PIX_FMT_MONOWHITE) {
00134 pnm_get(s, buf1, sizeof(buf1));
00135 s->maxval = atoi(buf1);
00136 if (s->maxval >= 256) {
00137 if (avctx->pix_fmt == PIX_FMT_GRAY8) {
00138 avctx->pix_fmt = PIX_FMT_GRAY16BE;
00139 if (s->maxval != 65535)
00140 avctx->pix_fmt = PIX_FMT_GRAY16;
00141 } if (avctx->pix_fmt == PIX_FMT_RGB24) {
00142 if (s->maxval > 255)
00143 avctx->pix_fmt = PIX_FMT_RGB48BE;
00144 } else {
00145 av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format\n");
00146 avctx->pix_fmt = PIX_FMT_NONE;
00147 return -1;
00148 }
00149 }
00150 }
00151
00152 if (avctx->pix_fmt == PIX_FMT_YUV420P) {
00153 if ((avctx->width & 1) != 0)
00154 return -1;
00155 h = (avctx->height * 2);
00156 if ((h % 3) != 0)
00157 return -1;
00158 h /= 3;
00159 avctx->height = h;
00160 }
00161 return 0;
00162 }