1/* 2 * PAM image format 3 * Copyright (c) 2002, 2003 Fabrice Bellard 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#include "avcodec.h" 23#include "bytestream.h" 24#include "pnm.h" 25 26 27static int pam_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, 28 int buf_size, void *data) 29{ 30 PNMContext *s = avctx->priv_data; 31 AVFrame *pict = data; 32 AVFrame * const p = (AVFrame*)&s->picture; 33 int i, h, w, n, linesize, depth, maxval; 34 const char *tuple_type; 35 uint8_t *ptr; 36 37 if (buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200) { 38 av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n"); 39 return -1; 40 } 41 42 *p = *pict; 43 p->pict_type = FF_I_TYPE; 44 p->key_frame = 1; 45 46 s->bytestream_start = 47 s->bytestream = outbuf; 48 s->bytestream_end = outbuf+buf_size; 49 50 h = avctx->height; 51 w = avctx->width; 52 switch (avctx->pix_fmt) { 53 case PIX_FMT_MONOWHITE: 54 n = (w + 7) >> 3; 55 depth = 1; 56 maxval = 1; 57 tuple_type = "BLACKANDWHITE"; 58 break; 59 case PIX_FMT_GRAY8: 60 n = w; 61 depth = 1; 62 maxval = 255; 63 tuple_type = "GRAYSCALE"; 64 break; 65 case PIX_FMT_RGB24: 66 n = w * 3; 67 depth = 3; 68 maxval = 255; 69 tuple_type = "RGB"; 70 break; 71 case PIX_FMT_RGB32: 72 n = w * 4; 73 depth = 4; 74 maxval = 255; 75 tuple_type = "RGB_ALPHA"; 76 break; 77 default: 78 return -1; 79 } 80 snprintf(s->bytestream, s->bytestream_end - s->bytestream, 81 "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLETYPE %s\nENDHDR\n", 82 w, h, depth, maxval, tuple_type); 83 s->bytestream += strlen(s->bytestream); 84 85 ptr = p->data[0]; 86 linesize = p->linesize[0]; 87 88 if (avctx->pix_fmt == PIX_FMT_RGB32) { 89 int j; 90 unsigned int v; 91 92 for (i = 0; i < h; i++) { 93 for (j = 0; j < w; j++) { 94 v = ((uint32_t *)ptr)[j]; 95 bytestream_put_be24(&s->bytestream, v); 96 *s->bytestream++ = v >> 24; 97 } 98 ptr += linesize; 99 } 100 } else { 101 for (i = 0; i < h; i++) { 102 memcpy(s->bytestream, ptr, n); 103 s->bytestream += n; 104 ptr += linesize; 105 } 106 } 107 return s->bytestream - s->bytestream_start; 108} 109 110 111AVCodec pam_encoder = { 112 "pam", 113 AVMEDIA_TYPE_VIDEO, 114 CODEC_ID_PAM, 115 sizeof(PNMContext), 116 ff_pnm_init, 117 pam_encode_frame, 118 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB32, PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, PIX_FMT_NONE}, 119 .long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), 120}; 121