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