Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavcodec
pnmdec.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 "
avcodec.h
"
23
#include "
bytestream.h
"
24
#include "
put_bits.h
"
25
#include "
pnm.h
"
26
27
28
static
int
pnm_decode_frame
(
AVCodecContext
*avctx,
void
*
data
,
29
int
*data_size,
AVPacket
*avpkt)
30
{
31
const
uint8_t *buf = avpkt->
data
;
32
int
buf_size = avpkt->
size
;
33
PNMContext
*
const
s = avctx->
priv_data
;
34
AVFrame
*
picture
=
data
;
35
AVFrame
*
const
p = (
AVFrame
*)&s->
picture
;
36
int
i, j, n, linesize, h, upgrade = 0;
37
unsigned
char
*ptr;
38
int
components, sample_len;
39
40
s->
bytestream_start
=
41
s->
bytestream
= buf;
42
s->
bytestream_end
= buf + buf_size;
43
44
if (
ff_pnm_decode_header
(avctx, s) < 0)
45
return
-1;
46
47
if
(p->
data
[0])
48
avctx->
release_buffer
(avctx, p);
49
50
p->
reference
= 0;
51
if
(avctx->
get_buffer
(avctx, p) < 0) {
52
av_log
(avctx,
AV_LOG_ERROR
,
"get_buffer() failed\n"
);
53
return
-1;
54
}
55
p->
pict_type
=
AV_PICTURE_TYPE_I
;
56
p->
key_frame
= 1;
57
58
switch
(avctx->
pix_fmt
) {
59
default
:
60
return
-1;
61
case
PIX_FMT_RGB48BE
:
62
n = avctx->
width
* 6;
63
components=3;
64
sample_len=16;
65
goto
do_read;
66
case
PIX_FMT_RGB24
:
67
n = avctx->
width
* 3;
68
components=3;
69
sample_len=8;
70
goto
do_read;
71
case
PIX_FMT_GRAY8
:
72
n = avctx->
width
;
73
components=1;
74
sample_len=8;
75
if
(s->
maxval
< 255)
76
upgrade = 1;
77
goto
do_read;
78
case
PIX_FMT_GRAY16BE
:
79
case
PIX_FMT_GRAY16LE
:
80
n = avctx->
width
* 2;
81
components=1;
82
sample_len=16;
83
if
(s->
maxval
< 65535)
84
upgrade = 2;
85
goto
do_read;
86
case
PIX_FMT_MONOWHITE
:
87
case
PIX_FMT_MONOBLACK
:
88
n = (avctx->
width
+ 7) >> 3;
89
components=1;
90
sample_len=1;
91
do_read:
92
ptr = p->
data
[0];
93
linesize = p->
linesize
[0];
94
if
(s->
bytestream
+ n * avctx->
height
> s->
bytestream_end
)
95
return
-1;
96
if
(s->
type
< 4){
97
for
(i=0; i<avctx->
height
; i++) {
98
PutBitContext
pb;
99
init_put_bits
(&pb, ptr, linesize);
100
for
(j=0; j<avctx->
width
* components; j++){
101
unsigned
int
c=0;
102
int
v
=0;
103
while
(s->
bytestream
< s->
bytestream_end
&& (*s->
bytestream
<
'0'
|| *s->
bytestream
>
'9'
))
104
s->
bytestream
++;
105
if
(s->
bytestream
>= s->
bytestream_end
)
106
return
-1;
107
do
{
108
v= 10*v + c;
109
c= (*s->
bytestream
++) -
'0'
;
110
}
while
(c <= 9);
111
put_bits
(&pb, sample_len, (((1<<sample_len)-1)*v + (s->
maxval
>>1))/s->
maxval
);
112
}
113
flush_put_bits
(&pb);
114
ptr+= linesize;
115
}
116
}
else
{
117
for
(i = 0; i < avctx->
height
; i++) {
118
if
(!upgrade)
119
memcpy(ptr, s->
bytestream
, n);
120
else
if
(upgrade == 1) {
121
unsigned
int
j,
f
= (255 * 128 + s->
maxval
/ 2) / s->
maxval
;
122
for
(j = 0; j < n; j++)
123
ptr[j] = (s->
bytestream
[j] * f + 64) >> 7;
124
}
else
if
(upgrade == 2) {
125
unsigned
int
j,
v
,
f
= (65535 * 32768 + s->
maxval
/ 2) / s->
maxval
;
126
for
(j = 0; j < n / 2; j++) {
127
v =
av_be2ne16
(((uint16_t *)s->
bytestream
)[j]);
128
((uint16_t *)ptr)[j] = (v * f + 16384) >> 15;
129
}
130
}
131
s->
bytestream
+= n;
132
ptr += linesize;
133
}
134
}
135
break
;
136
case
PIX_FMT_YUV420P
:
137
{
138
unsigned
char
*ptr1, *ptr2;
139
140
n = avctx->
width
;
141
ptr = p->
data
[0];
142
linesize = p->
linesize
[0];
143
if
(s->
bytestream
+ n * avctx->
height
* 3 / 2 > s->
bytestream_end
)
144
return
-1;
145
for
(i = 0; i < avctx->
height
; i++) {
146
memcpy(ptr, s->
bytestream
, n);
147
s->
bytestream
+= n;
148
ptr += linesize;
149
}
150
ptr1 = p->
data
[1];
151
ptr2 = p->
data
[2];
152
n >>= 1;
153
h = avctx->
height
>> 1;
154
for
(i = 0; i < h; i++) {
155
memcpy(ptr1, s->
bytestream
, n);
156
s->
bytestream
+= n;
157
memcpy(ptr2, s->
bytestream
, n);
158
s->
bytestream
+= n;
159
ptr1 += p->
linesize
[1];
160
ptr2 += p->
linesize
[2];
161
}
162
}
163
break
;
164
case
PIX_FMT_RGB32
:
165
ptr = p->
data
[0];
166
linesize = p->
linesize
[0];
167
if
(s->
bytestream
+ avctx->
width
* avctx->
height
* 4 > s->
bytestream_end
)
168
return
-1;
169
for
(i = 0; i < avctx->
height
; i++) {
170
int
j,
r
,
g
,
b
, a;
171
172
for
(j = 0; j < avctx->
width
; j++) {
173
r = *s->
bytestream
++;
174
g = *s->
bytestream
++;
175
b = *s->
bytestream
++;
176
a = *s->
bytestream
++;
177
((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
178
}
179
ptr += linesize;
180
}
181
break
;
182
}
183
*picture = *(
AVFrame
*)&s->
picture
;
184
*data_size =
sizeof
(
AVPicture
);
185
186
return
s->
bytestream
- s->
bytestream_start
;
187
}
188
189
190
#if CONFIG_PGM_DECODER
191
AVCodec
ff_pgm_decoder = {
192
.
name
=
"pgm"
,
193
.type =
AVMEDIA_TYPE_VIDEO
,
194
.id =
CODEC_ID_PGM
,
195
.priv_data_size =
sizeof
(
PNMContext
),
196
.
init
=
ff_pnm_init
,
197
.
close
=
ff_pnm_end
,
198
.
decode
=
pnm_decode_frame
,
199
.capabilities =
CODEC_CAP_DR1
,
200
.pix_fmts = (
const
enum
PixelFormat
[]){
PIX_FMT_GRAY8
,
PIX_FMT_GRAY16BE
,
PIX_FMT_NONE
},
201
.long_name =
NULL_IF_CONFIG_SMALL
(
"PGM (Portable GrayMap) image"
),
202
};
203
#endif
204
205
#if CONFIG_PGMYUV_DECODER
206
AVCodec
ff_pgmyuv_decoder = {
207
.
name
=
"pgmyuv"
,
208
.type =
AVMEDIA_TYPE_VIDEO
,
209
.id =
CODEC_ID_PGMYUV
,
210
.priv_data_size =
sizeof
(
PNMContext
),
211
.
init
=
ff_pnm_init
,
212
.
close
=
ff_pnm_end
,
213
.
decode
=
pnm_decode_frame
,
214
.capabilities =
CODEC_CAP_DR1
,
215
.pix_fmts = (
const
enum
PixelFormat
[]){
PIX_FMT_YUV420P
,
PIX_FMT_NONE
},
216
.long_name =
NULL_IF_CONFIG_SMALL
(
"PGMYUV (Portable GrayMap YUV) image"
),
217
};
218
#endif
219
220
#if CONFIG_PPM_DECODER
221
AVCodec
ff_ppm_decoder = {
222
.
name
=
"ppm"
,
223
.type =
AVMEDIA_TYPE_VIDEO
,
224
.id =
CODEC_ID_PPM
,
225
.priv_data_size =
sizeof
(
PNMContext
),
226
.
init
=
ff_pnm_init
,
227
.
close
=
ff_pnm_end
,
228
.
decode
=
pnm_decode_frame
,
229
.capabilities =
CODEC_CAP_DR1
,
230
.pix_fmts = (
const
enum
PixelFormat
[]){
PIX_FMT_RGB24
,
PIX_FMT_RGB48BE
,
PIX_FMT_NONE
},
231
.long_name =
NULL_IF_CONFIG_SMALL
(
"PPM (Portable PixelMap) image"
),
232
};
233
#endif
234
235
#if CONFIG_PBM_DECODER
236
AVCodec
ff_pbm_decoder = {
237
.
name
=
"pbm"
,
238
.type =
AVMEDIA_TYPE_VIDEO
,
239
.id =
CODEC_ID_PBM
,
240
.priv_data_size =
sizeof
(
PNMContext
),
241
.
init
=
ff_pnm_init
,
242
.
close
=
ff_pnm_end
,
243
.
decode
=
pnm_decode_frame
,
244
.capabilities =
CODEC_CAP_DR1
,
245
.pix_fmts = (
const
enum
PixelFormat
[]){
PIX_FMT_MONOWHITE
,
PIX_FMT_NONE
},
246
.long_name =
NULL_IF_CONFIG_SMALL
(
"PBM (Portable BitMap) image"
),
247
};
248
#endif
249
250
#if CONFIG_PAM_DECODER
251
AVCodec
ff_pam_decoder = {
252
.
name
=
"pam"
,
253
.type =
AVMEDIA_TYPE_VIDEO
,
254
.id =
CODEC_ID_PAM
,
255
.priv_data_size =
sizeof
(
PNMContext
),
256
.
init
=
ff_pnm_init
,
257
.
close
=
ff_pnm_end
,
258
.
decode
=
pnm_decode_frame
,
259
.capabilities =
CODEC_CAP_DR1
,
260
.pix_fmts = (
const
enum
PixelFormat
[]){
PIX_FMT_RGB24
,
PIX_FMT_RGB32
,
PIX_FMT_GRAY8
,
PIX_FMT_MONOWHITE
,
PIX_FMT_NONE
},
261
.long_name =
NULL_IF_CONFIG_SMALL
(
"PAM (Portable AnyMap) image"
),
262
};
263
#endif