2 * Sun Rasterfile (.sun/.ras/im{1,8,24}/.sunras) image encoder
3 * Copyright (c) 2012 Aneesh Dogra (lionaneesh) <lionaneesh@gmail.com>
5 * This file is part of Libav.
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.
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.
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
23 #include "bytestream.h"
27 typedef struct SUNRASTContext
{
30 int depth
; ///< depth of pixel
31 int length
; ///< length (bytes) of image
32 int type
; ///< type of file
33 int maptype
; ///< type of colormap
34 int maplength
; ///< length (bytes) of colormap
38 static void sunrast_image_write_header(AVCodecContext
*avctx
)
40 SUNRASTContext
*s
= avctx
->priv_data
;
42 bytestream2_put_be32u(&s
->p
, RAS_MAGIC
);
43 bytestream2_put_be32u(&s
->p
, avctx
->width
);
44 bytestream2_put_be32u(&s
->p
, avctx
->height
);
45 bytestream2_put_be32u(&s
->p
, s
->depth
);
46 bytestream2_put_be32u(&s
->p
, s
->length
);
47 bytestream2_put_be32u(&s
->p
, s
->type
);
48 bytestream2_put_be32u(&s
->p
, s
->maptype
);
49 bytestream2_put_be32u(&s
->p
, s
->maplength
);
52 static void sunrast_image_write_image(AVCodecContext
*avctx
,
53 const uint8_t *pixels
,
54 const uint32_t *palette_data
,
57 SUNRASTContext
*s
= avctx
->priv_data
;
61 if (s
->maplength
) { // palettized
62 PutByteContext pb_r
, pb_g
;
63 int len
= s
->maplength
/ 3;
66 bytestream2_skip_p(&s
->p
, len
);
68 bytestream2_skip_p(&s
->p
, len
);
70 for (x
= 0; x
< len
; x
++) {
71 uint32_t pixel
= palette_data
[x
];
73 bytestream2_put_byteu(&pb_r
, (pixel
>> 16) & 0xFF);
74 bytestream2_put_byteu(&pb_g
, (pixel
>> 8) & 0xFF);
75 bytestream2_put_byteu(&s
->p
, pixel
& 0xFF);
79 len
= (s
->depth
* avctx
->width
+ 7) >> 3;
80 alen
= len
+ (len
& 1);
83 if (s
->type
== RT_BYTE_ENCODED
) {
84 uint8_t value
, value2
;
86 const uint8_t *start
= linesize
< 0 ? pixels
+ (avctx
->height
- 1) * linesize
88 const uint8_t *end
= linesize
< 0 ? pixels
- linesize
89 : pixels
+ avctx
->height
* linesize
;
93 #define GET_VALUE ptr >= end || ptr < start ? 0 : x >= len ? ptr[len-1] : ptr[x]
97 while (ptr
< end
&& ptr
>= start
) {
107 while (value2
== value
&& run
< 256 && ptr
< end
&& ptr
>= start
) {
117 if (run
> 2 || value
== RLE_TRIGGER
) {
118 bytestream2_put_byteu(&s
->p
, RLE_TRIGGER
);
119 bytestream2_put_byteu(&s
->p
, run
- 1);
121 bytestream2_put_byteu(&s
->p
, value
);
122 } else if (run
== 1) {
123 bytestream2_put_byteu(&s
->p
, value
);
125 bytestream2_put_be16u(&s
->p
, (value
<< 8) | value
);
128 // update data length for header
129 s
->length
= bytestream2_tell_p(&s
->p
) - 32 - s
->maplength
;
132 for (y
= 0; y
< avctx
->height
; y
++) {
133 bytestream2_put_buffer(&s
->p
, ptr
, len
);
135 bytestream2_put_byteu(&s
->p
, 0);
141 static av_cold
int sunrast_encode_init(AVCodecContext
*avctx
)
143 SUNRASTContext
*s
= avctx
->priv_data
;
145 switch (avctx
->coder_type
) {
146 case FF_CODER_TYPE_RLE
:
147 s
->type
= RT_BYTE_ENCODED
;
149 case FF_CODER_TYPE_RAW
:
150 s
->type
= RT_STANDARD
;
153 av_log(avctx
, AV_LOG_ERROR
, "invalid coder_type\n");
154 return AVERROR(EINVAL
);
157 avctx
->coded_frame
= &s
->picture
;
158 avctx
->coded_frame
->key_frame
= 1;
159 avctx
->coded_frame
->pict_type
= AV_PICTURE_TYPE_I
;
160 s
->maptype
= RMT_NONE
;
163 switch (avctx
->pix_fmt
) {
164 case AV_PIX_FMT_MONOWHITE
:
167 case AV_PIX_FMT_PAL8
:
168 s
->maptype
= RMT_EQUAL_RGB
;
169 s
->maplength
= 3 * 256;
170 case AV_PIX_FMT_GRAY8
:
173 case AV_PIX_FMT_BGR24
:
179 s
->length
= avctx
->height
* (FFALIGN(avctx
->width
* s
->depth
, 16) >> 3);
180 s
->size
= 32 + s
->maplength
+
181 s
->length
* (s
->type
== RT_BYTE_ENCODED
? 2 : 1);
186 static int sunrast_encode_frame(AVCodecContext
*avctx
, AVPacket
*avpkt
,
187 const AVFrame
*frame
, int *got_packet_ptr
)
189 SUNRASTContext
*s
= avctx
->priv_data
;
192 if ((ret
= ff_alloc_packet(avpkt
, s
->size
)) < 0)
195 bytestream2_init_writer(&s
->p
, avpkt
->data
, avpkt
->size
);
196 sunrast_image_write_header(avctx
);
197 sunrast_image_write_image(avctx
, frame
->data
[0],
198 (const uint32_t *)frame
->data
[1],
200 // update data length in header after RLE
201 if (s
->type
== RT_BYTE_ENCODED
)
202 AV_WB32(&avpkt
->data
[16], s
->length
);
205 avpkt
->flags
|= AV_PKT_FLAG_KEY
;
206 avpkt
->size
= bytestream2_tell_p(&s
->p
);
210 static const AVCodecDefault sunrast_defaults
[] = {
215 AVCodec ff_sunrast_encoder
= {
217 .type
= AVMEDIA_TYPE_VIDEO
,
218 .id
= AV_CODEC_ID_SUNRAST
,
219 .priv_data_size
= sizeof(SUNRASTContext
),
220 .init
= sunrast_encode_init
,
221 .encode2
= sunrast_encode_frame
,
222 .defaults
= sunrast_defaults
,
223 .pix_fmts
= (const enum AVPixelFormat
[]){ AV_PIX_FMT_BGR24
,
226 AV_PIX_FMT_MONOWHITE
,
228 .long_name
= NULL_IF_CONFIG_SMALL("Sun Rasterfile image"),