Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavcodec
pnm.c
Go to the documentation of this file.
1
/*
2
* PNM image format
3
* Copyright (c) 2002, 2003 Fabrice Bellard
4
*
5
* This file is part of Libav.
6
*
7
* Libav 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
* Libav 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 Libav; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
22
#include "
libavutil/imgutils.h
"
23
#include "
avcodec.h
"
24
#include "
pnm.h
"
25
26
static
inline
int
pnm_space
(
int
c)
27
{
28
return
c ==
' '
|| c ==
'\n'
|| c ==
'\r'
|| c ==
'\t'
;
29
}
30
31
static
void
pnm_get
(
PNMContext
*sc,
char
*str,
int
buf_size)
32
{
33
char
*s;
34
int
c;
35
36
/* skip spaces and comments */
37
for
(;;) {
38
c = *sc->
bytestream
++;
39
if
(c ==
'#'
) {
40
do
{
41
c = *sc->
bytestream
++;
42
}
while
(c !=
'\n'
&& sc->
bytestream
< sc->
bytestream_end
);
43
}
else
if
(!
pnm_space
(c)) {
44
break
;
45
}
46
}
47
48
s = str;
49
while
(sc->
bytestream
< sc->
bytestream_end
&& !
pnm_space
(c)) {
50
if
((s - str) < buf_size - 1)
51
*s++ = c;
52
c = *sc->
bytestream
++;
53
}
54
*s =
'\0'
;
55
}
56
57
int
ff_pnm_decode_header
(
AVCodecContext
*avctx,
PNMContext
*
const
s)
58
{
59
char
buf1[32], tuple_type[32];
60
int
h, w,
depth
, maxval;
61
62
pnm_get
(s, buf1,
sizeof
(buf1));
63
s->
type
= buf1[1]-
'0'
;
64
if
(buf1[0] !=
'P'
)
65
return
-1;
66
67
if
(s->
type
==1 || s->
type
==4) {
68
avctx->
pix_fmt
=
PIX_FMT_MONOWHITE
;
69
}
else
if
(s->
type
==2 || s->
type
==5) {
70
if
(avctx->
codec_id
==
CODEC_ID_PGMYUV
)
71
avctx->
pix_fmt
=
PIX_FMT_YUV420P
;
72
else
73
avctx->
pix_fmt
=
PIX_FMT_GRAY8
;
74
}
else
if
(s->
type
==3 || s->
type
==6) {
75
avctx->
pix_fmt
=
PIX_FMT_RGB24
;
76
}
else
if
(s->
type
==7) {
77
w = -1;
78
h = -1;
79
maxval = -1;
80
depth = -1;
81
tuple_type[0] =
'\0'
;
82
for
(;;) {
83
pnm_get
(s, buf1,
sizeof
(buf1));
84
if
(!strcmp(buf1,
"WIDTH"
)) {
85
pnm_get
(s, buf1,
sizeof
(buf1));
86
w = strtol(buf1,
NULL
, 10);
87
}
else
if
(!strcmp(buf1,
"HEIGHT"
)) {
88
pnm_get
(s, buf1,
sizeof
(buf1));
89
h = strtol(buf1,
NULL
, 10);
90
}
else
if
(!strcmp(buf1,
"DEPTH"
)) {
91
pnm_get
(s, buf1,
sizeof
(buf1));
92
depth = strtol(buf1,
NULL
, 10);
93
}
else
if
(!strcmp(buf1,
"MAXVAL"
)) {
94
pnm_get
(s, buf1,
sizeof
(buf1));
95
maxval = strtol(buf1,
NULL
, 10);
96
}
else
if
(!strcmp(buf1,
"TUPLETYPE"
)) {
97
pnm_get
(s, tuple_type,
sizeof
(tuple_type));
98
}
else
if
(!strcmp(buf1,
"ENDHDR"
)) {
99
break
;
100
}
else
{
101
return
-1;
102
}
103
}
104
/* check that all tags are present */
105
if
(w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] ==
'\0'
||
av_image_check_size
(w, h, 0, avctx))
106
return
-1;
107
108
avctx->
width
= w;
109
avctx->
height
= h;
110
if
(depth == 1) {
111
if
(maxval == 1)
112
avctx->
pix_fmt
=
PIX_FMT_MONOWHITE
;
113
else
114
avctx->
pix_fmt
=
PIX_FMT_GRAY8
;
115
}
else
if
(depth == 3) {
116
if
(maxval < 256) {
117
avctx->
pix_fmt
=
PIX_FMT_RGB24
;
118
}
else
{
119
av_log
(avctx,
AV_LOG_ERROR
,
"16-bit components are only supported for grayscale\n"
);
120
avctx->
pix_fmt
=
PIX_FMT_NONE
;
121
return
-1;
122
}
123
}
else
if
(depth == 4) {
124
avctx->
pix_fmt
=
PIX_FMT_RGB32
;
125
}
else
{
126
return
-1;
127
}
128
return
0;
129
}
else
{
130
return
-1;
131
}
132
pnm_get
(s, buf1,
sizeof
(buf1));
133
avctx->
width
= atoi(buf1);
134
if
(avctx->
width
<= 0)
135
return
-1;
136
pnm_get
(s, buf1,
sizeof
(buf1));
137
avctx->
height
= atoi(buf1);
138
if
(
av_image_check_size
(avctx->
width
, avctx->
height
, 0, avctx))
139
return
-1;
140
if
(avctx->
pix_fmt
!=
PIX_FMT_MONOWHITE
) {
141
pnm_get
(s, buf1,
sizeof
(buf1));
142
s->
maxval
= atoi(buf1);
143
if
(s->
maxval
<= 0) {
144
av_log
(avctx,
AV_LOG_ERROR
,
"Invalid maxval: %d\n"
, s->
maxval
);
145
s->
maxval
= 255;
146
}
147
if
(s->
maxval
>= 256) {
148
if
(avctx->
pix_fmt
==
PIX_FMT_GRAY8
) {
149
avctx->
pix_fmt
=
PIX_FMT_GRAY16BE
;
150
if
(s->
maxval
!= 65535)
151
avctx->
pix_fmt
=
PIX_FMT_GRAY16
;
152
}
else
if
(avctx->
pix_fmt
==
PIX_FMT_RGB24
) {
153
if
(s->
maxval
> 255)
154
avctx->
pix_fmt
=
PIX_FMT_RGB48BE
;
155
}
else
{
156
av_log
(avctx,
AV_LOG_ERROR
,
"Unsupported pixel format\n"
);
157
avctx->
pix_fmt
=
PIX_FMT_NONE
;
158
return
-1;
159
}
160
}
161
}
else
162
s->
maxval
=1;
163
/* more check if YUV420 */
164
if
(avctx->
pix_fmt
==
PIX_FMT_YUV420P
) {
165
if
((avctx->
width
& 1) != 0)
166
return
-1;
167
h = (avctx->
height
* 2);
168
if
((h % 3) != 0)
169
return
-1;
170
h /= 3;
171
avctx->
height
= h;
172
}
173
return
0;
174
}
175
176
av_cold
int
ff_pnm_end
(
AVCodecContext
*avctx)
177
{
178
PNMContext
*s = avctx->
priv_data
;
179
180
if
(s->
picture
.
data
[0])
181
avctx->
release_buffer
(avctx, &s->
picture
);
182
183
return
0;
184
}
185
186
av_cold
int
ff_pnm_init
(
AVCodecContext
*avctx)
187
{
188
PNMContext
*s = avctx->
priv_data
;
189
190
avcodec_get_frame_defaults
((
AVFrame
*)&s->
picture
);
191
avctx->
coded_frame
= (
AVFrame
*)&s->
picture
;
192
193
return
0;
194
}