1 /*****************************************************************
2 * gmerlin - a general purpose multimedia framework and applications
3 *
4 * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5 * gmerlin-general@lists.sourceforge.net
6 * http://gmerlin.sourceforge.net
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program 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
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * *****************************************************************/
21
22 #include <x11/x11.h>
23 #include <x11/x11_window_private.h>
24
25 /* Warning: These functions are not optimized and not intended to
26 be used very often */
27
make_icon(bg_x11_window_t * win,const gavl_video_frame_t * icon,const gavl_video_format_t * format)28 static Pixmap make_icon(bg_x11_window_t * win,
29 const gavl_video_frame_t * icon,
30 const gavl_video_format_t * format)
31 {
32 XImage * im;
33 gavl_video_format_t out_format;
34 gavl_video_converter_t * cnv;
35 gavl_video_options_t * opt;
36 int do_convert;
37 const gavl_video_frame_t * image_frame;
38 gavl_video_frame_t * out_frame;
39
40 Pixmap ret;
41
42 /* Create converter */
43 cnv = gavl_video_converter_create();
44 opt = gavl_video_converter_get_options(cnv);
45 gavl_video_options_set_alpha_mode(opt, GAVL_ALPHA_IGNORE);
46
47 /* Create pixmap */
48 ret = XCreatePixmap(win->dpy, win->root, format->image_width,
49 format->image_height, win->depth);
50
51 /* Set up format and converter */
52 gavl_video_format_copy(&out_format, format);
53 out_format.pixelformat =
54 bg_x11_window_get_pixelformat(win->dpy, win->visual, win->depth);
55
56 do_convert = gavl_video_converter_init(cnv, format, &out_format);
57 if(do_convert)
58 {
59 out_frame = gavl_video_frame_create(&out_format);
60 image_frame = out_frame;
61 gavl_video_convert(cnv, icon, out_frame);
62 }
63 else
64 {
65 image_frame = icon;
66 out_frame = NULL;
67 }
68
69 /* Make image */
70
71 im = XCreateImage(win->dpy, win->visual, win->depth,
72 ZPixmap,
73 0, (char*)(image_frame->planes[0]),
74 format->image_width,
75 format->image_height,
76 32,
77 image_frame->strides[0]);
78
79 XPutImage(win->dpy, /* dpy */
80 ret, /* d */
81 win->gc, /* gc */
82 im, /* image */
83 0, /* src_x */
84 0, /* src_y */
85 0, /* dst_x */
86 0, /* dst_y */
87 format->image_width, /* src_width */
88 format->image_height); /* src_height */
89
90 /* Cleanup */
91 gavl_video_converter_destroy(cnv);
92 if(out_frame)
93 gavl_video_frame_destroy(out_frame);
94
95 im->data = NULL;
96 XDestroyImage(im);
97
98 /* Return */
99 return ret;
100
101 }
102
create_mask_8(gavl_video_format_t * format,gavl_video_frame_t * frame,char * im,int bytes_per_line)103 static void create_mask_8(gavl_video_format_t * format,
104 gavl_video_frame_t * frame,
105 char * im, int bytes_per_line)
106 {
107 int i, j;
108 uint8_t * ptr;
109 uint8_t * im_ptr;
110 int shift;
111
112 for(i = 0; i < format->image_height; i++)
113 {
114 ptr = frame->planes[0] + i * frame->strides[0];
115 im_ptr = (uint8_t*)(im + i * bytes_per_line);
116 shift = 0;
117
118 for(j = 0; j < format->image_width; j++)
119 {
120 if(*ptr >= 0x80)
121 *im_ptr |= 1 << shift;
122 if(shift == 7)
123 {
124 im_ptr++;
125 shift = 0;
126 }
127 else
128 shift++;
129 ptr++;
130 }
131 }
132
133 }
134
create_mask_16(gavl_video_format_t * format,gavl_video_frame_t * frame,char * im,int bytes_per_line)135 static void create_mask_16(gavl_video_format_t * format,
136 gavl_video_frame_t * frame,
137 char * im, int bytes_per_line)
138 {
139 int i, j;
140 uint16_t * ptr;
141 uint8_t * im_ptr;
142 int shift;
143
144 for(i = 0; i < format->image_height; i++)
145 {
146 ptr = (uint16_t*)(frame->planes[0] + i * frame->strides[0]);
147 im_ptr = (uint8_t*)(im + i * bytes_per_line);
148 shift = 0;
149
150 for(j = 0; j < format->image_width; j++)
151 {
152 if(*ptr >= 0x8000)
153 *im_ptr |= 1 << shift;
154 if(shift == 7)
155 {
156 im_ptr++;
157 shift = 0;
158 }
159 else
160 shift++;
161 ptr++;
162 }
163 }
164
165 }
166
create_mask_float(gavl_video_format_t * format,gavl_video_frame_t * frame,char * im,int bytes_per_line)167 static void create_mask_float(gavl_video_format_t * format,
168 gavl_video_frame_t * frame,
169 char * im, int bytes_per_line)
170 {
171 int i, j;
172 float * ptr;
173 uint8_t * im_ptr;
174 int shift;
175
176 for(i = 0; i < format->image_height; i++)
177 {
178 ptr = (float*)(frame->planes[0] + i * frame->strides[0]);
179 im_ptr = (uint8_t*)(im + i * bytes_per_line);
180 shift = 0;
181
182 for(j = 0; j < format->image_width; j++)
183 {
184 if(*ptr >= 0.5)
185 *im_ptr |= 1 << shift;
186 if(shift == 7)
187 {
188 im_ptr++;
189 shift = 0;
190 }
191 else
192 shift++;
193 ptr++;
194 }
195 }
196
197 }
198
make_mask(bg_x11_window_t * win,const gavl_video_frame_t * icon,const gavl_video_format_t * format)199 static Pixmap make_mask(bg_x11_window_t * win,
200 const gavl_video_frame_t * icon,
201 const gavl_video_format_t * format)
202 {
203 gavl_video_frame_t * alpha_frame;
204 gavl_video_format_t alpha_format;
205 char * image_data;
206
207 Pixmap ret;
208 int bytes_per_line;
209
210 /* Extract alpha */
211 if(!gavl_get_color_channel_format(format,
212 &alpha_format,
213 GAVL_CCH_ALPHA))
214 return None; /* No alpha */
215
216 alpha_frame = gavl_video_frame_create(&alpha_format);
217
218 gavl_video_frame_extract_channel(format,
219 GAVL_CCH_ALPHA,
220 icon,
221 alpha_frame);
222
223 /* Create image */
224
225 bytes_per_line = (format->image_width + 7) / 8;
226 image_data = calloc(1, bytes_per_line * format->image_height);
227
228 switch(alpha_format.pixelformat)
229 {
230 case GAVL_GRAY_8:
231 create_mask_8(&alpha_format, alpha_frame, image_data, bytes_per_line);
232 break;
233 case GAVL_GRAY_16:
234 create_mask_16(&alpha_format, alpha_frame, image_data, bytes_per_line);
235 break;
236 case GAVL_GRAY_FLOAT:
237 create_mask_float(&alpha_format, alpha_frame, image_data, bytes_per_line);
238 break;
239 default:
240 break;
241 }
242 ret = XCreateBitmapFromData(win->dpy, win->root,
243 image_data,
244 format->image_width,
245 format->image_height);
246
247 gavl_video_frame_destroy(alpha_frame);
248 free(image_data);
249 return ret;
250 }
251
bg_x11_window_make_icon(bg_x11_window_t * win,const gavl_video_frame_t * icon,const gavl_video_format_t * format,Pixmap * icon_ret,Pixmap * mask_ret)252 void bg_x11_window_make_icon(bg_x11_window_t * win,
253 const gavl_video_frame_t * icon,
254 const gavl_video_format_t * format,
255 Pixmap * icon_ret, Pixmap * mask_ret)
256 {
257 if(icon_ret)
258 *icon_ret = make_icon(win, icon, format);
259
260 if(mask_ret)
261 *mask_ret = make_mask(win, icon, format);
262 }
263
264