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