]> git.sesse.net Git - mlt/blob - src/modules/lumas/luma.c
Luma and composite fixes
[mlt] / src / modules / lumas / luma.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <string.h>
5
6 typedef struct 
7 {
8         int type;
9         int w;
10         int h;
11         int bands;
12         int rband;
13         int vmirror;
14         int hmirror;
15         int dmirror;
16         int invert;
17         int offset;
18         int flip;
19         int flop;
20         int pflip;
21         int pflop;
22         int quart;
23         int rotate;
24 }
25 luma;
26
27 void luma_init( luma *this )
28 {
29         memset( this, 0, sizeof( luma ) );
30         this->type = 0;
31         this->w = 720;
32         this->h = 576;
33         this->bands = 1;
34         this->rband = 0;
35         this->vmirror = 0;
36         this->hmirror = 0;
37         this->dmirror = 0;
38         this->invert = 0;
39         this->offset = 0;
40         this->flip = 0;
41         this->flop = 0;
42         this->quart = 0;
43         this->pflop = 0;
44         this->pflip = 0;
45 }
46
47 static inline int sqrti( int n )
48 {
49     int p = 0;
50         int q = 1;
51         int r = n;
52         int h = 0;
53
54     while( q <= n ) 
55                 q = 4 * q;
56
57     while( q != 1 )
58     {
59         q = q / 4;
60         h = p + q;
61         p = p / 2;
62         if ( r >= h )
63         {
64             p = p + q;
65             r = r - h;
66         } 
67     }
68
69     return p;
70 }
71
72 uint16_t *luma_render( luma *this )
73 {
74         int i = 0;
75         int j = 0;
76         int k = 0;
77
78         if ( this->quart )
79         {
80                 this->w *= 2;
81                 this->h *= 2;
82         }
83
84         if ( this->rotate )
85         {
86                 int t = this->w;
87                 this->w = this->h;
88                 this->h = t;
89         }
90
91         int max = ( 1 << 16 ) - 1;
92         uint16_t *image = malloc( this->w * this->h * sizeof( uint16_t ) );
93         uint16_t *end = image + this->w * this->h;
94         uint16_t *p = image;
95         uint16_t *r = image;
96         int lower = 0;
97         int lpb = this->h / this->bands;
98         int rpb = max / this->bands;
99         int direction = 1;
100
101         int half_w = this->w / 2;
102         int half_h = this->h / 2;
103
104         if ( !this->dmirror && ( this->hmirror || this->vmirror ) )
105                 rpb *= 2;
106
107         for ( i = 0; i < this->bands; i ++ )
108         {
109                 lower = i * rpb;
110                 direction = 1;
111
112                 if ( this->rband && i % 2 == 1 )
113                 {
114                         direction = -1;
115                         lower += rpb;
116                 }
117
118                 switch( this->type )
119                 {
120                         case 1:
121                                 {
122                                         int length = sqrti( half_w * half_w + lpb * lpb / 4 );
123                                         int value;
124                                         int x = 0;
125                                         int y = 0;
126                                         for ( j = 0; j < lpb; j ++ )
127                                         {
128                                                 y = j - lpb / 2;
129                                                 for ( k = 0; k < this->w; k ++ )
130                                                 {
131                                                         x = k - half_w;
132                                                         value = sqrti( x * x + y * y );
133                                                         *p ++ = lower + ( direction * rpb * ( ( max * value ) / length ) / max ) + ( j * this->offset * 2 / lpb ) + ( j * this->offset / lpb );
134                                                 }
135                                         }
136                                 }
137                                 break;
138
139                         case 2:
140                                 {
141                                         for ( j = 0; j < lpb; j ++ )
142                                         {
143                                                 int value = ( ( j * this->w ) / lpb ) - half_w;
144                                                 if ( value > 0 )
145                                                         value = - value;
146                                                 for ( k = - half_w; k < value; k ++ )
147                                                         *p ++ = lower + ( direction * rpb * ( ( max * abs( k ) ) / half_w ) / max );
148                                                 for ( k = value; k < abs( value ); k ++ )
149                                                         *p ++ = lower + ( direction * rpb * ( ( max * abs( value ) ) / half_w ) / max ) + ( j * this->offset * 2 / lpb ) + ( j * this->offset / lpb );
150                                                 for ( k = abs( value ); k < half_w; k ++ )
151                                                         *p ++ = lower + ( direction * rpb * ( ( max * abs( k ) ) / half_w ) / max );
152                                         }
153                                 }
154                                 break;
155
156                         case 3:
157                                 {
158                                         int length;
159                                         for ( j = -half_h; j < half_h; j ++ )
160                                         {
161                                                 if ( j < 0 )
162                                                 {
163                                                         for ( k = - half_w; k < half_w; k ++ )
164                                                         {
165                                                                 length = sqrti( k * k + j * j );
166                                                                 *p ++ = ( max / 4 * k ) / ( length + 1 );
167                                                         }
168                                                 }
169                                                 else
170                                                 {
171                                                         for ( k = half_w; k > - half_w; k -- )
172                                                         {
173                                                                 length = sqrti( k * k + j * j );
174                                                                 *p ++ = ( max / 2 ) + ( max / 4 * k ) / ( length + 1 );
175                                                         }
176                                                 }
177                                         }
178                                 }
179                                 break;
180
181                         default:
182                                 for ( j = 0; j < lpb; j ++ )
183                                         for ( k = 0; k < this->w; k ++ )
184                                                 *p ++ = lower + ( direction * ( rpb * ( ( k * max ) / this->w ) / max ) ) + ( j * this->offset * 2 / lpb );
185                                 break;
186                 }
187         }
188
189         if ( this->quart )
190         {
191                 this->w /= 2;
192                 this->h /= 2;
193                 for ( i = 1; i < this->h; i ++ )
194                 {
195                         p = image + i * this->w;
196                         r = image + i * 2 * this->w;
197                         j = this->w;
198                         while ( j -- > 0 )
199                                 *p ++ = *r ++;
200                 }
201         }
202
203         if ( this->dmirror )
204         {
205                 for ( i = 0; i < this->h; i ++ )
206                 {
207                         p = image + i * this->w;
208                         r = end - i * this->w;
209                         j = ( this->w * ( this->h - i ) ) / this->h;
210                         while ( j -- )
211                                 *( -- r ) = *p ++;
212                 }
213         }
214
215         if ( this->flip )
216         {
217                 uint16_t t;
218                 for ( i = 0; i < this->h; i ++ )
219                 {
220                         p = image + i * this->w;
221                         r = p + this->w;
222                         while( p != r )
223                         {
224                                 t = *p;
225                                 *p ++ = *( -- r );
226                                 *r = t;
227                         }
228                 }
229         }
230
231         if ( this->flop )
232         {
233                 uint16_t t;
234                 r = end;
235                 for ( i = 1; i < this->h / 2; i ++ )
236                 {
237                         p = image + i * this->w;
238                         j = this->w;
239                         while( j -- )
240                         {
241                                 t = *( -- p );
242                                 *p = *( -- r );
243                                 *r = t;
244                         }
245                 }
246         }
247
248         if ( this->hmirror )
249         {
250                 p = image;
251                 while ( p < end )
252                 {
253                         r = p + this->w;
254                         while ( p != r )
255                                 *( -- r ) = *p ++;
256                         p += this->w / 2;
257                 }
258         }
259
260         if ( this->vmirror )
261         {
262                 p = image;
263                 r = end;
264                 while ( p != r )
265                         *( -- r ) = *p ++;
266         }
267
268         if ( this->invert )
269         {
270                 p = image;
271                 r = image;
272                 while ( p < end )
273                         *p ++ = max - *r ++;
274         }
275
276         if ( this->pflip )
277         {
278                 uint16_t t;
279                 for ( i = 0; i < this->h; i ++ )
280                 {
281                         p = image + i * this->w;
282                         r = p + this->w;
283                         while( p != r )
284                         {
285                                 t = *p;
286                                 *p ++ = *( -- r );
287                                 *r = t;
288                         }
289                 }
290         }
291
292         if ( this->pflop )
293         {
294                 uint16_t t;
295                 end = image + this->w * this->h;
296                 r = end;
297                 for ( i = 1; i < this->h / 2; i ++ )
298                 {
299                         p = image + i * this->w;
300                         j = this->w;
301                         while( j -- )
302                         {
303                                 t = *( -- p );
304                                 *p = *( -- r );
305                                 *r = t;
306                         }
307                 }
308         }
309
310         if ( this->rotate )
311         {
312                 uint16_t *image2 = malloc( this->w * this->h * sizeof( uint16_t ) );
313                 for ( i = 0; i < this->h; i ++ )
314                 {
315                         p = image + i * this->w;
316                         r = image2 + this->h - i - 1;
317                         for ( j = 0; j < this->w; j ++ )
318                         {
319                                 *r = *( p ++ );
320                                 r += this->h;
321                         }
322                 }
323                 i = this->w;
324                 this->w = this->h;
325                 this->h = i;
326                 free( image );
327                 image = image2;
328         }
329
330         return image;
331 }
332
333 int main( int argc, char **argv )
334 {
335         int arg = 1;
336         int bpp = 8;
337
338         luma this;
339         uint16_t *image = NULL;
340
341         luma_init( &this );
342
343         for ( arg = 1; arg < argc - 1; arg ++ )
344         {
345                 if ( !strcmp( argv[ arg ], "-bpp" ) )
346                         bpp = atoi( argv[ ++ arg ] );
347                 else if ( !strcmp( argv[ arg ], "-type" ) )
348                         this.type = atoi( argv[ ++ arg ] );
349                 else if ( !strcmp( argv[ arg ], "-w" ) )
350                         this.w = atoi( argv[ ++ arg ] );
351                 else if ( !strcmp( argv[ arg ], "-h" ) )
352                         this.h = atoi( argv[ ++ arg ] );
353                 else if ( !strcmp( argv[ arg ], "-bands" ) )
354                         this.bands = atoi( argv[ ++ arg ] );
355                 else if ( !strcmp( argv[ arg ], "-rband" ) )
356                         this.rband = atoi( argv[ ++ arg ] );
357                 else if ( !strcmp( argv[ arg ], "-hmirror" ) )
358                         this.hmirror = atoi( argv[ ++ arg ] );
359                 else if ( !strcmp( argv[ arg ], "-vmirror" ) )
360                         this.vmirror = atoi( argv[ ++ arg ] );
361                 else if ( !strcmp( argv[ arg ], "-dmirror" ) )
362                         this.dmirror = atoi( argv[ ++ arg ] );
363                 else if ( !strcmp( argv[ arg ], "-offset" ) )
364                         this.offset = atoi( argv[ ++ arg ] );
365                 else if ( !strcmp( argv[ arg ], "-invert" ) )
366                         this.invert = atoi( argv[ ++ arg ] );
367                 else if ( !strcmp( argv[ arg ], "-flip" ) )
368                         this.flip = atoi( argv[ ++ arg ] );
369                 else if ( !strcmp( argv[ arg ], "-flop" ) )
370                         this.flop = atoi( argv[ ++ arg ] );
371                 else if ( !strcmp( argv[ arg ], "-pflip" ) )
372                         this.pflip = atoi( argv[ ++ arg ] );
373                 else if ( !strcmp( argv[ arg ], "-pflop" ) )
374                         this.pflop = atoi( argv[ ++ arg ] );
375                 else if ( !strcmp( argv[ arg ], "-quart" ) )
376                         this.quart = atoi( argv[ ++ arg ] );
377                 else if ( !strcmp( argv[ arg ], "-rotate" ) )
378                         this.rotate = atoi( argv[ ++ arg ] );
379                 else
380                         fprintf( stderr, "ignoring %s\n", argv[ arg ] );
381         }
382
383         if ( bpp != 8 && bpp != 16 )
384         {
385                 fprintf( stderr, "Invalid bpp %d\n", bpp );
386                 return 1;
387         }
388
389         image = luma_render( &this );
390
391         if ( bpp == 16 )
392         {
393                 uint16_t *end = image + this.w * this.h;
394                 uint16_t *p = image;
395                 uint8_t *q = ( uint8_t * )image;
396                 while ( p < end )
397                 {
398                         *p ++ = ( *q << 8 ) + *( q + 1 );
399                         q += 2;
400                 }
401                 printf( "P5\n" );
402                 printf( "%d %d\n", this.w, this.h );
403                 printf( "65535\n" );
404                 fwrite( image, this.w * this.h * sizeof( uint16_t ), 1, stdout );
405         }
406         else
407         {
408                 uint16_t *end = image + this.w * this.h;
409                 uint16_t *p = image;
410                 uint8_t *q = ( uint8_t * )image;
411                 while ( p < end )
412                         *q ++ = ( uint8_t )( *p ++ >> 8 );
413                 printf( "P5\n" );
414                 printf( "%d %d\n", this.w, this.h );
415                 printf( "255\n" );
416                 fwrite( image, this.w * this.h, 1, stdout );
417         }
418
419         return 0;
420 }
421