diff --git a/libavcodec/pnm.c b/libavcodec/pnm.c index 4fd9c61a24..cb6a7139f2 100644 --- a/libavcodec/pnm.c +++ b/libavcodec/pnm.c @@ -59,16 +59,20 @@ int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s) int h, w, depth, maxval; pnm_get(s, buf1, sizeof(buf1)); - if (!strcmp(buf1, "P4")) { + s->type= buf1[1]-'0'; + if(buf1[0] != 'P') + return -1; + + if (s->type==1 || s->type==4) { avctx->pix_fmt = PIX_FMT_MONOWHITE; - } else if (!strcmp(buf1, "P5")) { + } else if (s->type==2 || s->type==5) { if (avctx->codec_id == CODEC_ID_PGMYUV) avctx->pix_fmt = PIX_FMT_YUV420P; else avctx->pix_fmt = PIX_FMT_GRAY8; - } else if (!strcmp(buf1, "P6")) { + } else if (s->type==3 || s->type==6) { avctx->pix_fmt = PIX_FMT_RGB24; - } else if (!strcmp(buf1, "P7")) { + } else if (s->type==7) { w = -1; h = -1; maxval = -1; @@ -149,7 +153,8 @@ int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s) return -1; } } - } + }else + s->maxval=1; /* more check if YUV420 */ if (avctx->pix_fmt == PIX_FMT_YUV420P) { if ((avctx->width & 1) != 0) diff --git a/libavcodec/pnm.h b/libavcodec/pnm.h index 163cad0815..ac4b1084fb 100644 --- a/libavcodec/pnm.h +++ b/libavcodec/pnm.h @@ -30,6 +30,7 @@ typedef struct PNMContext { uint8_t *bytestream_end; AVFrame picture; int maxval; ///< maximum value of a pixel + int type; } PNMContext; int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s); diff --git a/libavcodec/pnmdec.c b/libavcodec/pnmdec.c index f29c873200..5630e7689c 100644 --- a/libavcodec/pnmdec.c +++ b/libavcodec/pnmdec.c @@ -21,6 +21,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "put_bits.h" #include "pnm.h" @@ -32,8 +33,9 @@ static int pnm_decode_frame(AVCodecContext *avctx, void *data, PNMContext * const s = avctx->priv_data; AVFrame *picture = data; AVFrame * const p = (AVFrame*)&s->picture; - int i, n, linesize, h, upgrade = 0; + int i, j, n, linesize, h, upgrade = 0; unsigned char *ptr; + int components, sample_len; s->bytestream_start = s->bytestream = buf; @@ -58,29 +60,60 @@ static int pnm_decode_frame(AVCodecContext *avctx, void *data, return -1; case PIX_FMT_RGB48BE: n = avctx->width * 6; + components=3; + sample_len=16; goto do_read; case PIX_FMT_RGB24: n = avctx->width * 3; + components=3; + sample_len=8; goto do_read; case PIX_FMT_GRAY8: n = avctx->width; + components=1; + sample_len=8; if (s->maxval < 255) upgrade = 1; goto do_read; case PIX_FMT_GRAY16BE: case PIX_FMT_GRAY16LE: n = avctx->width * 2; + components=1; + sample_len=16; if (s->maxval < 65535) upgrade = 2; goto do_read; case PIX_FMT_MONOWHITE: case PIX_FMT_MONOBLACK: n = (avctx->width + 7) >> 3; + components=1; + sample_len=1; do_read: ptr = p->data[0]; linesize = p->linesize[0]; if (s->bytestream + n * avctx->height > s->bytestream_end) return -1; + if(s->type < 4){ + for (i=0; iheight; i++) { + PutBitContext pb; + init_put_bits(&pb, ptr, linesize); + for(j=0; jwidth * components; j++){ + unsigned int c=0; + int v=0; + while(s->bytestream < s->bytestream_end && (*s->bytestream < '0' || *s->bytestream > '9' )) + s->bytestream++; + if(s->bytestream >= s->bytestream_end) + return -1; + do{ + v= 10*v + c; + c= (*s->bytestream++) - '0'; + }while(c <= 9); + put_bits(&pb, sample_len, (((1<maxval>>1))/s->maxval); + } + flush_put_bits(&pb); + ptr+= linesize; + } + }else{ for (i = 0; i < avctx->height; i++) { if (!upgrade) memcpy(ptr, s->bytestream, n); @@ -98,6 +131,7 @@ static int pnm_decode_frame(AVCodecContext *avctx, void *data, s->bytestream += n; ptr += linesize; } + } break; case PIX_FMT_YUV420P: {