1 #include "common.h"
2
3 #include <math.h>
4
5 #include "blend.h"
6 #include "colormod.h"
7 #include "image.h"
8 #include "rgbadraw.h"
9 #include "scale.h"
10 #include "updates.h"
11
12 void
__imlib_FlipImageHoriz(ImlibImage * im)13 __imlib_FlipImageHoriz(ImlibImage * im)
14 {
15 DATA32 *p1, *p2, tmp;
16 int x, y;
17
18 for (y = 0; y < im->h; y++)
19 {
20 p1 = im->data + (y * im->w);
21 p2 = im->data + ((y + 1) * im->w) - 1;
22 for (x = 0; x < (im->w >> 1); x++)
23 {
24 tmp = *p1;
25 *p1 = *p2;
26 *p2 = tmp;
27 p1++;
28 p2--;
29 }
30 }
31 x = im->border.left;
32 im->border.left = im->border.right;
33 im->border.right = x;
34 }
35
36 void
__imlib_FlipImageVert(ImlibImage * im)37 __imlib_FlipImageVert(ImlibImage * im)
38 {
39 DATA32 *p1, *p2, tmp;
40 int x, y;
41
42 for (y = 0; y < (im->h >> 1); y++)
43 {
44 p1 = im->data + (y * im->w);
45 p2 = im->data + ((im->h - 1 - y) * im->w);
46 for (x = 0; x < im->w; x++)
47 {
48 tmp = *p1;
49 *p1 = *p2;
50 *p2 = tmp;
51 p1++;
52 p2++;
53 }
54 }
55 x = im->border.top;
56 im->border.top = im->border.bottom;
57 im->border.bottom = x;
58 }
59
60 void
__imlib_FlipImageBoth(ImlibImage * im)61 __imlib_FlipImageBoth(ImlibImage * im)
62 {
63 DATA32 *p1, *p2, tmp;
64 int x;
65
66 p1 = im->data;
67 p2 = im->data + (im->h * im->w) - 1;
68 for (x = (im->w * im->h) / 2; --x >= 0;)
69 {
70 tmp = *p1;
71 *p1 = *p2;
72 *p2 = tmp;
73 p1++;
74 p2--;
75 }
76 x = im->border.top;
77 im->border.top = im->border.bottom;
78 im->border.bottom = x;
79 x = im->border.left;
80 im->border.left = im->border.right;
81 im->border.right = x;
82 }
83
84 /*\ Directions (source is right/down):
85 |*| 0 = down/right (flip over ul-dr diagonal)
86 |*| 1 = down/left (rotate 90 degrees clockwise)
87 |*| 2 = up/right (rotate 90 degrees counterclockwise)
88 |*| 3 = up/left (flip over ur-ll diagonal)
89 \*/
90 void
__imlib_FlipImageDiagonal(ImlibImage * im,int direction)91 __imlib_FlipImageDiagonal(ImlibImage * im, int direction)
92 {
93 DATA32 *data, *to, *from;
94 int x, y, w, hw, tmp;
95
96 data = malloc(im->w * im->h * sizeof(DATA32));
97 from = im->data;
98 w = im->h;
99 im->h = im->w;
100 im->w = w;
101 hw = w * im->h;
102 switch (direction)
103 {
104 default:
105 case 0: /*\ DOWN_RIGHT \ */
106 tmp = im->border.top;
107 im->border.top = im->border.left;
108 im->border.left = tmp;
109 tmp = im->border.bottom;
110 im->border.bottom = im->border.right;
111 im->border.right = tmp;
112 to = data;
113 hw = -hw + 1;
114 break;
115 case 1: /*\ DOWN_LEFT \ */
116 tmp = im->border.top;
117 im->border.top = im->border.left;
118 im->border.left = im->border.bottom;
119 im->border.bottom = im->border.right;
120 im->border.right = tmp;
121 to = data + w - 1;
122 hw = -hw - 1;
123 break;
124 case 2: /*\ UP_RIGHT \ */
125 tmp = im->border.top;
126 im->border.top = im->border.right;
127 im->border.right = im->border.bottom;
128 im->border.bottom = im->border.left;
129 im->border.left = tmp;
130 to = data + hw - w;
131 w = -w;
132 hw = hw + 1;
133 break;
134 case 3: /*\ UP_LEFT \ */
135 tmp = im->border.top;
136 im->border.top = im->border.right;
137 im->border.right = tmp;
138 tmp = im->border.bottom;
139 im->border.bottom = im->border.left;
140 im->border.left = tmp;
141 to = data + hw - 1;
142 w = -w;
143 hw = hw - 1;
144 break;
145 }
146 from = im->data;
147 for (x = im->w; --x >= 0;)
148 {
149 for (y = im->h; --y >= 0;)
150 {
151 *to = *from;
152 from++;
153 to += w;
154 }
155 to += hw;
156 }
157 __imlib_ReplaceData(im, data);
158 }
159
160 void
__imlib_BlurImage(ImlibImage * im,int rad)161 __imlib_BlurImage(ImlibImage * im, int rad)
162 {
163 DATA32 *p1, *p2, *data;
164 int x, y, mx, my, mw, mh, mt, xx, yy;
165 int a, r, g, b;
166 int *as, *rs, *gs, *bs;
167
168 if (rad < 1)
169 return;
170 data = malloc(im->w * im->h * sizeof(DATA32));
171 as = malloc(sizeof(int) * im->w);
172 rs = malloc(sizeof(int) * im->w);
173 gs = malloc(sizeof(int) * im->w);
174 bs = malloc(sizeof(int) * im->w);
175
176 for (y = 0; y < im->h; y++)
177 {
178 my = y - rad;
179 mh = (rad << 1) + 1;
180 if (my < 0)
181 {
182 mh += my;
183 my = 0;
184 }
185 if ((my + mh) > im->h)
186 mh = im->h - my;
187
188 p1 = data + (y * im->w);
189 memset(as, 0, im->w * sizeof(int));
190 memset(rs, 0, im->w * sizeof(int));
191 memset(gs, 0, im->w * sizeof(int));
192 memset(bs, 0, im->w * sizeof(int));
193
194 for (yy = 0; yy < mh; yy++)
195 {
196 p2 = im->data + ((yy + my) * im->w);
197 for (x = 0; x < im->w; x++)
198 {
199 as[x] += (*p2 >> 24) & 0xff;
200 rs[x] += (*p2 >> 16) & 0xff;
201 gs[x] += (*p2 >> 8) & 0xff;
202 bs[x] += *p2 & 0xff;
203 p2++;
204 }
205 }
206 if (im->w > ((rad << 1) + 1))
207 {
208 for (x = 0; x < im->w; x++)
209 {
210 a = 0;
211 r = 0;
212 g = 0;
213 b = 0;
214 mx = x - rad;
215 mw = (rad << 1) + 1;
216 if (mx < 0)
217 {
218 mw += mx;
219 mx = 0;
220 }
221 if ((mx + mw) > im->w)
222 mw = im->w - mx;
223 mt = mw * mh;
224 for (xx = mx; xx < (mw + mx); xx++)
225 {
226 a += as[xx];
227 r += rs[xx];
228 g += gs[xx];
229 b += bs[xx];
230 }
231 a = a / mt;
232 r = r / mt;
233 g = g / mt;
234 b = b / mt;
235 *p1 = PIXEL_ARGB(a, r, g, b);
236 p1++;
237 }
238 }
239 else
240 {
241 }
242 }
243 free(as);
244 free(rs);
245 free(gs);
246 free(bs);
247 __imlib_ReplaceData(im, data);
248 }
249
250 void
__imlib_SharpenImage(ImlibImage * im,int rad)251 __imlib_SharpenImage(ImlibImage * im, int rad)
252 {
253 DATA32 *data, *p1, *p2;
254 int a, r, g, b, x, y;
255
256 data = malloc(im->w * im->h * sizeof(DATA32));
257 if (rad == 0)
258 return;
259 else
260 {
261 for (y = 1; y < (im->h - 1); y++)
262 {
263 p1 = im->data + 1 + (y * im->w);
264 p2 = data + 1 + (y * im->w);
265 for (x = 1; x < (im->w - 1); x++)
266 {
267 b = (int)((p1[0]) & 0xff) * 5;
268 g = (int)((p1[0] >> 8) & 0xff) * 5;
269 r = (int)((p1[0] >> 16) & 0xff) * 5;
270 a = (int)((p1[0] >> 24) & 0xff) * 5;
271 b -= (int)((p1[-1]) & 0xff);
272 g -= (int)((p1[-1] >> 8) & 0xff);
273 r -= (int)((p1[-1] >> 16) & 0xff);
274 a -= (int)((p1[-1] >> 24) & 0xff);
275 b -= (int)((p1[1]) & 0xff);
276 g -= (int)((p1[1] >> 8) & 0xff);
277 r -= (int)((p1[1] >> 16) & 0xff);
278 a -= (int)((p1[1] >> 24) & 0xff);
279 b -= (int)((p1[-im->w]) & 0xff);
280 g -= (int)((p1[-im->w] >> 8) & 0xff);
281 r -= (int)((p1[-im->w] >> 16) & 0xff);
282 a -= (int)((p1[-im->w] >> 24) & 0xff);
283 b -= (int)((p1[im->w]) & 0xff);
284 g -= (int)((p1[im->w] >> 8) & 0xff);
285 r -= (int)((p1[im->w] >> 16) & 0xff);
286 a -= (int)((p1[im->w] >> 24) & 0xff);
287
288 a = (a & ((~a) >> 16));
289 a = ((a | ((a & 256) - ((a & 256) >> 8))));
290 r = (r & ((~r) >> 16));
291 r = ((r | ((r & 256) - ((r & 256) >> 8))));
292 g = (g & ((~g) >> 16));
293 g = ((g | ((g & 256) - ((g & 256) >> 8))));
294 b = (b & ((~b) >> 16));
295 b = ((b | ((b & 256) - ((b & 256) >> 8))));
296
297 *p2 = PIXEL_ARGB(a, r, g, b);
298 p2++;
299 p1++;
300 }
301 }
302 }
303 __imlib_ReplaceData(im, data);
304 }
305
306 void
__imlib_TileImageHoriz(ImlibImage * im)307 __imlib_TileImageHoriz(ImlibImage * im)
308 {
309 DATA32 *p1, *p2, *p3, *p, *data;
310 int x, y, per, tmp, na, nr, ng, nb, mix, a, r, g, b, aa, rr,
311 gg, bb;
312
313 data = malloc(im->w * im->h * sizeof(DATA32));
314 p1 = im->data;
315 p = data;
316 for (y = 0; y < im->h; y++)
317 {
318 p2 = p1 + (im->w >> 1);
319 p3 = p1;
320 per = (im->w >> 1);
321 for (x = 0; x < (im->w >> 1); x++)
322 {
323 mix = (x * 255) / per;
324 b = (*p1) & 0xff;
325 g = (*p1 >> 8) & 0xff;
326 r = (*p1 >> 16) & 0xff;
327 a = (*p1 >> 24) & 0xff;
328
329 bb = (*p2) & 0xff;
330 gg = (*p2 >> 8) & 0xff;
331 rr = (*p2 >> 16) & 0xff;
332 aa = (*p2 >> 24) & 0xff;
333
334 tmp = (r - rr) * mix;
335 nr = rr + ((tmp + (tmp >> 8) + 0x80) >> 8);
336 tmp = (g - gg) * mix;
337 ng = gg + ((tmp + (tmp >> 8) + 0x80) >> 8);
338 tmp = (b - bb) * mix;
339 nb = bb + ((tmp + (tmp >> 8) + 0x80) >> 8);
340 tmp = (a - aa) * mix;
341 na = aa + ((tmp + (tmp >> 8) + 0x80) >> 8);
342 *p = PIXEL_ARGB(na, nr, ng, nb);
343 p++;
344 p1++;
345 p2++;
346 }
347 p2 = p3;
348 per = (im->w - (im->w >> 1));
349 for (; x < im->w; x++)
350 {
351 mix = ((im->w - 1 - x) * 255) / per;
352 b = (*p1) & 0xff;
353 g = (*p1 >> 8) & 0xff;
354 r = (*p1 >> 16) & 0xff;
355 a = (*p1 >> 24) & 0xff;
356
357 bb = (*p2) & 0xff;
358 gg = (*p2 >> 8) & 0xff;
359 rr = (*p2 >> 16) & 0xff;
360 aa = (*p2 >> 24) & 0xff;
361
362 tmp = (r - rr) * mix;
363 nr = rr + ((tmp + (tmp >> 8) + 0x80) >> 8);
364 tmp = (g - gg) * mix;
365 ng = gg + ((tmp + (tmp >> 8) + 0x80) >> 8);
366 tmp = (b - bb) * mix;
367 nb = bb + ((tmp + (tmp >> 8) + 0x80) >> 8);
368 tmp = (a - aa) * mix;
369 na = aa + ((tmp + (tmp >> 8) + 0x80) >> 8);
370 *p = PIXEL_ARGB(na, nr, ng, nb);
371 p++;
372 p1++;
373 p2++;
374 }
375 }
376 __imlib_ReplaceData(im, data);
377 }
378
379 void
__imlib_TileImageVert(ImlibImage * im)380 __imlib_TileImageVert(ImlibImage * im)
381 {
382 DATA32 *p1, *p2, *p, *data;
383 int x, y, tmp, na, nr, ng, nb, mix, a, r, g, b, aa, rr, gg,
384 bb;
385
386 data = malloc(im->w * im->h * sizeof(DATA32));
387 p = data;
388 for (y = 0; y < im->h; y++)
389 {
390 p1 = im->data + (y * im->w);
391 if (y < (im->h >> 1))
392 {
393 p2 = im->data + ((y + (im->h >> 1)) * im->w);
394 mix = (y * 255) / (im->h >> 1);
395 }
396 else
397 {
398 p2 = im->data + ((y - (im->h >> 1)) * im->w);
399 mix = ((im->h - y) * 255) / (im->h - (im->h >> 1));
400 }
401 for (x = 0; x < im->w; x++)
402 {
403 b = (*p1) & 0xff;
404 g = (*p1 >> 8) & 0xff;
405 r = (*p1 >> 16) & 0xff;
406 a = (*p1 >> 24) & 0xff;
407
408 bb = (*p2) & 0xff;
409 gg = (*p2 >> 8) & 0xff;
410 rr = (*p2 >> 16) & 0xff;
411 aa = (*p2 >> 24) & 0xff;
412
413 tmp = (r - rr) * mix;
414 nr = rr + ((tmp + (tmp >> 8) + 0x80) >> 8);
415 tmp = (g - gg) * mix;
416 ng = gg + ((tmp + (tmp >> 8) + 0x80) >> 8);
417 tmp = (b - bb) * mix;
418 nb = bb + ((tmp + (tmp >> 8) + 0x80) >> 8);
419 tmp = (a - aa) * mix;
420 na = aa + ((tmp + (tmp >> 8) + 0x80) >> 8);
421 *p = PIXEL_ARGB(na, nr, ng, nb);
422 p++;
423 p1++;
424 p2++;
425 }
426 }
427 __imlib_ReplaceData(im, data);
428 }
429
430 void
__imlib_copy_image_data(ImlibImage * im,int x,int y,int w,int h,int nx,int ny)431 __imlib_copy_image_data(ImlibImage * im, int x, int y, int w, int h, int nx,
432 int ny)
433 {
434 int xx, yy, jump;
435 DATA32 *p1, *p2;
436
437 /* clip horizontal co-ordinates so that both dest and src fit inside */
438 /* the image */
439 if (x < 0)
440 {
441 w += x;
442 nx -= x;
443 x = 0;
444 }
445 if (w <= 0)
446 return;
447 if (nx < 0)
448 {
449 w += nx;
450 x -= nx;
451 nx = 0;
452 }
453 if (w <= 0)
454 return;
455 if ((x + w) > im->w)
456 w = (im->w - x);
457 if (w <= 0)
458 return;
459 if ((nx + w) > im->w)
460 w = (im->w - nx);
461 if (w <= 0)
462 return;
463 /* clip vertical co-ordinates so that both dest and src fit inside */
464 /* the image */
465 if (y < 0)
466 {
467 h += y;
468 ny -= y;
469 y = 0;
470 }
471 if (h <= 0)
472 return;
473 if (ny < 0)
474 {
475 h += ny;
476 y -= ny;
477 ny = 0;
478 }
479 if (h <= 0)
480 return;
481 if ((y + h) > im->h)
482 h = (im->h - y);
483 if (h <= 0)
484 return;
485 if ((ny + h) > im->h)
486 h = (im->h - ny);
487 if (h <= 0)
488 return;
489
490 /* figure out what our source and destnation start pointers are */
491 p1 = im->data + (y * im->w) + x;
492 p2 = im->data + (ny * im->w) + nx;
493 /* the pointer jump between lines */
494 jump = (im->w - w);
495 /* dest < src address - we can copy forwards */
496 if (p2 < p1)
497 {
498 /* work our way thru the array */
499 for (yy = 0; yy < h; yy++)
500 {
501 for (xx = 0; xx < w; xx++)
502 {
503 *p2 = *p1;
504 p1++;
505 p2++;
506 }
507 p1 += jump;
508 p2 += jump;
509 }
510 }
511 /* dst > src - we must copy backwards */
512 else
513 {
514 /* new pointers to start working at (bottom-right of rect) */
515 p1 = im->data + ((y + h - 1) * im->w) + x + w - 1;
516 p2 = im->data + ((ny + h - 1) * im->w) + nx + w - 1;
517 /* work our way thru the array */
518 for (yy = 0; yy < h; yy++)
519 {
520 for (xx = 0; xx < w; xx++)
521 {
522 *p2 = *p1;
523 p1--;
524 p2--;
525 }
526 p1 -= jump;
527 p2 -= jump;
528 }
529 }
530 }
531
532 void
__imlib_copy_alpha_data(ImlibImage * src,ImlibImage * dst,int x,int y,int w,int h,int nx,int ny)533 __imlib_copy_alpha_data(ImlibImage * src, ImlibImage * dst, int x, int y,
534 int w, int h, int nx, int ny)
535 {
536 int xx, yy, jump, jump2;
537 DATA32 *p1, *p2;
538
539 /* clip horizontal co-ordinates so that both dest and src fit inside */
540 /* the image */
541 if (x < 0)
542 {
543 w += x;
544 nx -= x;
545 x = 0;
546 }
547 if (w <= 0)
548 return;
549 if (nx < 0)
550 {
551 w += nx;
552 x -= nx;
553 nx = 0;
554 }
555 if (w <= 0)
556 return;
557 if ((x + w) > src->w)
558 w = (src->w - x);
559 if (w <= 0)
560 return;
561 if ((nx + w) > dst->w)
562 w = (dst->w - nx);
563 if (w <= 0)
564 return;
565 /* clip vertical co-ordinates so that both dest and src fit inside */
566 /* the image */
567 if (y < 0)
568 {
569 h += y;
570 ny -= y;
571 y = 0;
572 }
573 if (h <= 0)
574 return;
575 if (ny < 0)
576 {
577 h += ny;
578 y -= ny;
579 ny = 0;
580 }
581 if (h <= 0)
582 return;
583 if ((y + h) > src->h)
584 h = (src->h - y);
585 if (h <= 0)
586 return;
587 if ((ny + h) > dst->h)
588 h = (dst->h - ny);
589 if (h <= 0)
590 return;
591
592 /* figure out what our source and destnation start pointers are */
593 p1 = src->data + (y * src->w) + x;
594 p2 = dst->data + (ny * dst->w) + nx;
595 /* the pointer jump between lines */
596 jump = (src->w - w);
597 jump2 = (dst->w - w);
598
599 /* work our way thru the array */
600 for (yy = 0; yy < h; yy++)
601 {
602 for (xx = 0; xx < w; xx++)
603 {
604 *p2 = (*p1 & 0xff000000) | (*p2 & 0x00ffffff);
605 p1++;
606 p2++;
607 }
608 p1 += jump;
609 p2 += jump2;
610 }
611 }
612