Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * XWD image format | |
3 | * | |
4 | * Copyright (c) 2012 Paul B Mahol | |
5 | * | |
6 | * This file is part of FFmpeg. | |
7 | * | |
8 | * FFmpeg is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License as published by the Free Software Foundation; either | |
11 | * version 2.1 of the License, or (at your option) any later version. | |
12 | * | |
13 | * FFmpeg is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * Lesser General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU Lesser General Public | |
19 | * License along with FFmpeg; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
21 | */ | |
22 | ||
23 | #include "libavutil/intreadwrite.h" | |
24 | #include "libavutil/pixdesc.h" | |
25 | #include "avcodec.h" | |
26 | #include "bytestream.h" | |
27 | #include "internal.h" | |
28 | #include "xwd.h" | |
29 | ||
30 | #define WINDOW_NAME "lavcxwdenc" | |
31 | #define WINDOW_NAME_SIZE 11 | |
32 | ||
33 | static int xwd_encode_frame(AVCodecContext *avctx, AVPacket *pkt, | |
34 | const AVFrame *pict, int *got_packet) | |
35 | { | |
36 | enum AVPixelFormat pix_fmt = avctx->pix_fmt; | |
37 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); | |
38 | uint32_t pixdepth, bpp, bpad, ncolors = 0, lsize, vclass, be = 0; | |
39 | uint32_t rgb[3] = { 0 }, bitorder = 0; | |
40 | uint32_t header_size; | |
41 | int i, out_size, ret; | |
42 | uint8_t *ptr, *buf; | |
43 | AVFrame * const p = (AVFrame *)pict; | |
44 | ||
45 | pixdepth = av_get_bits_per_pixel(desc); | |
46 | if (desc->flags & AV_PIX_FMT_FLAG_BE) | |
47 | be = 1; | |
48 | switch (pix_fmt) { | |
49 | case AV_PIX_FMT_ARGB: | |
50 | case AV_PIX_FMT_BGRA: | |
51 | case AV_PIX_FMT_RGBA: | |
52 | case AV_PIX_FMT_ABGR: | |
53 | if (pix_fmt == AV_PIX_FMT_ARGB || | |
54 | pix_fmt == AV_PIX_FMT_ABGR) | |
55 | be = 1; | |
56 | if (pix_fmt == AV_PIX_FMT_ABGR || | |
57 | pix_fmt == AV_PIX_FMT_RGBA) { | |
58 | rgb[0] = 0xFF; | |
59 | rgb[1] = 0xFF00; | |
60 | rgb[2] = 0xFF0000; | |
61 | } else { | |
62 | rgb[0] = 0xFF0000; | |
63 | rgb[1] = 0xFF00; | |
64 | rgb[2] = 0xFF; | |
65 | } | |
66 | bpp = 32; | |
67 | pixdepth = 24; | |
68 | vclass = XWD_TRUE_COLOR; | |
69 | bpad = 32; | |
70 | break; | |
71 | case AV_PIX_FMT_BGR24: | |
72 | case AV_PIX_FMT_RGB24: | |
73 | if (pix_fmt == AV_PIX_FMT_RGB24) | |
74 | be = 1; | |
75 | bpp = 24; | |
76 | vclass = XWD_TRUE_COLOR; | |
77 | bpad = 32; | |
78 | rgb[0] = 0xFF0000; | |
79 | rgb[1] = 0xFF00; | |
80 | rgb[2] = 0xFF; | |
81 | break; | |
82 | case AV_PIX_FMT_RGB565LE: | |
83 | case AV_PIX_FMT_RGB565BE: | |
84 | case AV_PIX_FMT_BGR565LE: | |
85 | case AV_PIX_FMT_BGR565BE: | |
86 | if (pix_fmt == AV_PIX_FMT_BGR565LE || | |
87 | pix_fmt == AV_PIX_FMT_BGR565BE) { | |
88 | rgb[0] = 0x1F; | |
89 | rgb[1] = 0x7E0; | |
90 | rgb[2] = 0xF800; | |
91 | } else { | |
92 | rgb[0] = 0xF800; | |
93 | rgb[1] = 0x7E0; | |
94 | rgb[2] = 0x1F; | |
95 | } | |
96 | bpp = 16; | |
97 | vclass = XWD_TRUE_COLOR; | |
98 | bpad = 16; | |
99 | break; | |
100 | case AV_PIX_FMT_RGB555LE: | |
101 | case AV_PIX_FMT_RGB555BE: | |
102 | case AV_PIX_FMT_BGR555LE: | |
103 | case AV_PIX_FMT_BGR555BE: | |
104 | if (pix_fmt == AV_PIX_FMT_BGR555LE || | |
105 | pix_fmt == AV_PIX_FMT_BGR555BE) { | |
106 | rgb[0] = 0x1F; | |
107 | rgb[1] = 0x3E0; | |
108 | rgb[2] = 0x7C00; | |
109 | } else { | |
110 | rgb[0] = 0x7C00; | |
111 | rgb[1] = 0x3E0; | |
112 | rgb[2] = 0x1F; | |
113 | } | |
114 | bpp = 16; | |
115 | vclass = XWD_TRUE_COLOR; | |
116 | bpad = 16; | |
117 | break; | |
118 | case AV_PIX_FMT_RGB8: | |
119 | case AV_PIX_FMT_BGR8: | |
120 | case AV_PIX_FMT_RGB4_BYTE: | |
121 | case AV_PIX_FMT_BGR4_BYTE: | |
122 | case AV_PIX_FMT_PAL8: | |
123 | bpp = 8; | |
124 | vclass = XWD_PSEUDO_COLOR; | |
125 | bpad = 8; | |
126 | ncolors = 256; | |
127 | break; | |
128 | case AV_PIX_FMT_GRAY8: | |
129 | bpp = 8; | |
130 | bpad = 8; | |
131 | vclass = XWD_STATIC_GRAY; | |
132 | break; | |
133 | case AV_PIX_FMT_MONOWHITE: | |
134 | be = 1; | |
135 | bitorder = 1; | |
136 | bpp = 1; | |
137 | bpad = 8; | |
138 | vclass = XWD_STATIC_GRAY; | |
139 | break; | |
140 | default: | |
141 | av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n"); | |
142 | return AVERROR(EINVAL); | |
143 | } | |
144 | ||
145 | lsize = FFALIGN(bpp * avctx->width, bpad) / 8; | |
146 | header_size = XWD_HEADER_SIZE + WINDOW_NAME_SIZE; | |
147 | out_size = header_size + ncolors * XWD_CMAP_SIZE + avctx->height * lsize; | |
148 | ||
149 | if ((ret = ff_alloc_packet2(avctx, pkt, out_size)) < 0) | |
150 | return ret; | |
151 | buf = pkt->data; | |
152 | ||
153 | p->key_frame = 1; | |
154 | p->pict_type = AV_PICTURE_TYPE_I; | |
155 | ||
156 | bytestream_put_be32(&buf, header_size); | |
157 | bytestream_put_be32(&buf, XWD_VERSION); // file version | |
158 | bytestream_put_be32(&buf, XWD_Z_PIXMAP); // pixmap format | |
159 | bytestream_put_be32(&buf, pixdepth); // pixmap depth in pixels | |
160 | bytestream_put_be32(&buf, avctx->width); // pixmap width in pixels | |
161 | bytestream_put_be32(&buf, avctx->height); // pixmap height in pixels | |
162 | bytestream_put_be32(&buf, 0); // bitmap x offset | |
163 | bytestream_put_be32(&buf, be); // byte order | |
164 | bytestream_put_be32(&buf, 32); // bitmap unit | |
165 | bytestream_put_be32(&buf, bitorder); // bit-order of image data | |
166 | bytestream_put_be32(&buf, bpad); // bitmap scan-line pad in bits | |
167 | bytestream_put_be32(&buf, bpp); // bits per pixel | |
168 | bytestream_put_be32(&buf, lsize); // bytes per scan-line | |
169 | bytestream_put_be32(&buf, vclass); // visual class | |
170 | bytestream_put_be32(&buf, rgb[0]); // red mask | |
171 | bytestream_put_be32(&buf, rgb[1]); // green mask | |
172 | bytestream_put_be32(&buf, rgb[2]); // blue mask | |
173 | bytestream_put_be32(&buf, 8); // size of each bitmask in bits | |
174 | bytestream_put_be32(&buf, ncolors); // number of colors | |
175 | bytestream_put_be32(&buf, ncolors); // number of entries in color map | |
176 | bytestream_put_be32(&buf, avctx->width); // window width | |
177 | bytestream_put_be32(&buf, avctx->height); // window height | |
178 | bytestream_put_be32(&buf, 0); // window upper left X coordinate | |
179 | bytestream_put_be32(&buf, 0); // window upper left Y coordinate | |
180 | bytestream_put_be32(&buf, 0); // window border width | |
181 | bytestream_put_buffer(&buf, WINDOW_NAME, WINDOW_NAME_SIZE); | |
182 | ||
183 | for (i = 0; i < ncolors; i++) { | |
184 | uint32_t val; | |
185 | uint8_t red, green, blue; | |
186 | ||
187 | val = AV_RN32A(p->data[1] + i * 4); | |
188 | red = (val >> 16) & 0xFF; | |
189 | green = (val >> 8) & 0xFF; | |
190 | blue = val & 0xFF; | |
191 | ||
192 | bytestream_put_be32(&buf, i); // colormap entry number | |
193 | bytestream_put_be16(&buf, red << 8); | |
194 | bytestream_put_be16(&buf, green << 8); | |
195 | bytestream_put_be16(&buf, blue << 8); | |
196 | bytestream_put_byte(&buf, 0x7); // bitmask flag | |
197 | bytestream_put_byte(&buf, 0); // padding | |
198 | } | |
199 | ||
200 | ptr = p->data[0]; | |
201 | for (i = 0; i < avctx->height; i++) { | |
202 | bytestream_put_buffer(&buf, ptr, lsize); | |
203 | ptr += p->linesize[0]; | |
204 | } | |
205 | ||
206 | pkt->flags |= AV_PKT_FLAG_KEY; | |
207 | *got_packet = 1; | |
208 | return 0; | |
209 | } | |
210 | ||
211 | AVCodec ff_xwd_encoder = { | |
212 | .name = "xwd", | |
213 | .long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"), | |
214 | .type = AVMEDIA_TYPE_VIDEO, | |
215 | .id = AV_CODEC_ID_XWD, | |
216 | .encode2 = xwd_encode_frame, | |
217 | .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGRA, | |
218 | AV_PIX_FMT_RGBA, | |
219 | AV_PIX_FMT_ARGB, | |
220 | AV_PIX_FMT_ABGR, | |
221 | AV_PIX_FMT_RGB24, | |
222 | AV_PIX_FMT_BGR24, | |
223 | AV_PIX_FMT_RGB565BE, | |
224 | AV_PIX_FMT_RGB565LE, | |
225 | AV_PIX_FMT_BGR565BE, | |
226 | AV_PIX_FMT_BGR565LE, | |
227 | AV_PIX_FMT_RGB555BE, | |
228 | AV_PIX_FMT_RGB555LE, | |
229 | AV_PIX_FMT_BGR555BE, | |
230 | AV_PIX_FMT_BGR555LE, | |
231 | AV_PIX_FMT_RGB8, | |
232 | AV_PIX_FMT_BGR8, | |
233 | AV_PIX_FMT_RGB4_BYTE, | |
234 | AV_PIX_FMT_BGR4_BYTE, | |
235 | AV_PIX_FMT_PAL8, | |
236 | AV_PIX_FMT_GRAY8, | |
237 | AV_PIX_FMT_MONOWHITE, | |
238 | AV_PIX_FMT_NONE }, | |
239 | }; |