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