• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/pixdesc.h"
24 #include "avcodec.h"
25 #include "bytestream.h"
26 #include "codec_internal.h"
27 #include "encode.h"
28 #include "xwd.h"
29 
30 #define WINDOW_NAME         "lavcxwdenc"
31 #define WINDOW_NAME_SIZE    11
32 
xwd_encode_frame(AVCodecContext * avctx,AVPacket * pkt,const AVFrame * pict,int * got_packet)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     uint32_t pal[256];
45 
46     pixdepth = av_get_bits_per_pixel(desc);
47     if (desc->flags & AV_PIX_FMT_FLAG_BE)
48         be = 1;
49     switch (pix_fmt) {
50     case AV_PIX_FMT_ARGB:
51     case AV_PIX_FMT_BGRA:
52     case AV_PIX_FMT_RGBA:
53     case AV_PIX_FMT_ABGR:
54         if (pix_fmt == AV_PIX_FMT_ARGB ||
55             pix_fmt == AV_PIX_FMT_ABGR)
56             be = 1;
57         if (pix_fmt == AV_PIX_FMT_ABGR ||
58             pix_fmt == AV_PIX_FMT_RGBA) {
59             rgb[0] = 0xFF;
60             rgb[1] = 0xFF00;
61             rgb[2] = 0xFF0000;
62         } else {
63             rgb[0] = 0xFF0000;
64             rgb[1] = 0xFF00;
65             rgb[2] = 0xFF;
66         }
67         bpp      = 32;
68         pixdepth = 24;
69         vclass   = XWD_TRUE_COLOR;
70         bpad     = 32;
71         break;
72     case AV_PIX_FMT_BGR24:
73     case AV_PIX_FMT_RGB24:
74         if (pix_fmt == AV_PIX_FMT_RGB24)
75             be = 1;
76         bpp      = 24;
77         vclass   = XWD_TRUE_COLOR;
78         bpad     = 32;
79         rgb[0]   = 0xFF0000;
80         rgb[1]   = 0xFF00;
81         rgb[2]   = 0xFF;
82         break;
83     case AV_PIX_FMT_RGB565LE:
84     case AV_PIX_FMT_RGB565BE:
85     case AV_PIX_FMT_BGR565LE:
86     case AV_PIX_FMT_BGR565BE:
87         if (pix_fmt == AV_PIX_FMT_BGR565LE ||
88             pix_fmt == AV_PIX_FMT_BGR565BE) {
89             rgb[0] = 0x1F;
90             rgb[1] = 0x7E0;
91             rgb[2] = 0xF800;
92         } else {
93             rgb[0] = 0xF800;
94             rgb[1] = 0x7E0;
95             rgb[2] = 0x1F;
96         }
97         bpp      = 16;
98         vclass   = XWD_TRUE_COLOR;
99         bpad     = 16;
100         break;
101     case AV_PIX_FMT_RGB555LE:
102     case AV_PIX_FMT_RGB555BE:
103     case AV_PIX_FMT_BGR555LE:
104     case AV_PIX_FMT_BGR555BE:
105         if (pix_fmt == AV_PIX_FMT_BGR555LE ||
106             pix_fmt == AV_PIX_FMT_BGR555BE) {
107             rgb[0] = 0x1F;
108             rgb[1] = 0x3E0;
109             rgb[2] = 0x7C00;
110         } else {
111             rgb[0] = 0x7C00;
112             rgb[1] = 0x3E0;
113             rgb[2] = 0x1F;
114         }
115         bpp      = 16;
116         vclass   = XWD_TRUE_COLOR;
117         bpad     = 16;
118         break;
119     case AV_PIX_FMT_RGB8:
120     case AV_PIX_FMT_BGR8:
121     case AV_PIX_FMT_RGB4_BYTE:
122     case AV_PIX_FMT_BGR4_BYTE:
123     case AV_PIX_FMT_PAL8:
124         bpp      = 8;
125         vclass   = XWD_PSEUDO_COLOR;
126         bpad     = 8;
127         ncolors  = 256;
128         break;
129     case AV_PIX_FMT_GRAY8:
130         bpp      = 8;
131         bpad     = 8;
132         vclass   = XWD_STATIC_GRAY;
133         break;
134     case AV_PIX_FMT_MONOWHITE:
135         be       = 1;
136         bitorder = 1;
137         bpp      = 1;
138         bpad     = 8;
139         vclass   = XWD_STATIC_GRAY;
140         break;
141     default:
142         av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n");
143         return AVERROR(EINVAL);
144     }
145 
146     lsize       = FFALIGN(bpp * avctx->width, bpad) / 8;
147     header_size = XWD_HEADER_SIZE + WINDOW_NAME_SIZE;
148     out_size    = header_size + ncolors * XWD_CMAP_SIZE + avctx->height * lsize;
149 
150     if ((ret = ff_get_encode_buffer(avctx, pkt, out_size, 0)) < 0)
151         return ret;
152     buf = pkt->data;
153 
154     p->key_frame = 1;
155     p->pict_type = AV_PICTURE_TYPE_I;
156 
157     bytestream_put_be32(&buf, header_size);
158     bytestream_put_be32(&buf, XWD_VERSION);   // file version
159     bytestream_put_be32(&buf, XWD_Z_PIXMAP);  // pixmap format
160     bytestream_put_be32(&buf, pixdepth);      // pixmap depth in pixels
161     bytestream_put_be32(&buf, avctx->width);  // pixmap width in pixels
162     bytestream_put_be32(&buf, avctx->height); // pixmap height in pixels
163     bytestream_put_be32(&buf, 0);             // bitmap x offset
164     bytestream_put_be32(&buf, be);            // byte order
165     bytestream_put_be32(&buf, 32);            // bitmap unit
166     bytestream_put_be32(&buf, bitorder);      // bit-order of image data
167     bytestream_put_be32(&buf, bpad);          // bitmap scan-line pad in bits
168     bytestream_put_be32(&buf, bpp);           // bits per pixel
169     bytestream_put_be32(&buf, lsize);         // bytes per scan-line
170     bytestream_put_be32(&buf, vclass);        // visual class
171     bytestream_put_be32(&buf, rgb[0]);        // red mask
172     bytestream_put_be32(&buf, rgb[1]);        // green mask
173     bytestream_put_be32(&buf, rgb[2]);        // blue mask
174     bytestream_put_be32(&buf, 8);             // size of each bitmask in bits
175     bytestream_put_be32(&buf, ncolors);       // number of colors
176     bytestream_put_be32(&buf, ncolors);       // number of entries in color map
177     bytestream_put_be32(&buf, avctx->width);  // window width
178     bytestream_put_be32(&buf, avctx->height); // window height
179     bytestream_put_be32(&buf, 0);             // window upper left X coordinate
180     bytestream_put_be32(&buf, 0);             // window upper left Y coordinate
181     bytestream_put_be32(&buf, 0);             // window border width
182     bytestream_put_buffer(&buf, WINDOW_NAME, WINDOW_NAME_SIZE);
183 
184     if (pix_fmt == AV_PIX_FMT_PAL8) {
185         memcpy(pal, p->data[1], sizeof(pal));
186     } else {
187         avpriv_set_systematic_pal2(pal, pix_fmt);
188     }
189 
190     for (i = 0; i < ncolors; i++) {
191         uint32_t val;
192         uint8_t red, green, blue;
193 
194         val   = pal[i];
195         red   = (val >> 16) & 0xFF;
196         green = (val >>  8) & 0xFF;
197         blue  =  val        & 0xFF;
198 
199         bytestream_put_be32(&buf, i);         // colormap entry number
200         bytestream_put_be16(&buf, red   << 8);
201         bytestream_put_be16(&buf, green << 8);
202         bytestream_put_be16(&buf, blue  << 8);
203         bytestream_put_byte(&buf, 0x7);       // bitmask flag
204         bytestream_put_byte(&buf, 0);         // padding
205     }
206 
207     ptr = p->data[0];
208     for (i = 0; i < avctx->height; i++) {
209         bytestream_put_buffer(&buf, ptr, lsize);
210         ptr += p->linesize[0];
211     }
212 
213     *got_packet = 1;
214     return 0;
215 }
216 
217 const FFCodec ff_xwd_encoder = {
218     .p.name         = "xwd",
219     .p.long_name    = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"),
220     .p.type         = AVMEDIA_TYPE_VIDEO,
221     .p.id           = AV_CODEC_ID_XWD,
222     .p.capabilities = AV_CODEC_CAP_DR1,
223     FF_CODEC_ENCODE_CB(xwd_encode_frame),
224     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGRA,
225                                                  AV_PIX_FMT_RGBA,
226                                                  AV_PIX_FMT_ARGB,
227                                                  AV_PIX_FMT_ABGR,
228                                                  AV_PIX_FMT_RGB24,
229                                                  AV_PIX_FMT_BGR24,
230                                                  AV_PIX_FMT_RGB565BE,
231                                                  AV_PIX_FMT_RGB565LE,
232                                                  AV_PIX_FMT_BGR565BE,
233                                                  AV_PIX_FMT_BGR565LE,
234                                                  AV_PIX_FMT_RGB555BE,
235                                                  AV_PIX_FMT_RGB555LE,
236                                                  AV_PIX_FMT_BGR555BE,
237                                                  AV_PIX_FMT_BGR555LE,
238                                                  AV_PIX_FMT_RGB8,
239                                                  AV_PIX_FMT_BGR8,
240                                                  AV_PIX_FMT_RGB4_BYTE,
241                                                  AV_PIX_FMT_BGR4_BYTE,
242                                                  AV_PIX_FMT_PAL8,
243                                                  AV_PIX_FMT_GRAY8,
244                                                  AV_PIX_FMT_MONOWHITE,
245                                                  AV_PIX_FMT_NONE },
246 };
247