author | zecke <zecke> | 2002-07-11 22:48:38 (UTC) |
---|---|---|
committer | zecke <zecke> | 2002-07-11 22:48:38 (UTC) |
commit | a7b8ef4096c17ba5e0ff96e9292a291390831e69 (patch) (unidiff) | |
tree | 94efad118c336e4d8c00137c7be5b31852c8296d /noncore/multimedia/opieplayer2/alphablend.c | |
parent | d2c7228d2efe6f47ef5b7ec04157fcead775be74 (diff) | |
download | opie-a7b8ef4096c17ba5e0ff96e9292a291390831e69.zip opie-a7b8ef4096c17ba5e0ff96e9292a291390831e69.tar.gz opie-a7b8ef4096c17ba5e0ff96e9292a291390831e69.tar.bz2 |
add files
Diffstat (limited to 'noncore/multimedia/opieplayer2/alphablend.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/multimedia/opieplayer2/alphablend.c | 753 |
1 files changed, 753 insertions, 0 deletions
diff --git a/noncore/multimedia/opieplayer2/alphablend.c b/noncore/multimedia/opieplayer2/alphablend.c new file mode 100644 index 0000000..57f6013 --- a/dev/null +++ b/noncore/multimedia/opieplayer2/alphablend.c | |||
@@ -0,0 +1,753 @@ | |||
1 | //TOAST_SPU will define ALL spu entries - no matter the tranparency | ||
2 | //#define TOAST_SPU | ||
3 | /* #define PRIV_CLUT */ | ||
4 | /* Currently only blend_yuv(..) works */ | ||
5 | /* | ||
6 | * | ||
7 | * Copyright (C) James Courtier-Dutton James@superbug.demon.co.uk - July 2001 | ||
8 | * | ||
9 | * Copyright (C) 2000 Thomas Mirlacher | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | * | ||
25 | * The author may be reached as <dent@linuxvideo.org> | ||
26 | * | ||
27 | *------------------------------------------------------------ | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | /* | ||
32 | #define LOG_BLEND_YUV | ||
33 | */ | ||
34 | |||
35 | #include <string.h> | ||
36 | #include <stdlib.h> | ||
37 | #include <stdio.h> | ||
38 | #include <inttypes.h> | ||
39 | |||
40 | #include <xine/video_out.h> | ||
41 | #include "alphablend.h" | ||
42 | |||
43 | |||
44 | #define BLEND_COLOR(dst, src, mask, o) ((((src&mask)*o + ((dst&mask)*(0x0f-o)))/0xf) & mask) | ||
45 | |||
46 | #define BLEND_BYTE(dst, src, o) (((src)*o + ((dst)*(0xf-o)))/0xf) | ||
47 | |||
48 | static void mem_blend16(uint16_t *mem, uint16_t clr, uint8_t o, int len) { | ||
49 | uint16_t *limit = mem + len; | ||
50 | while (mem < limit) { | ||
51 | *mem = | ||
52 | BLEND_COLOR(*mem, clr, 0xf800, o) | | ||
53 | BLEND_COLOR(*mem, clr, 0x07e0, o) | | ||
54 | BLEND_COLOR(*mem, clr, 0x001f, o); | ||
55 | mem++; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | static void mem_blend24(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b, | ||
60 | uint8_t o, int len) { | ||
61 | uint8_t *limit = mem + len*3; | ||
62 | while (mem < limit) { | ||
63 | *mem = BLEND_BYTE(*mem, r, o); | ||
64 | mem++; | ||
65 | *mem = BLEND_BYTE(*mem, g, o); | ||
66 | mem++; | ||
67 | *mem = BLEND_BYTE(*mem, b, o); | ||
68 | mem++; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | static void mem_blend24_32(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b, | ||
73 | uint8_t o, int len) { | ||
74 | uint8_t *limit = mem + len*4; | ||
75 | while (mem < limit) { | ||
76 | *mem = BLEND_BYTE(*mem, r, o); | ||
77 | mem++; | ||
78 | *mem = BLEND_BYTE(*mem, g, o); | ||
79 | mem++; | ||
80 | *mem = BLEND_BYTE(*mem, b, o); | ||
81 | mem += 2; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | static void mem_blend32(uint8_t *mem, uint8_t *src, uint8_t o, int len) { | ||
86 | uint8_t *limit = mem + len*4; | ||
87 | while (mem < limit) { | ||
88 | *mem = BLEND_BYTE(*mem, src[0], o); | ||
89 | mem++; | ||
90 | *mem = BLEND_BYTE(*mem, src[1], o); | ||
91 | mem++; | ||
92 | *mem = BLEND_BYTE(*mem, src[2], o); | ||
93 | mem++; | ||
94 | *mem = BLEND_BYTE(*mem, src[3], o); | ||
95 | mem++; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | |||
100 | /* | ||
101 | * Some macros for fixed point arithmetic. | ||
102 | * | ||
103 | * The blend_rgb* routines perform rle image scaling using | ||
104 | * scale factors that are expressed as integers scaled with | ||
105 | * a factor of 2**16. | ||
106 | * | ||
107 | * INT_TO_SCALED()/SCALED_TO_INT() converts from integer | ||
108 | * to scaled fixed point and back. | ||
109 | */ | ||
110 | #define SCALE_SHIFT 16 | ||
111 | #define SCALE_FACTOR (1<<SCALE_SHIFT) | ||
112 | #defineINT_TO_SCALED(i) ((i) << SCALE_SHIFT) | ||
113 | #defineSCALED_TO_INT(sc) ((sc) >> SCALE_SHIFT) | ||
114 | |||
115 | |||
116 | static rle_elem_t * | ||
117 | rle_img_advance_line(rle_elem_t *rle, rle_elem_t *rle_limit, int w) | ||
118 | { | ||
119 | int x; | ||
120 | |||
121 | for (x = 0; x < w && rle < rle_limit; ) { | ||
122 | x += rle->len; | ||
123 | rle++; | ||
124 | } | ||
125 | return rle; | ||
126 | } | ||
127 | |||
128 | |||
129 | void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, | ||
130 | int img_width, int img_height, | ||
131 | int dst_width, int dst_height) | ||
132 | { | ||
133 | uint8_t *trans; | ||
134 | clut_t* clut = (clut_t*) img_overl->clip_color; | ||
135 | |||
136 | int src_width = img_overl->width; | ||
137 | int src_height = img_overl->height; | ||
138 | rle_elem_t *rle = img_overl->rle; | ||
139 | rle_elem_t *rle_limit = rle + img_overl->num_rle; | ||
140 | int x, y, x1_scaled, x2_scaled; | ||
141 | int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */ | ||
142 | int clip_right; | ||
143 | uint16_t *img_pix; | ||
144 | |||
145 | dy_step = INT_TO_SCALED(dst_height) / img_height; | ||
146 | x_scale = INT_TO_SCALED(img_width) / dst_width; | ||
147 | |||
148 | img_pix = (uint16_t *) img | ||
149 | + (img_overl->y * img_height / dst_height) * img_width | ||
150 | + (img_overl->x * img_width / dst_width); | ||
151 | |||
152 | trans = img_overl->clip_trans; | ||
153 | |||
154 | /* avoid wraping overlay if drawing to small image */ | ||
155 | if( (img_overl->x + img_overl->clip_right) < dst_width ) | ||
156 | clip_right = img_overl->clip_right; | ||
157 | else | ||
158 | clip_right = dst_width - 1 - img_overl->x; | ||
159 | |||
160 | /* avoid buffer overflow */ | ||
161 | if( (src_height + img_overl->y) >= dst_height ) | ||
162 | src_height = dst_height - 1 - img_overl->y; | ||
163 | |||
164 | for (y = dy = 0; y < src_height && rle < rle_limit;) { | ||
165 | int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); | ||
166 | rle_elem_t *rle_start = rle; | ||
167 | |||
168 | for (x = x1_scaled = 0; x < src_width;) { | ||
169 | uint8_t clr; | ||
170 | uint16_t o; | ||
171 | int rlelen; | ||
172 | |||
173 | clr = rle->color; | ||
174 | o = trans[clr]; | ||
175 | rlelen = rle->len; | ||
176 | |||
177 | if (o && mask) { | ||
178 | /* threat cases where clipping border is inside rle->len pixels */ | ||
179 | if ( img_overl->clip_left > x ) { | ||
180 | if( img_overl->clip_left < x + rlelen ) { | ||
181 | x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale ); | ||
182 | rlelen -= img_overl->clip_left - x; | ||
183 | x += img_overl->clip_left - x; | ||
184 | } else { | ||
185 | o = 0; | ||
186 | } | ||
187 | } else if( clip_right < x + rlelen ) { | ||
188 | if( clip_right > x ) { | ||
189 | x2_scaled = SCALED_TO_INT( clip_right * x_scale); | ||
190 | mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, | ||
191 | x2_scaled-x1_scaled); | ||
192 | o = 0; | ||
193 | } else { | ||
194 | o = 0; | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | |||
199 | x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale); | ||
200 | if (o && mask) { | ||
201 | mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); | ||
202 | } | ||
203 | |||
204 | x1_scaled = x2_scaled; | ||
205 | x += rlelen; | ||
206 | rle++; | ||
207 | if (rle >= rle_limit) break; | ||
208 | } | ||
209 | |||
210 | img_pix += img_width; | ||
211 | dy += dy_step; | ||
212 | if (dy >= INT_TO_SCALED(1)) { | ||
213 | dy -= INT_TO_SCALED(1); | ||
214 | ++y; | ||
215 | while (dy >= INT_TO_SCALED(1)) { | ||
216 | rle = rle_img_advance_line(rle, rle_limit, src_width); | ||
217 | dy -= INT_TO_SCALED(1); | ||
218 | ++y; | ||
219 | } | ||
220 | } else { | ||
221 | rle = rle_start; /* y-scaling, reuse the last rle encoded line */ | ||
222 | } | ||
223 | } | ||
224 | } | ||
225 | |||
226 | void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, | ||
227 | int img_width, int img_height, | ||
228 | int dst_width, int dst_height) | ||
229 | { | ||
230 | clut_t* clut = (clut_t*) img_overl->clip_color; | ||
231 | uint8_t *trans; | ||
232 | int src_width = img_overl->width; | ||
233 | int src_height = img_overl->height; | ||
234 | rle_elem_t *rle = img_overl->rle; | ||
235 | rle_elem_t *rle_limit = rle + img_overl->num_rle; | ||
236 | int x, y, x1_scaled, x2_scaled; | ||
237 | int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */ | ||
238 | int clip_right; | ||
239 | uint8_t *img_pix; | ||
240 | |||
241 | dy_step = INT_TO_SCALED(dst_height) / img_height; | ||
242 | x_scale = INT_TO_SCALED(img_width) / dst_width; | ||
243 | |||
244 | img_pix = img + 3 * ( (img_overl->y * img_height / dst_height) * img_width | ||
245 | + (img_overl->x * img_width / dst_width)); | ||
246 | |||
247 | trans = img_overl->clip_trans; | ||
248 | |||
249 | /* avoid wraping overlay if drawing to small image */ | ||
250 | if( (img_overl->x + img_overl->clip_right) < dst_width ) | ||
251 | clip_right = img_overl->clip_right; | ||
252 | else | ||
253 | clip_right = dst_width - 1 - img_overl->x; | ||
254 | |||
255 | /* avoid buffer overflow */ | ||
256 | if( (src_height + img_overl->y) >= dst_height ) | ||
257 | src_height = dst_height - 1 - img_overl->y; | ||
258 | |||
259 | for (dy = y = 0; y < src_height && rle < rle_limit; ) { | ||
260 | int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); | ||
261 | rle_elem_t *rle_start = rle; | ||
262 | |||
263 | for (x = x1_scaled = 0; x < src_width;) { | ||
264 | uint8_t clr; | ||
265 | uint16_t o; | ||
266 | int rlelen; | ||
267 | |||
268 | clr = rle->color; | ||
269 | o = trans[clr]; | ||
270 | rlelen = rle->len; | ||
271 | |||
272 | if (o && mask) { | ||
273 | /* threat cases where clipping border is inside rle->len pixels */ | ||
274 | if ( img_overl->clip_left > x ) { | ||
275 | if( img_overl->clip_left < x + rlelen ) { | ||
276 | x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale ); | ||
277 | rlelen -= img_overl->clip_left - x; | ||
278 | x += img_overl->clip_left - x; | ||
279 | } else { | ||
280 | o = 0; | ||
281 | } | ||
282 | } else if( clip_right < x + rlelen ) { | ||
283 | if( clip_right > x ) { | ||
284 | x2_scaled = SCALED_TO_INT( clip_right * x_scale); | ||
285 | mem_blend24(img_pix + x1_scaled*3, clut[clr].cb, | ||
286 | clut[clr].cr, clut[clr].y, | ||
287 | o, x2_scaled-x1_scaled); | ||
288 | o = 0; | ||
289 | } else { | ||
290 | o = 0; | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | |||
295 | x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale); | ||
296 | if (o && mask) { | ||
297 | mem_blend24(img_pix + x1_scaled*3, clut[clr].cb, | ||
298 | clut[clr].cr, clut[clr].y, | ||
299 | o, x2_scaled-x1_scaled); | ||
300 | } | ||
301 | |||
302 | x1_scaled = x2_scaled; | ||
303 | x += rlelen; | ||
304 | rle++; | ||
305 | if (rle >= rle_limit) break; | ||
306 | } | ||
307 | |||
308 | img_pix += img_width * 3; | ||
309 | dy += dy_step; | ||
310 | if (dy >= INT_TO_SCALED(1)) { | ||
311 | dy -= INT_TO_SCALED(1); | ||
312 | ++y; | ||
313 | while (dy >= INT_TO_SCALED(1)) { | ||
314 | rle = rle_img_advance_line(rle, rle_limit, src_width); | ||
315 | dy -= INT_TO_SCALED(1); | ||
316 | ++y; | ||
317 | } | ||
318 | } else { | ||
319 | rle = rle_start; /* y-scaling, reuse the last rle encoded line */ | ||
320 | } | ||
321 | } | ||
322 | } | ||
323 | |||
324 | void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl, | ||
325 | int img_width, int img_height, | ||
326 | int dst_width, int dst_height) | ||
327 | { | ||
328 | clut_t* clut = (clut_t*) img_overl->clip_color; | ||
329 | uint8_t *trans; | ||
330 | int src_width = img_overl->width; | ||
331 | int src_height = img_overl->height; | ||
332 | rle_elem_t *rle = img_overl->rle; | ||
333 | rle_elem_t *rle_limit = rle + img_overl->num_rle; | ||
334 | int x, y, x1_scaled, x2_scaled; | ||
335 | int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */ | ||
336 | int clip_right; | ||
337 | uint8_t *img_pix; | ||
338 | |||
339 | dy_step = INT_TO_SCALED(dst_height) / img_height; | ||
340 | x_scale = INT_TO_SCALED(img_width) / dst_width; | ||
341 | |||
342 | img_pix = img + 4 * ( (img_overl->y * img_height / dst_height) * img_width | ||
343 | + (img_overl->x * img_width / dst_width)); | ||
344 | |||
345 | trans = img_overl->clip_trans; | ||
346 | |||
347 | /* avoid wraping overlay if drawing to small image */ | ||
348 | if( (img_overl->x + img_overl->clip_right) < dst_width ) | ||
349 | clip_right = img_overl->clip_right; | ||
350 | else | ||
351 | clip_right = dst_width - 1 - img_overl->x; | ||
352 | |||
353 | /* avoid buffer overflow */ | ||
354 | if( (src_height + img_overl->y) >= dst_height ) | ||
355 | src_height = dst_height - 1 - img_overl->y; | ||
356 | |||
357 | for (y = dy = 0; y < src_height && rle < rle_limit; ) { | ||
358 | int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); | ||
359 | rle_elem_t *rle_start = rle; | ||
360 | |||
361 | for (x = x1_scaled = 0; x < src_width;) { | ||
362 | uint8_t clr; | ||
363 | uint16_t o; | ||
364 | int rlelen; | ||
365 | |||
366 | clr = rle->color; | ||
367 | o = trans[clr]; | ||
368 | rlelen = rle->len; | ||
369 | |||
370 | if (o && mask) { | ||
371 | /* threat cases where clipping border is inside rle->len pixels */ | ||
372 | if ( img_overl->clip_left > x ) { | ||
373 | if( img_overl->clip_left < x + rlelen ) { | ||
374 | x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale ); | ||
375 | rlelen -= img_overl->clip_left - x; | ||
376 | x += img_overl->clip_left - x; | ||
377 | } else { | ||
378 | o = 0; | ||
379 | } | ||
380 | } else if( clip_right < x + rlelen ) { | ||
381 | if( clip_right > x ) { | ||
382 | x2_scaled = SCALED_TO_INT( clip_right * x_scale); | ||
383 | mem_blend24_32(img_pix + x1_scaled*4, clut[clr].cb, | ||
384 | clut[clr].cr, clut[clr].y, | ||
385 | o, x2_scaled-x1_scaled); | ||
386 | o = 0; | ||
387 | } else { | ||
388 | o = 0; | ||
389 | } | ||
390 | } | ||
391 | } | ||
392 | |||
393 | x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale); | ||
394 | if (o && mask) { | ||
395 | mem_blend24_32(img_pix + x1_scaled*4, clut[clr].cb, | ||
396 | clut[clr].cr, clut[clr].y, | ||
397 | o, x2_scaled-x1_scaled); | ||
398 | } | ||
399 | |||
400 | x1_scaled = x2_scaled; | ||
401 | x += rlelen; | ||
402 | rle++; | ||
403 | if (rle >= rle_limit) break; | ||
404 | } | ||
405 | |||
406 | img_pix += img_width * 4; | ||
407 | dy += dy_step; | ||
408 | if (dy >= INT_TO_SCALED(1)) { | ||
409 | dy -= INT_TO_SCALED(1); | ||
410 | ++y; | ||
411 | while (dy >= INT_TO_SCALED(1)) { | ||
412 | rle = rle_img_advance_line(rle, rle_limit, src_width); | ||
413 | dy -= INT_TO_SCALED(1); | ||
414 | ++y; | ||
415 | } | ||
416 | } else { | ||
417 | rle = rle_start; /* y-scaling, reuse the last rle encoded line */ | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | |||
422 | static void mem_blend8(uint8_t *mem, uint8_t val, uint8_t o, size_t sz) | ||
423 | { | ||
424 | uint8_t *limit = mem + sz; | ||
425 | while (mem < limit) { | ||
426 | *mem = BLEND_BYTE(*mem, val, o); | ||
427 | mem++; | ||
428 | } | ||
429 | } | ||
430 | |||
431 | void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, | ||
432 | int dst_width, int dst_height) | ||
433 | { | ||
434 | clut_t *my_clut; | ||
435 | uint8_t *my_trans; | ||
436 | |||
437 | int src_width = img_overl->width; | ||
438 | int src_height = img_overl->height; | ||
439 | rle_elem_t *rle = img_overl->rle; | ||
440 | rle_elem_t *rle_limit = rle + img_overl->num_rle; | ||
441 | int x_off = img_overl->x; | ||
442 | int y_off = img_overl->y; | ||
443 | int ymask,xmask; | ||
444 | int rle_this_bite; | ||
445 | int rle_remainder; | ||
446 | int rlelen; | ||
447 | int x, y; | ||
448 | int clip_right; | ||
449 | uint8_t clr=0; | ||
450 | |||
451 | uint8_t *dst_y = dst_base[0] + dst_width * y_off + x_off; | ||
452 | uint8_t *dst_cr = dst_base[2] + | ||
453 | (y_off / 2) * (dst_width / 2) + (x_off / 2) + 1; | ||
454 | uint8_t *dst_cb = dst_base[1] + | ||
455 | (y_off / 2) * (dst_width / 2) + (x_off / 2) + 1; | ||
456 | #ifdef LOG_BLEND_YUV | ||
457 | printf("overlay_blend started x=%d, y=%d, w=%d h=%d\n",img_overl->x,img_overl->y,img_overl->width,img_overl->height); | ||
458 | #endif | ||
459 | my_clut = (clut_t*) img_overl->clip_color; | ||
460 | my_trans = img_overl->clip_trans; | ||
461 | |||
462 | /* avoid wraping overlay if drawing to small image */ | ||
463 | if( (x_off + img_overl->clip_right) < dst_width ) | ||
464 | clip_right = img_overl->clip_right; | ||
465 | else | ||
466 | clip_right = dst_width - 1 - x_off; | ||
467 | |||
468 | /* avoid buffer overflow */ | ||
469 | if( (src_height + y_off) >= dst_height ) | ||
470 | src_height = dst_height - 1 - y_off; | ||
471 | |||
472 | rlelen=rle_remainder=0; | ||
473 | for (y = 0; y < src_height; y++) { | ||
474 | ymask = ((img_overl->clip_top > y) || (img_overl->clip_bottom < y)); | ||
475 | xmask = 0; | ||
476 | #ifdef LOG_BLEND_YUV | ||
477 | printf("X started ymask=%d y=%d src_height=%d\n",ymask, y, src_height); | ||
478 | #endif | ||
479 | |||
480 | for (x = 0; x < src_width;) { | ||
481 | uint16_t o; | ||
482 | #ifdef LOG_BLEND_YUV | ||
483 | printf("1:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x); | ||
484 | #endif | ||
485 | |||
486 | if ((rlelen < 0) || (rle_remainder < 0)) { | ||
487 | printf("alphablend: major bug in blend_yuv < 0\n"); | ||
488 | } | ||
489 | if (rlelen == 0) { | ||
490 | rle_remainder = rlelen = rle->len; | ||
491 | clr = rle->color; | ||
492 | rle++; | ||
493 | } | ||
494 | if (rle_remainder == 0) { | ||
495 | rle_remainder = rlelen; | ||
496 | } | ||
497 | if ((rle_remainder + x) > src_width) { | ||
498 | /* Do something for long rlelengths */ | ||
499 | rle_remainder = src_width - x; | ||
500 | ; | ||
501 | } | ||
502 | #ifdef LOG_BLEND_YUV | ||
503 | printf("2:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x); | ||
504 | #endif | ||
505 | |||
506 | if (ymask == 0) { | ||
507 | if (x <= img_overl->clip_left) { | ||
508 | /* Starts outside clip area */ | ||
509 | if ((x + rle_remainder - 1) > img_overl->clip_left ) { | ||
510 | #ifdef LOG_BLEND_YUV | ||
511 | printf("Outside clip left %d, ending inside\n", img_overl->clip_left); | ||
512 | #endif | ||
513 | /* Cutting needed, starts outside, ends inside */ | ||
514 | rle_this_bite = (img_overl->clip_left - x + 1); | ||
515 | rle_remainder -= rle_this_bite; | ||
516 | rlelen -= rle_this_bite; | ||
517 | my_clut = (clut_t*) img_overl->color; | ||
518 | my_trans = img_overl->trans; | ||
519 | xmask = 0; | ||
520 | } else { | ||
521 | #ifdef LOG_BLEND_YUV | ||
522 | printf("Outside clip left %d, ending outside\n", img_overl->clip_left); | ||
523 | #endif | ||
524 | /* no cutting needed, starts outside, ends outside */ | ||
525 | rle_this_bite = rle_remainder; | ||
526 | rle_remainder = 0; | ||
527 | rlelen -= rle_this_bite; | ||
528 | my_clut = (clut_t*) img_overl->color; | ||
529 | my_trans = img_overl->trans; | ||
530 | xmask = 0; | ||
531 | } | ||
532 | } else if (x < clip_right) { | ||
533 | /* Starts inside clip area */ | ||
534 | if ((x + rle_remainder) > clip_right ) { | ||
535 | #ifdef LOG_BLEND_YUV | ||
536 | printf("Inside clip right %d, ending outside\n", clip_right); | ||
537 | #endif | ||
538 | /* Cutting needed, starts inside, ends outside */ | ||
539 | rle_this_bite = (clip_right - x); | ||
540 | rle_remainder -= rle_this_bite; | ||
541 | rlelen -= rle_this_bite; | ||
542 | my_clut = (clut_t*) img_overl->clip_color; | ||
543 | my_trans = img_overl->clip_trans; | ||
544 | xmask++; | ||
545 | } else { | ||
546 | #ifdef LOG_BLEND_YUV | ||
547 | printf("Inside clip right %d, ending inside\n", clip_right); | ||
548 | #endif | ||
549 | /* no cutting needed, starts inside, ends inside */ | ||
550 | rle_this_bite = rle_remainder; | ||
551 | rle_remainder = 0; | ||
552 | rlelen -= rle_this_bite; | ||
553 | my_clut = (clut_t*) img_overl->clip_color; | ||
554 | my_trans = img_overl->clip_trans; | ||
555 | xmask++; | ||
556 | } | ||
557 | } else if (x >= clip_right) { | ||
558 | /* Starts outside clip area, ends outsite clip area */ | ||
559 | if ((x + rle_remainder ) > src_width ) { | ||
560 | #ifdef LOG_BLEND_YUV | ||
561 | printf("Outside clip right %d, ending eol\n", clip_right); | ||
562 | #endif | ||
563 | /* Cutting needed, starts outside, ends at right edge */ | ||
564 | /* It should never reach here due to the earlier test of src_width */ | ||
565 | rle_this_bite = (src_width - x ); | ||
566 | rle_remainder -= rle_this_bite; | ||
567 | rlelen -= rle_this_bite; | ||
568 | my_clut = (clut_t*) img_overl->color; | ||
569 | my_trans = img_overl->trans; | ||
570 | xmask = 0; | ||
571 | } else { | ||
572 | /* no cutting needed, starts outside, ends outside */ | ||
573 | #ifdef LOG_BLEND_YUV | ||
574 | printf("Outside clip right %d, ending outside\n", clip_right); | ||
575 | #endif | ||
576 | rle_this_bite = rle_remainder; | ||
577 | rle_remainder = 0; | ||
578 | rlelen -= rle_this_bite; | ||
579 | my_clut = (clut_t*) img_overl->color; | ||
580 | my_trans = img_overl->trans; | ||
581 | xmask = 0; | ||
582 | } | ||
583 | } | ||
584 | } else { | ||
585 | /* Outside clip are due to y */ | ||
586 | /* no cutting needed, starts outside, ends outside */ | ||
587 | rle_this_bite = rle_remainder; | ||
588 | rle_remainder = 0; | ||
589 | rlelen -= rle_this_bite; | ||
590 | my_clut = (clut_t*) img_overl->color; | ||
591 | my_trans = img_overl->trans; | ||
592 | xmask = 0; | ||
593 | } | ||
594 | o = my_trans[clr]; | ||
595 | #ifdef LOG_BLEND_YUV | ||
596 | printf("Trans=%d clr=%d xmask=%d my_clut[clr]=%d\n",o, clr, xmask, my_clut[clr].y); | ||
597 | #endif | ||
598 | if (o) { | ||
599 | if(o >= 15) { | ||
600 | memset(dst_y + x, my_clut[clr].y, rle_this_bite); | ||
601 | if (y & 1) { | ||
602 | memset(dst_cr + (x >> 1), my_clut[clr].cr, (rle_this_bite+1) >> 1); | ||
603 | memset(dst_cb + (x >> 1), my_clut[clr].cb, (rle_this_bite+1) >> 1); | ||
604 | } | ||
605 | } else { | ||
606 | mem_blend8(dst_y + x, my_clut[clr].y, o, rle_this_bite); | ||
607 | if (y & 1) { | ||
608 | /* Blending cr and cb should use a different function, with pre -128 to each sample */ | ||
609 | mem_blend8(dst_cr + (x >> 1), my_clut[clr].cr, o, (rle_this_bite+1) >> 1); | ||
610 | mem_blend8(dst_cb + (x >> 1), my_clut[clr].cb, o, (rle_this_bite+1) >> 1); | ||
611 | } | ||
612 | } | ||
613 | |||
614 | } | ||
615 | #ifdef LOG_BLEND_YUV | ||
616 | printf("rle_this_bite=%d, remainder=%d, x=%d\n",rle_this_bite, rle_remainder, x); | ||
617 | #endif | ||
618 | x += rle_this_bite; | ||
619 | if (rle >= rle_limit) { | ||
620 | #ifdef LOG_BLEND_YUV | ||
621 | printf("x-rle_limit\n"); | ||
622 | #endif | ||
623 | break; | ||
624 | } | ||
625 | } | ||
626 | if (rle >= rle_limit) { | ||
627 | #ifdef LOG_BLEND_YUV | ||
628 | printf("x-rle_limit\n"); | ||
629 | #endif | ||
630 | break; | ||
631 | } | ||
632 | |||
633 | dst_y += dst_width; | ||
634 | |||
635 | if (y & 1) { | ||
636 | dst_cr += (dst_width + 1) / 2; | ||
637 | dst_cb += (dst_width + 1) / 2; | ||
638 | } | ||
639 | } | ||
640 | #ifdef LOG_BLEND_YUV | ||
641 | printf("overlay_blend ended\n"); | ||
642 | #endif | ||
643 | } | ||
644 | |||
645 | void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, | ||
646 | int dst_width, int dst_height) | ||
647 | { | ||
648 | clut_t *my_clut; | ||
649 | uint8_t *my_trans; | ||
650 | |||
651 | int src_width = img_overl->width; | ||
652 | int src_height = img_overl->height; | ||
653 | rle_elem_t *rle = img_overl->rle; | ||
654 | rle_elem_t *rle_limit = rle + img_overl->num_rle; | ||
655 | int x_off = img_overl->x; | ||
656 | int y_off = img_overl->y; | ||
657 | int mask; | ||
658 | int x, y; | ||
659 | int l; | ||
660 | int clip_right; | ||
661 | uint32_t yuy2; | ||
662 | |||
663 | uint8_t *dst_y = dst_img + 2 * (dst_width * y_off + x_off); | ||
664 | uint8_t *dst; | ||
665 | |||
666 | my_clut = (clut_t*) img_overl->clip_color; | ||
667 | my_trans = img_overl->clip_trans; | ||
668 | |||
669 | /* avoid wraping overlay if drawing to small image */ | ||
670 | if( (x_off + img_overl->clip_right) < dst_width ) | ||
671 | clip_right = img_overl->clip_right; | ||
672 | else | ||
673 | clip_right = dst_width - 1 - x_off; | ||
674 | |||
675 | /* avoid buffer overflow */ | ||
676 | if( (src_height + y_off) >= dst_height ) | ||
677 | src_height = dst_height - 1 - y_off; | ||
678 | |||
679 | for (y = 0; y < src_height; y++) { | ||
680 | mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); | ||
681 | |||
682 | dst = dst_y; | ||
683 | for (x = 0; x < src_width;) { | ||
684 | uint8_t clr; | ||
685 | uint16_t o; | ||
686 | int rlelen; | ||
687 | |||
688 | clr = rle->color; | ||
689 | o = my_trans[clr]; | ||
690 | rlelen = rle->len; | ||
691 | |||
692 | if (o && mask) { | ||
693 | /* threat cases where clipping border is inside rle->len pixels */ | ||
694 | if ( img_overl->clip_left > x ) { | ||
695 | if( img_overl->clip_left < x + rlelen ) { | ||
696 | rlelen -= img_overl->clip_left - x; | ||
697 | x += img_overl->clip_left - x; | ||
698 | } else { | ||
699 | o = 0; | ||
700 | } | ||
701 | } else if( clip_right < x + rlelen ) { | ||
702 | if( clip_right > x ) { | ||
703 | /* fixme: case not implemented */ | ||
704 | o = 0; | ||
705 | } else { | ||
706 | o = 0; | ||
707 | } | ||
708 | } | ||
709 | } | ||
710 | |||
711 | |||
712 | if (o && mask) { | ||
713 | l = rlelen>>1; | ||
714 | if( !(x & 1) ) { | ||
715 | yuy2 = my_clut[clr].y + (my_clut[clr].cb << 8) + | ||
716 | (my_clut[clr].y << 16) + (my_clut[clr].cr << 24); | ||
717 | } else { | ||
718 | yuy2 = my_clut[clr].y + (my_clut[clr].cr << 8) + | ||
719 | (my_clut[clr].y << 16) + (my_clut[clr].cb << 24); | ||
720 | } | ||
721 | |||
722 | if (o >= 15) { | ||
723 | while(l--) { | ||
724 | *((uint32_t *)dst)++ = yuy2; | ||
725 | } | ||
726 | if(rlelen & 1) | ||
727 | *((uint16_t *)dst)++ = yuy2 & 0xffff; | ||
728 | } else { | ||
729 | if( l ) { | ||
730 | mem_blend32(dst, (uint8_t *)&yuy2, o, l); | ||
731 | dst += 4*l; | ||
732 | } | ||
733 | |||
734 | if(rlelen & 1) { | ||
735 | *dst = BLEND_BYTE(*dst, *((uint8_t *)&yuy2), o); | ||
736 | dst++; | ||
737 | *dst = BLEND_BYTE(*dst, *((uint8_t *)&yuy2+1), o); | ||
738 | dst++; | ||
739 | } | ||
740 | } | ||
741 | } else { | ||
742 | dst += rlelen*2; | ||
743 | } | ||
744 | |||
745 | x += rlelen; | ||
746 | rle++; | ||
747 | if (rle >= rle_limit) break; | ||
748 | } | ||
749 | if (rle >= rle_limit) break; | ||
750 | |||
751 | dst_y += dst_width*2; | ||
752 | } | ||
753 | } | ||