Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavcodec
sunrast.c
Go to the documentation of this file.
1
/*
2
* Sun Rasterfile (.sun/.ras/im{1,8,24}/.sunras) image decoder
3
* Copyright (c) 2007, 2008 Ivo van Poorten
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/common.h
"
23
#include "
libavutil/intreadwrite.h
"
24
#include "
libavutil/imgutils.h
"
25
#include "
avcodec.h
"
26
#include "
internal.h
"
27
#include "
sunrast.h
"
28
29
typedef
struct
SUNRASTContext
{
30
AVFrame
picture
;
31
}
SUNRASTContext
;
32
33
static
av_cold
int
sunrast_init
(
AVCodecContext
*avctx) {
34
SUNRASTContext
*s = avctx->
priv_data
;
35
36
avcodec_get_frame_defaults
(&s->
picture
);
37
avctx->
coded_frame
= &s->
picture
;
38
39
return
0;
40
}
41
42
static
int
sunrast_decode_frame
(
AVCodecContext
*avctx,
void
*
data
,
43
int
*got_frame,
AVPacket
*avpkt)
44
{
45
const
uint8_t
*buf = avpkt->
data
;
46
const
uint8_t
*buf_end = avpkt->
data
+ avpkt->
size
;
47
SUNRASTContext
*
const
s = avctx->
priv_data
;
48
AVFrame
*
picture
=
data
;
49
AVFrame
*
const
p = &s->
picture
;
50
unsigned
int
w, h, depth, type, maptype, maplength,
stride
, x, y,
len
, alen;
51
uint8_t
*ptr;
52
const
uint8_t
*bufstart = buf;
53
int
ret;
54
55
if
(avpkt->
size
< 32)
56
return
AVERROR_INVALIDDATA
;
57
58
if
(
AV_RB32
(buf) !=
RAS_MAGIC
) {
59
av_log
(avctx,
AV_LOG_ERROR
,
"this is not sunras encoded data\n"
);
60
return
AVERROR_INVALIDDATA
;
61
}
62
63
w =
AV_RB32
(buf + 4);
64
h =
AV_RB32
(buf + 8);
65
depth =
AV_RB32
(buf + 12);
66
type =
AV_RB32
(buf + 20);
67
maptype =
AV_RB32
(buf + 24);
68
maplength =
AV_RB32
(buf + 28);
69
buf += 32;
70
71
if
(type ==
RT_FORMAT_TIFF
|| type ==
RT_FORMAT_IFF
|| type ==
RT_EXPERIMENTAL
) {
72
av_log_ask_for_sample
(avctx,
"unsupported (compression) type\n"
);
73
return
AVERROR_PATCHWELCOME
;
74
}
75
if
(type >
RT_FORMAT_IFF
) {
76
av_log
(avctx,
AV_LOG_ERROR
,
"invalid (compression) type\n"
);
77
return
AVERROR_INVALIDDATA
;
78
}
79
if
(
av_image_check_size
(w, h, 0, avctx)) {
80
av_log
(avctx,
AV_LOG_ERROR
,
"invalid image size\n"
);
81
return
AVERROR_INVALIDDATA
;
82
}
83
if
(maptype ==
RMT_RAW
) {
84
av_log_ask_for_sample
(avctx,
"unsupported colormap type\n"
);
85
return
AVERROR_PATCHWELCOME
;
86
}
87
if
(maptype >
RMT_RAW
) {
88
av_log
(avctx,
AV_LOG_ERROR
,
"invalid colormap type\n"
);
89
return
AVERROR_INVALIDDATA
;
90
}
91
92
93
switch
(depth) {
94
case
1:
95
avctx->
pix_fmt
=
AV_PIX_FMT_MONOWHITE
;
96
break
;
97
case
8:
98
avctx->
pix_fmt
= maplength ?
AV_PIX_FMT_PAL8
:
AV_PIX_FMT_GRAY8
;
99
break
;
100
case
24:
101
avctx->
pix_fmt
= (type ==
RT_FORMAT_RGB
) ?
AV_PIX_FMT_RGB24
:
AV_PIX_FMT_BGR24
;
102
break
;
103
default
:
104
av_log
(avctx,
AV_LOG_ERROR
,
"invalid depth\n"
);
105
return
AVERROR_INVALIDDATA
;
106
}
107
108
if
(p->
data
[0])
109
avctx->
release_buffer
(avctx, p);
110
111
if
(w != avctx->
width
|| h != avctx->
height
)
112
avcodec_set_dimensions
(avctx, w, h);
113
if
((ret =
ff_get_buffer
(avctx, p)) < 0) {
114
av_log
(avctx,
AV_LOG_ERROR
,
"get_buffer() failed\n"
);
115
return
ret;
116
}
117
118
p->
pict_type
=
AV_PICTURE_TYPE_I
;
119
120
if
(buf_end - buf < maplength)
121
return
AVERROR_INVALIDDATA
;
122
123
if
(depth != 8 && maplength) {
124
av_log
(avctx,
AV_LOG_WARNING
,
"useless colormap found or file is corrupted, trying to recover\n"
);
125
126
}
else
if
(maplength) {
127
unsigned
int
len = maplength / 3;
128
129
if
(maplength % 3 || maplength > 768) {
130
av_log
(avctx,
AV_LOG_WARNING
,
"invalid colormap length\n"
);
131
return
AVERROR_INVALIDDATA
;
132
}
133
134
ptr = p->
data
[1];
135
for
(x = 0; x <
len
; x++, ptr += 4)
136
*(uint32_t *)ptr = (buf[x] << 16) + (buf[len + x] << 8) + buf[len + len + x];
137
}
138
139
buf += maplength;
140
141
ptr = p->
data
[0];
142
stride = p->
linesize
[0];
143
144
/* scanlines are aligned on 16 bit boundaries */
145
len = (depth * w + 7) >> 3;
146
alen = len + (len & 1);
147
148
if
(type ==
RT_BYTE_ENCODED
) {
149
int
value,
run
;
150
uint8_t
*end = ptr + h *
stride
;
151
152
x = 0;
153
while
(ptr != end && buf < buf_end) {
154
run = 1;
155
if
(buf_end - buf < 1)
156
return
AVERROR_INVALIDDATA
;
157
158
if
((value = *buf++) ==
RLE_TRIGGER
) {
159
run = *buf++ + 1;
160
if
(run != 1)
161
value = *buf++;
162
}
163
while
(run--) {
164
if
(x < len)
165
ptr[x] = value;
166
if
(++x >= alen) {
167
x = 0;
168
ptr +=
stride
;
169
if
(ptr == end)
170
break
;
171
}
172
}
173
}
174
}
else
{
175
for
(y = 0; y < h; y++) {
176
if
(buf_end - buf < len)
177
break
;
178
memcpy(ptr, buf, len);
179
ptr +=
stride
;
180
buf += alen;
181
}
182
}
183
184
*picture = s->
picture
;
185
*got_frame = 1;
186
187
return
buf - bufstart;
188
}
189
190
static
av_cold
int
sunrast_end
(
AVCodecContext
*avctx) {
191
SUNRASTContext
*s = avctx->
priv_data
;
192
193
if
(s->
picture
.
data
[0])
194
avctx->
release_buffer
(avctx, &s->
picture
);
195
196
return
0;
197
}
198
199
AVCodec
ff_sunrast_decoder
= {
200
.
name
=
"sunrast"
,
201
.type =
AVMEDIA_TYPE_VIDEO
,
202
.id =
AV_CODEC_ID_SUNRAST
,
203
.priv_data_size =
sizeof
(
SUNRASTContext
),
204
.
init
=
sunrast_init
,
205
.
close
=
sunrast_end
,
206
.
decode
=
sunrast_decode_frame
,
207
.capabilities =
CODEC_CAP_DR1
,
208
.long_name =
NULL_IF_CONFIG_SMALL
(
"Sun Rasterfile image"
),
209
};