Merge branch 'master' of http://repo.or.cz/r/FFMpeg-mirror
[FFMpeg-mirror/DVCPRO-HD.git] / libavcodec / pnmenc.c
blobb62ea759dffcf27a1c52ada31720108103f39fa4
1 /*
2 * PNM image format
3 * Copyright (c) 2002, 2003 Fabrice Bellard.
5 * This file is part of FFmpeg.
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.
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.
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
21 #include "avcodec.h"
22 #include "bytestream.h"
23 #include "pnm.h"
26 static av_cold int common_init(AVCodecContext *avctx){
27 PNMContext *s = avctx->priv_data;
29 avcodec_get_frame_defaults((AVFrame*)&s->picture);
30 avctx->coded_frame= (AVFrame*)&s->picture;
32 return 0;
35 static int pnm_decode_frame(AVCodecContext *avctx,
36 void *data, int *data_size,
37 const uint8_t *buf, int buf_size)
39 PNMContext * const s = avctx->priv_data;
40 AVFrame *picture = data;
41 AVFrame * const p= (AVFrame*)&s->picture;
42 int i, n, linesize, h, upgrade = 0;
43 unsigned char *ptr;
45 s->bytestream_start=
46 s->bytestream= buf;
47 s->bytestream_end= buf + buf_size;
49 if(ff_pnm_decode_header(avctx, s) < 0)
50 return -1;
52 if(p->data[0])
53 avctx->release_buffer(avctx, p);
55 p->reference= 0;
56 if(avctx->get_buffer(avctx, p) < 0){
57 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
58 return -1;
60 p->pict_type= FF_I_TYPE;
61 p->key_frame= 1;
63 switch(avctx->pix_fmt) {
64 default:
65 return -1;
66 case PIX_FMT_RGB24:
67 n = avctx->width * 3;
68 goto do_read;
69 case PIX_FMT_GRAY8:
70 n = avctx->width;
71 if (s->maxval < 255)
72 upgrade = 1;
73 goto do_read;
74 case PIX_FMT_GRAY16BE:
75 case PIX_FMT_GRAY16LE:
76 n = avctx->width * 2;
77 if (s->maxval < 65535)
78 upgrade = 2;
79 goto do_read;
80 case PIX_FMT_MONOWHITE:
81 case PIX_FMT_MONOBLACK:
82 n = (avctx->width + 7) >> 3;
83 do_read:
84 ptr = p->data[0];
85 linesize = p->linesize[0];
86 if(s->bytestream + n*avctx->height > s->bytestream_end)
87 return -1;
88 for(i = 0; i < avctx->height; i++) {
89 if (!upgrade)
90 memcpy(ptr, s->bytestream, n);
91 else if (upgrade == 1) {
92 unsigned int j, f = (255*128 + s->maxval/2) / s->maxval;
93 for (j=0; j<n; j++)
94 ptr[j] = (s->bytestream[j] * f + 64) >> 7;
95 } else if (upgrade == 2) {
96 unsigned int j, v, f = (65535*32768 + s->maxval/2) / s->maxval;
97 for (j=0; j<n/2; j++) {
98 v = be2me_16(((uint16_t *)s->bytestream)[j]);
99 ((uint16_t *)ptr)[j] = (v * f + 16384) >> 15;
102 s->bytestream += n;
103 ptr += linesize;
105 break;
106 case PIX_FMT_YUV420P:
108 unsigned char *ptr1, *ptr2;
110 n = avctx->width;
111 ptr = p->data[0];
112 linesize = p->linesize[0];
113 if(s->bytestream + n*avctx->height*3/2 > s->bytestream_end)
114 return -1;
115 for(i = 0; i < avctx->height; i++) {
116 memcpy(ptr, s->bytestream, n);
117 s->bytestream += n;
118 ptr += linesize;
120 ptr1 = p->data[1];
121 ptr2 = p->data[2];
122 n >>= 1;
123 h = avctx->height >> 1;
124 for(i = 0; i < h; i++) {
125 memcpy(ptr1, s->bytestream, n);
126 s->bytestream += n;
127 memcpy(ptr2, s->bytestream, n);
128 s->bytestream += n;
129 ptr1 += p->linesize[1];
130 ptr2 += p->linesize[2];
133 break;
134 case PIX_FMT_RGB32:
135 ptr = p->data[0];
136 linesize = p->linesize[0];
137 if(s->bytestream + avctx->width*avctx->height*4 > s->bytestream_end)
138 return -1;
139 for(i = 0; i < avctx->height; i++) {
140 int j, r, g, b, a;
142 for(j = 0;j < avctx->width; j++) {
143 r = *s->bytestream++;
144 g = *s->bytestream++;
145 b = *s->bytestream++;
146 a = *s->bytestream++;
147 ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
149 ptr += linesize;
151 break;
153 *picture= *(AVFrame*)&s->picture;
154 *data_size = sizeof(AVPicture);
156 return s->bytestream - s->bytestream_start;
159 static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
160 PNMContext *s = avctx->priv_data;
161 AVFrame *pict = data;
162 AVFrame * const p= (AVFrame*)&s->picture;
163 int i, h, h1, c, n, linesize;
164 uint8_t *ptr, *ptr1, *ptr2;
166 if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
167 av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
168 return -1;
171 *p = *pict;
172 p->pict_type= FF_I_TYPE;
173 p->key_frame= 1;
175 s->bytestream_start=
176 s->bytestream= outbuf;
177 s->bytestream_end= outbuf+buf_size;
179 h = avctx->height;
180 h1 = h;
181 switch(avctx->pix_fmt) {
182 case PIX_FMT_MONOWHITE:
183 c = '4';
184 n = (avctx->width + 7) >> 3;
185 break;
186 case PIX_FMT_GRAY8:
187 c = '5';
188 n = avctx->width;
189 break;
190 case PIX_FMT_GRAY16BE:
191 c = '5';
192 n = avctx->width * 2;
193 break;
194 case PIX_FMT_RGB24:
195 c = '6';
196 n = avctx->width * 3;
197 break;
198 case PIX_FMT_YUV420P:
199 c = '5';
200 n = avctx->width;
201 h1 = (h * 3) / 2;
202 break;
203 default:
204 return -1;
206 snprintf(s->bytestream, s->bytestream_end - s->bytestream,
207 "P%c\n%d %d\n",
208 c, avctx->width, h1);
209 s->bytestream += strlen(s->bytestream);
210 if (avctx->pix_fmt != PIX_FMT_MONOWHITE) {
211 snprintf(s->bytestream, s->bytestream_end - s->bytestream,
212 "%d\n", (avctx->pix_fmt != PIX_FMT_GRAY16BE) ? 255 : 65535);
213 s->bytestream += strlen(s->bytestream);
216 ptr = p->data[0];
217 linesize = p->linesize[0];
218 for(i=0;i<h;i++) {
219 memcpy(s->bytestream, ptr, n);
220 s->bytestream += n;
221 ptr += linesize;
224 if (avctx->pix_fmt == PIX_FMT_YUV420P) {
225 h >>= 1;
226 n >>= 1;
227 ptr1 = p->data[1];
228 ptr2 = p->data[2];
229 for(i=0;i<h;i++) {
230 memcpy(s->bytestream, ptr1, n);
231 s->bytestream += n;
232 memcpy(s->bytestream, ptr2, n);
233 s->bytestream += n;
234 ptr1 += p->linesize[1];
235 ptr2 += p->linesize[2];
238 return s->bytestream - s->bytestream_start;
241 static int pam_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
242 PNMContext *s = avctx->priv_data;
243 AVFrame *pict = data;
244 AVFrame * const p= (AVFrame*)&s->picture;
245 int i, h, w, n, linesize, depth, maxval;
246 const char *tuple_type;
247 uint8_t *ptr;
249 if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
250 av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
251 return -1;
254 *p = *pict;
255 p->pict_type= FF_I_TYPE;
256 p->key_frame= 1;
258 s->bytestream_start=
259 s->bytestream= outbuf;
260 s->bytestream_end= outbuf+buf_size;
262 h = avctx->height;
263 w = avctx->width;
264 switch(avctx->pix_fmt) {
265 case PIX_FMT_MONOWHITE:
266 n = (w + 7) >> 3;
267 depth = 1;
268 maxval = 1;
269 tuple_type = "BLACKANDWHITE";
270 break;
271 case PIX_FMT_GRAY8:
272 n = w;
273 depth = 1;
274 maxval = 255;
275 tuple_type = "GRAYSCALE";
276 break;
277 case PIX_FMT_RGB24:
278 n = w * 3;
279 depth = 3;
280 maxval = 255;
281 tuple_type = "RGB";
282 break;
283 case PIX_FMT_RGB32:
284 n = w * 4;
285 depth = 4;
286 maxval = 255;
287 tuple_type = "RGB_ALPHA";
288 break;
289 default:
290 return -1;
292 snprintf(s->bytestream, s->bytestream_end - s->bytestream,
293 "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLETYPE %s\nENDHDR\n",
294 w, h, depth, maxval, tuple_type);
295 s->bytestream += strlen(s->bytestream);
297 ptr = p->data[0];
298 linesize = p->linesize[0];
300 if (avctx->pix_fmt == PIX_FMT_RGB32) {
301 int j;
302 unsigned int v;
304 for(i=0;i<h;i++) {
305 for(j=0;j<w;j++) {
306 v = ((uint32_t *)ptr)[j];
307 bytestream_put_be24(&s->bytestream, v);
308 *s->bytestream++ = v >> 24;
310 ptr += linesize;
312 } else {
313 for(i=0;i<h;i++) {
314 memcpy(s->bytestream, ptr, n);
315 s->bytestream += n;
316 ptr += linesize;
319 return s->bytestream - s->bytestream_start;
322 #if 0
323 static int pnm_probe(AVProbeData *pd)
325 const char *p = pd->buf;
326 if (pd->buf_size >= 8 &&
327 p[0] == 'P' &&
328 p[1] >= '4' && p[1] <= '6' &&
329 pnm_space(p[2]) )
330 return AVPROBE_SCORE_MAX - 1; /* to permit pgmyuv probe */
331 else
332 return 0;
335 static int pgmyuv_probe(AVProbeData *pd)
337 if (match_ext(pd->filename, "pgmyuv"))
338 return AVPROBE_SCORE_MAX;
339 else
340 return 0;
343 static int pam_probe(AVProbeData *pd)
345 const char *p = pd->buf;
346 if (pd->buf_size >= 8 &&
347 p[0] == 'P' &&
348 p[1] == '7' &&
349 p[2] == '\n')
350 return AVPROBE_SCORE_MAX;
351 else
352 return 0;
354 #endif
357 #ifdef CONFIG_PGM_ENCODER
358 AVCodec pgm_encoder = {
359 "pgm",
360 CODEC_TYPE_VIDEO,
361 CODEC_ID_PGM,
362 sizeof(PNMContext),
363 common_init,
364 pnm_encode_frame,
365 NULL, //encode_end,
366 pnm_decode_frame,
367 .pix_fmts= (enum PixelFormat[]){PIX_FMT_GRAY8, PIX_FMT_GRAY16BE, PIX_FMT_NONE},
368 .long_name= NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"),
370 #endif // CONFIG_PGM_ENCODER
372 #ifdef CONFIG_PGMYUV_ENCODER
373 AVCodec pgmyuv_encoder = {
374 "pgmyuv",
375 CODEC_TYPE_VIDEO,
376 CODEC_ID_PGMYUV,
377 sizeof(PNMContext),
378 common_init,
379 pnm_encode_frame,
380 NULL, //encode_end,
381 pnm_decode_frame,
382 .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
383 .long_name= NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"),
385 #endif // CONFIG_PGMYUV_ENCODER
387 #ifdef CONFIG_PPM_ENCODER
388 AVCodec ppm_encoder = {
389 "ppm",
390 CODEC_TYPE_VIDEO,
391 CODEC_ID_PPM,
392 sizeof(PNMContext),
393 common_init,
394 pnm_encode_frame,
395 NULL, //encode_end,
396 pnm_decode_frame,
397 .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_NONE},
398 .long_name= NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"),
400 #endif // CONFIG_PPM_ENCODER
402 #ifdef CONFIG_PBM_ENCODER
403 AVCodec pbm_encoder = {
404 "pbm",
405 CODEC_TYPE_VIDEO,
406 CODEC_ID_PBM,
407 sizeof(PNMContext),
408 common_init,
409 pnm_encode_frame,
410 NULL, //encode_end,
411 pnm_decode_frame,
412 .pix_fmts= (enum PixelFormat[]){PIX_FMT_MONOWHITE, PIX_FMT_NONE},
413 .long_name= NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"),
415 #endif // CONFIG_PBM_ENCODER
417 #ifdef CONFIG_PAM_ENCODER
418 AVCodec pam_encoder = {
419 "pam",
420 CODEC_TYPE_VIDEO,
421 CODEC_ID_PAM,
422 sizeof(PNMContext),
423 common_init,
424 pam_encode_frame,
425 NULL, //encode_end,
426 pnm_decode_frame,
427 .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB32, PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, PIX_FMT_NONE},
428 .long_name= NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"),
430 #endif // CONFIG_PAM_ENCODER