1 /*
2  * This software is copyrighted as noted below.  It may be freely copied,
3  * modified, and redistributed, provided that the copyright notice is
4  * preserved on all copies.
5  *
6  * There is no warranty or other guarantee of fitness for this software,
7  * it is provided solely "as is".  Bug reports or fixes may be sent
8  * to the author, who may or may not act on them as he desires.
9  *
10  * You may not include this software in a program or other software product
11  * without supplying the source, or without informing the end-user that the
12  * source is available for no extra charge.
13  *
14  * If you modify this software, you should include a notice giving the
15  * name of the person performing the modification, the date of modification,
16  * and the reason for such modification.
17  */
18 /*
19  * mask.c - perform transformations using masks.
20  *
21  * Author:      Raul Rivero
22  *              Mathematics Dept.
23  *              University of Oviedo
24  * Date:        Mon Jan 6 1992
25  * Copyright (c) 1992, Raul Rivero
26  *
27  */
28 
29 #include <lug.h>
30 #include <lugfnts.h>
31 #define BLUETOP                 175
32 
33 #define mvptrs()        rb++, gb++, bb++; rm++, gm++, bm++; rs++, gs++, bs++;
34 
chroma_mask(base,mask,super,outbitmap)35 chroma_mask( base, mask, super, outbitmap )
36 bitmap_hdr *base, *mask, *super;
37 bitmap_hdr *outbitmap;
38 {
39   byte *rb, *gb, *bb;           /* base pointers */
40   byte *rm, *gm, *bm;           /* base mask */
41   byte *rs, *gs, *bs;           /* base super*/
42   byte *r, *g, *b;
43   byte *end;
44   double position;
45   int totalsize;
46 
47   /*
48    * Fill our new header and allocate memory.
49    */
50   outbitmap->magic = LUGUSED;
51   outbitmap->xsize = base->xsize;
52   outbitmap->ysize = base->ysize;
53   outbitmap->depth = base->depth;
54   outbitmap->colors = base->colors;
55   totalsize = outbitmap->xsize * outbitmap->ysize;
56   r = outbitmap->r = (byte *) Malloc( totalsize );
57   g = outbitmap->g = (byte *) Malloc( totalsize );
58   b = outbitmap->b = (byte *) Malloc( totalsize );
59 
60   /*
61    * Set the pointers.
62    */
63   rb = base->r  , gb = base->g  , bb = base->b;
64   rm = mask->r  , gm = mask->g  , bm = mask->b;
65   rs = super->r , gs = super->g , bs = super->b;
66 
67   end = r + totalsize;
68   while ( r < end ) {
69     if ( (*rm + *gm + *bm) > CHROMAMASK ) {
70       /*
71        * The current point has red as component, then we
72        * change this point with the super current point.
73        */
74       *r++ = *rs;
75       *g++ = *gs;
76       *b++ = *bs;
77       mvptrs();
78     }else {
79       *r++ = *rb;
80       *g++ = *gb;
81       *b++ = *bb;
82       mvptrs();
83     }
84   }
85 
86   /* No errors */
87   return 0;
88 }
89 
chroma_shadow_mask(base,mask,super,outbitmap)90 chroma_shadow_mask( base, mask, super, outbitmap )
91 bitmap_hdr *base, *mask, *super;
92 bitmap_hdr *outbitmap;
93 {
94   byte *rb, *gb, *bb;           /* base pointers */
95   byte *rm, *gm, *bm;           /* base mask */
96   byte *rs, *gs, *bs;           /* base super*/
97   byte *r, *g, *b;
98   byte *end;
99   double position;
100   int totalsize;
101 
102   if ( base->magic != LUGUSED || mask->magic != LUGUSED )
103     error( 19 );
104 
105   /*
106    * Fill our new header and allocate memory.
107    */
108   outbitmap->magic = LUGUSED;
109   outbitmap->xsize = base->xsize;
110   outbitmap->ysize = base->ysize;
111   outbitmap->depth = base->depth;
112   outbitmap->colors = base->colors;
113   totalsize = outbitmap->xsize * outbitmap->ysize;
114   r = outbitmap->r = (byte *) Malloc( totalsize );
115   g = outbitmap->g = (byte *) Malloc( totalsize );
116   b = outbitmap->b = (byte *) Malloc( totalsize );
117 
118   /*
119    * Set the pointers.
120    */
121   rb = base->r  , gb = base->g  , bb = base->b;
122   rm = mask->r  , gm = mask->g  , bm = mask->b;
123   rs = super->r , gs = super->g , bs = super->b;
124 
125   end = r + totalsize;
126   while ( r < end ) {
127     if ( *rm > 0 ) {
128       /*
129        * The current point has red as component, then we
130        * change this point with the super current point.
131        */
132       *r++ = *rs;
133       *g++ = *gs;
134       *b++ = *bs;
135       mvptrs();
136     }else {
137       if ( *bm > BLUETOP ) {
138         /*
139          * If the current blue is greater than BLUETOP then
140          * we change this pixel with the current base pixel.
141          */
142         *r++ = *rb;
143         *g++ = *gb;
144         *b++ = *bb;
145         mvptrs();
146       }else {
147         /*
148          * Well ... we have a shadow !!!, so we darken
149          * the current base pixel.
150          */
151         position = *bm / 255.;
152         *r++ = (byte) ( *rb * position );
153         *g++ = (byte) ( *gb * position );
154         *b++ = (byte) ( *bb * position );
155         mvptrs();
156       }
157     }
158   }
159 
160   /* No errors */
161   return 0;
162 }
163 
mask_change_color(base,mask,outbitmap,newr,newg,newb)164 mask_change_color( base, mask, outbitmap, newr, newg, newb )
165 bitmap_hdr *base, *mask, *outbitmap;
166 int newr, newg, newb;
167 {
168   byte *rb, *gb, *bb;           /* base pointers */
169   byte *rm, *gm, *bm;           /* base mask */
170   byte *r, *g, *b;
171   byte *end;
172   int totalsize;
173   double newh, news, newl;
174   double h, s, l;
175 
176   if ( base->xsize != mask->xsize || base->ysize != mask->ysize )
177     error( 9 );
178 
179   /*
180    * Translate new color ( rgb ) to hsl format.
181    */
182   RGB_to_HSL( newr, newg, newb, &newh, &news, &newl );
183 
184   /*
185    * Fill our new header and allocate memory.
186    */
187   outbitmap->magic = LUGUSED;
188   outbitmap->xsize = base->xsize;
189   outbitmap->ysize = base->ysize;
190   outbitmap->depth = base->depth;
191   outbitmap->colors = base->colors;
192   totalsize = outbitmap->xsize * outbitmap->ysize;
193   r = outbitmap->r = (byte *) Malloc( totalsize );
194   g = outbitmap->g = (byte *) Malloc( totalsize );
195   b = outbitmap->b = (byte *) Malloc( totalsize );
196 
197   /*
198    * Set the pointers.
199    */
200   rb = base->r  , gb = base->g, bb = base->b;
201   rm = mask->r  , gm = mask->g, bm = mask->b;
202 
203   end = r + totalsize;
204   while ( r < end ) {
205     if ( ( (*rm++) + (*gm++) + (*bm++) ) > CHROMAMASK ) {
206       /*
207        * The mask has been actived, so we need change
208        * this pixel with our new color.
209        */
210       RGB_to_HSL( *rb++, *gb++, *bb++, &h, &s, &l );
211       HSL_to_RGB( newh, news, l, r++, g++, b++ );
212     }else {
213       /*
214        * No mask, so we copy the base image.
215        */
216       *r++ = *rb++;
217       *g++ = *gb++;
218        *b++ = *bb++;
219     }
220   }
221 
222   /* No errors */
223   return 0;
224 }
225 
mask_change_to_bw(base,mask,outbitmap)226 mask_change_to_bw( base, mask, outbitmap )
227 bitmap_hdr *base, *mask, *outbitmap;
228 {
229   byte *rb, *gb, *bb;           /* base pointers */
230   byte *rm, *gm, *bm;           /* base mask */
231   byte *r, *g, *b;
232   byte *end;
233   int totalsize;
234   int value;
235 
236   if ( base->xsize != mask->xsize || base->ysize != mask->ysize )
237     error( 9 );
238 
239   /*
240    * Fill our new header and allocate memory.
241    */
242   outbitmap->magic = LUGUSED;
243   outbitmap->xsize = base->xsize;
244   outbitmap->ysize = base->ysize;
245   outbitmap->depth = base->depth;
246   outbitmap->colors = base->colors;
247   totalsize = outbitmap->xsize * outbitmap->ysize;
248   r = outbitmap->r = (byte *) Malloc( totalsize );
249   g = outbitmap->g = (byte *) Malloc( totalsize );
250   b = outbitmap->b = (byte *) Malloc( totalsize );
251 
252   /*
253    * Set the pointers.
254    */
255   rb = base->r  , gb = base->g, bb = base->b;
256   rm = mask->r  , gm = mask->g, bm = mask->b;
257 
258   end = r + totalsize;
259   while ( r < end ) {
260     if ( ( (*rm++) + (*gm++) + (*bm++) ) > CHROMAMASK ) {
261       /*
262        * The mask has been actived, so we need change
263        * this pixel with our new color.
264        */
265       value = RGB_to_BW( *rb++, *gb++, *bb++ );
266       *r++ = value;
267       *g++ = value;
268       *b++ = value;
269     }else {
270       /*
271        * No mask, so we copy the base image.
272        */
273       *r++ = *rb++;
274       *g++ = *gb++;
275       *b++ = *bb++;
276     }
277   }
278 
279   /* No errors */
280   return 0;
281 }
282 
mask_darken_color(base,mask,outbitmap)283 mask_darken_color( base, mask, outbitmap )
284 bitmap_hdr *base, *mask, *outbitmap;
285 {
286   byte *rb, *gb, *bb;           /* base pointers */
287   byte *rm, *gm, *bm;           /* base mask */
288   byte *r, *g, *b;
289   byte *end;
290   int totalsize;
291   double h, s, l;
292 
293   if ( base->xsize != mask->xsize || base->ysize != mask->ysize )
294     error( 9 );
295 
296   /*
297    * Fill our new header and allocate memory.
298    */
299   outbitmap->magic = LUGUSED;
300   outbitmap->xsize = base->xsize;
301   outbitmap->ysize = base->ysize;
302   outbitmap->depth = base->depth;
303   outbitmap->colors = base->colors;
304   totalsize = outbitmap->xsize * outbitmap->ysize;
305   r = outbitmap->r = (byte *) Malloc( totalsize );
306   g = outbitmap->g = (byte *) Malloc( totalsize );
307   b = outbitmap->b = (byte *) Malloc( totalsize );
308 
309   /*
310    * Set the pointers.
311    */
312   rb = base->r  , gb = base->g, bb = base->b;
313   rm = mask->r  , gm = mask->g, bm = mask->b;
314 
315   end = r + totalsize;
316   while ( r < end ) {
317     if ( ( (*rm++) + (*gm++) + (*bm++) ) > CHROMAMASK ) {
318       /*
319        * The mask has been actived, so we need change
320        * this pixel with our new color.
321        */
322       RGB_to_HSL( *rb++, *gb++, *bb++, &h, &s, &l );
323       HSL_to_RGB( h, s/2., l/1.5, r++, g++, b++ );
324     }else {
325       /*
326        * No mask, so we copy the base image.
327        */
328       *r++ = *rb++;
329       *g++ = *gb++;
330       *b++ = *bb++;
331     }
332   }
333 
334   /* No errors */
335   return 0;
336 }
337 
fade_mask(base,super,mask,out)338 fade_mask( base, super, mask, out )
339 bitmap_hdr *base, *super, *mask;
340 bitmap_hdr *out;
341 {
342   byte *rb, *gb, *bb;           /* base pointers */
343   byte *rm, *gm, *bm;           /* mask pointers */
344   byte *rs, *gs, *bs;           /* super pointers */
345   byte *ro, *go, *bo;
346   byte *end;
347   double percent, neg_percent;
348   double aux;
349   int totalsize = base->xsize * base->ysize;
350 
351   /* We have images really ? */
352   if ( base->magic  != LUGUSED ||
353        super->magic != LUGUSED ||
354        mask->magic  != LUGUSED )
355     error( 19 );
356 
357   /*
358    * Check if the width and height of the input images are the
359    * same. A trick: add all values an multiply one by 3 ( it
360    * no perfect ... but almost ).
361    */
362   if ( (base->xsize + super->xsize + mask->xsize) != 3 * base->xsize )
363     error( 12 );
364   if ( (base->ysize + super->ysize + mask->ysize) != 3 * mask->ysize )
365     error( 12 );
366 
367   /* Create the new image ( alloc memory, fill the header, ... ) */
368   create_solid_image( out, base->xsize, base->ysize, 0, 0, 0 );
369 
370   /*
371    * Set the pointers.
372    */
373   rb = base->r  , gb = base->g  , bb = base->b;
374   rs = super->r , gs = super->g , bs = super->b;
375   rm = mask->r  , gm = mask->g  , bm = mask->b;
376   ro = out->r   , go = out->g   , bo = out->b;
377 
378   /* Lets go ! */
379   end = rb + totalsize;
380   while ( rb < end ) {
381     /*
382      * Calculate the percent of transparency.
383      */
384     percent = *rm++ / 255.;
385     neg_percent = 1. - percent;
386 
387     /*
388      * Ok, now we know what need from one and another image ( the
389      * percent and negate percent ), so ...
390      */
391     aux = percent * (double) *rb++ + neg_percent * (double) *rs++;
392     *ro++ = (int) aux;
393     aux = percent * (double) *gb++ + neg_percent * (double) *gs++;
394     *go++ = (int) aux;
395     aux = percent * (double) *bb++ + neg_percent * (double) *bs++;
396     *bo++ = (int) aux;
397   }
398 
399   /* No errors */
400   return 0;
401 }
402