1 /*
2  * metapixel.c
3  *
4  * metapixel
5  *
6  * Copyright (C) 1997-2006 Mark Probst
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 #include <sys/time.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <assert.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <math.h>
30 #include <errno.h>
31 #include <float.h>
32 
33 #include "getopt.h"
34 
35 #include "vector.h"
36 #include "zoom.h"
37 #include "readimage.h"
38 #include "writeimage.h"
39 #include "lispreader.h"
40 
41 #include "metapixel.h"
42 
43 #ifndef MIN
44 #define MIN(a,b)           ((a)<(b)?(a):(b))
45 #endif
46 #ifndef MAX
47 #define MAX(a,b)           ((a)>(b)?(a):(b))
48 #endif
49 
50 static int index_order[IMAGE_SIZE * IMAGE_SIZE];
51 
52 static metapixel_t *first_pixel = 0;
53 static int num_metapixels = 0;
54 
55 static float sqrt_of_two, sqrt_of_image_size;
56 
57 static float index_weights[NUM_INDEXES];
58 static index_t weight_ordered_index_to_index[NUM_INDEXES];
59 static index_t index_to_weight_ordered_index[NUM_INDEXES];
60 
61 /* default settings */
62 
63 static char *default_prepare_directory = 0;
64 static int default_prepare_width = DEFAULT_PREPARE_WIDTH, default_prepare_height = DEFAULT_PREPARE_HEIGHT;
65 static string_list_t *default_library_directories = 0;
66 static int default_small_width = DEFAULT_WIDTH, default_small_height = DEFAULT_HEIGHT;
67 static float default_weight_factors[NUM_CHANNELS] = { 1.0, 1.0, 1.0 };
68 static int default_metric = METRIC_SUBPIXEL;
69 static int default_search = SEARCH_LOCAL;
70 static int default_classic_min_distance = DEFAULT_CLASSIC_MIN_DISTANCE;
71 static int default_collage_min_distance = DEFAULT_COLLAGE_MIN_DISTANCE;
72 static int default_cheat_amount = 0;
73 static int default_forbid_reconstruction_radius = 0;
74 
75 /* actual settings */
76 
77 static int small_width, small_height;
78 static float weight_factors[NUM_CHANNELS];
79 static int forbid_reconstruction_radius;
80 
81 static int benchmark_rendering = 0;
82 
83 static string_list_t*
string_list_prepend_copy(string_list_t * lst,const char * str)84 string_list_prepend_copy (string_list_t *lst, const char *str)
85 {
86     string_list_t *new = (string_list_t*)malloc(sizeof(string_list_t));
87 
88     new->str = strdup(str);
89     new->next = lst;
90 
91     return new;
92 }
93 
94 static char*
strip_path(char * name)95 strip_path (char *name)
96 {
97     char *p = strrchr(name, '/');
98 
99     if (p == 0)
100 	return name;
101     return p + 1;
102 }
103 
104 static metapixel_t*
new_metapixel(void)105 new_metapixel (void)
106 {
107     metapixel_t *pixel = (metapixel_t*)malloc(sizeof(metapixel_t));
108 
109     assert(pixel != 0);
110 
111     memset(pixel, 0, sizeof(metapixel_t));
112 
113     return pixel;
114 }
115 
116 static unsigned char*
scale_image(unsigned char * image,int image_width,int image_height,int x,int y,int width,int height,int new_width,int new_height)117 scale_image (unsigned char *image, int image_width, int image_height, int x, int y,
118 	     int width, int height, int new_width, int new_height)
119 {
120     unsigned char *new_image = (unsigned char*)malloc(new_width * new_height * NUM_CHANNELS);
121     unsigned char *image_start = image + (x + y * image_width) * NUM_CHANNELS;
122 
123     zoom_image(new_image, image_start, get_filter(FILTER_MITCHELL), NUM_CHANNELS,
124 	       new_width, new_height, new_width * NUM_CHANNELS,
125 	       width, height, image_width * NUM_CHANNELS);
126 
127     return new_image;
128 }
129 
130 void
alpha_compose(unsigned char * dst,int width,int height,unsigned char * src,int perc)131 alpha_compose (unsigned char *dst, int width, int height, unsigned char *src, int perc)
132 {
133     int i;
134 
135     for (i = 0; i < width * height * NUM_CHANNELS; ++i)
136 	dst[i] = dst[i] * (100 - perc) / 100 + src[i] * perc / 100;
137 }
138 
139 void
generate_index_order(void)140 generate_index_order (void)
141 {
142     int index = 0,
143 	begin = 0,
144 	row = 0,
145 	col = 0,
146 	first_half = 1;
147 
148     do
149     {
150 	index_order[index++] = col + IMAGE_SIZE * row;
151 
152 	if (first_half)
153 	{
154 	    if (row == 0)
155 	    {
156 		if (begin == IMAGE_SIZE - 1)
157 		{
158 		    first_half = 0;
159 		    col = begin = 1;
160 		    row = IMAGE_SIZE - 1;
161 		}
162 		else
163 		{
164 		    ++begin;
165 		    row = begin;
166 		    col = 0;
167 		}
168 	    }
169 	    else
170 	    {
171 		++col;
172 		--row;
173 	    }
174 	}
175 	else
176 	{
177 	    if (col == IMAGE_SIZE - 1)
178 	    {
179 		++begin;
180 		col = begin;
181 		row = IMAGE_SIZE - 1;
182 	    }
183 	    else
184 	    {
185 		++col;
186 		--row;
187 	    }
188 	}
189     } while (index < IMAGE_SIZE * IMAGE_SIZE);
190 }
191 
192 static int
compute_index(int real_index,int channel,int sign)193 compute_index (int real_index, int channel, int sign)
194 {
195     return real_index + (channel + (sign > 0 ? 1 : 0) * NUM_CHANNELS) * IMAGE_SIZE * IMAGE_SIZE;
196 }
197 
198 static void
uncompute_index(int index,int * real_index,int * channel,int * sign)199 uncompute_index (int index, int *real_index, int *channel, int *sign)
200 {
201     *real_index = index % (IMAGE_SIZE * IMAGE_SIZE);
202     *channel = (index / (IMAGE_SIZE * IMAGE_SIZE)) % NUM_CHANNELS;
203     *sign = (index / (NUM_CHANNELS * IMAGE_SIZE * IMAGE_SIZE)) ? 1 : -1;
204 }
205 
206 void
cut_last_coefficients(float * image,int channel,int howmany)207 cut_last_coefficients (float *image, int channel, int howmany)
208 {
209     int i;
210 
211     for (i = IMAGE_SIZE * IMAGE_SIZE - howmany; i < IMAGE_SIZE * IMAGE_SIZE; ++i)
212 	image[index_order[i] * NUM_CHANNELS + channel] = 0.0;
213 }
214 
215 void
transform_rgb_to_yiq(float * image,int num_pixels)216 transform_rgb_to_yiq (float *image, int num_pixels)
217 {
218     const static Matrix3D conversion_matrix =
219     {
220 	{ 0.299, 0.587, 0.114 },
221 	{ 0.596, -0.275, -0.321 },
222 	{ 0.212, -0.528, 0.311 }
223     };
224 
225     int i;
226 
227     for (i = 0; i < num_pixels; ++i)
228     {
229 	Vector3D rgb_vec,
230 	    yiq_vec;
231 
232 	InitVector3D(&rgb_vec,
233 		     image[NUM_CHANNELS * i + 0],
234 		     image[NUM_CHANNELS * i + 1],
235 		     image[NUM_CHANNELS * i + 2]);
236 	MultMatrixVector3D(&yiq_vec, &conversion_matrix, &rgb_vec);
237 	image[NUM_CHANNELS * i + 0] = yiq_vec.x;
238 	image[NUM_CHANNELS * i + 1] = yiq_vec.y / 1.192 + 127.5;
239 	image[NUM_CHANNELS * i + 2] = yiq_vec.z / 1.051 + 128.106565176;
240     }
241 }
242 
243 void
transform_yiq_to_rgb(float * image)244 transform_yiq_to_rgb (float *image)
245 {
246     const static Matrix3D conversion_matrix =
247     {
248 	{ 1.00308929854,  0.954849063112,   0.61785970812 },
249 	{ 0.996776058337, -0.270706233074, -0.644788332692 },
250 	{ 1.00849783766,   -1.1104851847,   1.69956753125 }
251     };
252 
253     int i;
254 
255     for (i = 0; i < IMAGE_SIZE * IMAGE_SIZE; ++i)
256     {
257 	Vector3D rgb_vec,
258 	    yiq_vec;
259 
260 	InitVector3D(&yiq_vec,
261 		     image[NUM_CHANNELS * i + 0],
262 		     image[NUM_CHANNELS * i + 1] - 127.5,
263 		     image[NUM_CHANNELS * i + 2] - 127.5);
264 	MultMatrixVector3D(&rgb_vec, &conversion_matrix, &yiq_vec);
265 	image[NUM_CHANNELS * i + 0] = rgb_vec.x;
266 	image[NUM_CHANNELS * i + 1] = rgb_vec.y;
267 	image[NUM_CHANNELS * i + 2] = rgb_vec.z;
268     }
269 }
270 
271 void
transpose_image(float * old_image,float * new_image)272 transpose_image (float *old_image, float *new_image)
273 {
274     int i,
275 	j,
276 	channel;
277 
278     for (i = 0; i < IMAGE_SIZE; ++i)
279 	for (j = 0; j < IMAGE_SIZE; ++j)
280 	    for (channel = 0; channel < NUM_CHANNELS; ++channel)
281 		new_image[channel + (i + j * IMAGE_SIZE) * NUM_CHANNELS] =
282 		    old_image[channel + (j + i * IMAGE_SIZE) * NUM_CHANNELS];
283 }
284 
285 void
decompose_row(float * row)286 decompose_row (float *row)
287 {
288     int h = IMAGE_SIZE,
289 	i;
290     float new_row[NUM_CHANNELS * IMAGE_SIZE];
291 
292     for (i = 0; i < NUM_CHANNELS * IMAGE_SIZE; ++i)
293 	row[i] = row[i] / sqrt_of_image_size;
294 
295     while (h > 1)
296     {
297 	h = h / 2;
298 	for (i = 0; i < h; ++i)
299 	{
300 	    int channel;
301 
302 	    for (channel = 0; channel < NUM_CHANNELS; ++channel)
303 	    {
304 		float val1 = row[channel + 2 * i * NUM_CHANNELS],
305 		    val2 = row[channel + (2 * i + 1) * NUM_CHANNELS];
306 
307 		new_row[channel + i * NUM_CHANNELS] = (val1 + val2) / sqrt_of_two;
308 		new_row[channel + (h + i) * NUM_CHANNELS] = (val1 - val2) / sqrt_of_two;
309 	    }
310 	}
311 	memcpy(row, new_row, sizeof(float) * NUM_CHANNELS * h * 2);
312     }
313 }
314 
315 void
decompose_column(float * column)316 decompose_column (float *column)
317 {
318     int h = IMAGE_SIZE,
319 	i,
320 	channel;
321     float new_column[ROW_LENGTH];
322 
323     for (i = 0; i < IMAGE_SIZE; ++i)
324 	for (channel = 0; channel < NUM_CHANNELS; ++channel)
325 	    column[channel + i * ROW_LENGTH] =
326 		column[channel + i * ROW_LENGTH] / sqrt_of_image_size;
327 
328     while (h > 1)
329     {
330 	h = h / 2;
331 	for (i = 0; i < h; ++i)
332 	{
333 	    for (channel = 0; channel < NUM_CHANNELS; ++channel)
334 	    {
335 		float val1 = column[channel + (2 * i) * ROW_LENGTH],
336 		    val2 = column[channel + (2 * i + 1) * ROW_LENGTH];
337 
338 		new_column[channel + i * NUM_CHANNELS] = (val1 + val2) / sqrt_of_two;
339 		new_column[channel + (h + i) * NUM_CHANNELS] = (val1 - val2) / sqrt_of_two;
340 	    }
341 	}
342 
343 	for (i = 0; i < h * 2; ++i)
344 	    for (channel = 0; channel < NUM_CHANNELS; ++channel)
345 		column[channel + i * ROW_LENGTH] = new_column[channel + i * NUM_CHANNELS];
346     }
347 }
348 
349 void
decompose_image(float * image)350 decompose_image (float *image)
351 {
352     int row;
353 
354     for (row = 0; row < IMAGE_SIZE; ++row)
355 	decompose_row(image + NUM_CHANNELS * IMAGE_SIZE * row);
356     for (row = 0; row < IMAGE_SIZE; ++row)
357 	decompose_column(image + NUM_CHANNELS * row);
358 }
359 
360 void
compose_row(float * row)361 compose_row (float *row)
362 {
363     int h = 1,
364 	i;
365     float new_row[NUM_CHANNELS * IMAGE_SIZE];
366 
367     memcpy(new_row, row, sizeof(float) * NUM_CHANNELS * IMAGE_SIZE);
368     while (h < IMAGE_SIZE)
369     {
370 	for (i = 0; i < h; ++i)
371 	{
372 	    int channel;
373 
374 	    for (channel = 0; channel < NUM_CHANNELS; ++channel)
375 	    {
376 		float val1 = row[channel + i * NUM_CHANNELS],
377 		    val2 = row[channel + (h + i) * NUM_CHANNELS];
378 
379 		new_row[channel + 2 * i * NUM_CHANNELS] = (val1 + val2) / sqrt_of_two;
380 		new_row[channel + (2 * i + 1) * NUM_CHANNELS] = (val1 - val2) / sqrt_of_two;
381 	    }
382 	}
383 	memcpy(row, new_row, sizeof(float) * NUM_CHANNELS * IMAGE_SIZE);
384 	h = h * 2;
385     }
386 
387     for (i = 0; i < NUM_CHANNELS * IMAGE_SIZE; ++i)
388 	row[i] = row[i] * sqrt_of_image_size;
389 }
390 
391 void
compose_image(float * image)392 compose_image (float *image)
393 {
394     int row;
395     float *transposed_image = (float*)malloc(sizeof(float) * 3 * IMAGE_SIZE * IMAGE_SIZE);
396 
397     transpose_image(image, transposed_image);
398     for (row = 0; row < IMAGE_SIZE; ++row)
399 	compose_row(transposed_image + NUM_CHANNELS * IMAGE_SIZE * row);
400     transpose_image(transposed_image, image);
401     for (row = 0; row < IMAGE_SIZE; ++row)
402 	compose_row(image + NUM_CHANNELS * IMAGE_SIZE * row);
403 
404     free(transposed_image);
405 }
406 
407 int
compare_coeffs_with_index(const void * p1,const void * p2)408 compare_coeffs_with_index (const void *p1, const void *p2)
409 {
410     const coefficient_with_index_t *coeff1 = (const coefficient_with_index_t*)p1;
411     const coefficient_with_index_t *coeff2 = (const coefficient_with_index_t*)p2;
412 
413     if (fabs(coeff1->coeff) < fabs(coeff2->coeff))
414 	return 1;
415     else if (fabs(coeff1->coeff) == fabs(coeff2->coeff))
416 	return 0;
417     return -1;
418 }
419 
420 void
find_highest_coefficients(float * image,coefficient_with_index_t highest_coeffs[NUM_COEFFS])421 find_highest_coefficients (float *image, coefficient_with_index_t highest_coeffs[NUM_COEFFS])
422 {
423     int index, channel;
424 
425     for (channel = 0; channel < NUM_CHANNELS; ++channel)
426     {
427 	for (index = 1; index < SIGNIFICANT_COEFFS + 1; ++index)
428 	{
429 	    float coeff = image[channel + NUM_CHANNELS * index];
430 	    int sign = coeff > 0.0 ? 1 : -1;
431 
432 	    highest_coeffs[index - 1 + channel * SIGNIFICANT_COEFFS].index = compute_index(index, channel, sign);
433 	    highest_coeffs[index - 1 + channel * SIGNIFICANT_COEFFS].coeff = coeff;
434 	}
435 
436 	qsort(highest_coeffs + channel * SIGNIFICANT_COEFFS, SIGNIFICANT_COEFFS,
437 	      sizeof(coefficient_with_index_t), compare_coeffs_with_index);
438     }
439 
440     for (index = SIGNIFICANT_COEFFS + 1; index < IMAGE_SIZE * IMAGE_SIZE; ++index)
441     {
442 	for (channel = 0; channel < NUM_CHANNELS; ++channel)
443 	{
444 	    float coeff = image[channel + NUM_CHANNELS * index];
445 
446 	    if (fabs(coeff) > fabs(highest_coeffs[(channel + 1) * SIGNIFICANT_COEFFS - 1].coeff))
447 	    {
448 		int significance;
449 		int sign = coeff > 0.0 ? 1 : -1;
450 
451 		for (significance = (channel + 1) * SIGNIFICANT_COEFFS - 2;
452 		     significance >= channel * SIGNIFICANT_COEFFS;
453 		     --significance)
454 		    if (fabs(coeff) <= fabs(highest_coeffs[significance].coeff))
455 			break;
456 		++significance;
457 		memmove(highest_coeffs + significance + 1,
458 			highest_coeffs + significance,
459 			sizeof(coefficient_with_index_t) * ((channel + 1) * SIGNIFICANT_COEFFS - 1 - significance));
460 		highest_coeffs[significance].index = compute_index(index, channel, sign);
461 		highest_coeffs[significance].coeff = coeff;
462 	    }
463 	}
464     }
465 }
466 
467 static float
weight_function(int index)468 weight_function (int index)
469 {
470     static float weight_table[NUM_CHANNELS][6] =
471     {
472 	{ 5.00, 0.83, 1.01, 0.52, 0.47, 0.30 },
473 	{ 19.21, 1.26, 0.44, 0.53, 0.28, 0.14 },
474 	{ 34, 0.36, 0.45, 0.14, 0.18, 0.27 }
475     };
476 
477     int real_index, channel, sign;
478     int i, j, bin;
479 
480     uncompute_index(index, &real_index, &channel, &sign);
481 
482     i = real_index % IMAGE_SIZE;
483     j = real_index / IMAGE_SIZE;
484     bin = MIN(MAX(i, j), 5);
485 
486     return weight_table[channel][bin] * weight_factors[channel];
487 }
488 
489 static int
compare_indexes_by_weight_descending(const void * p1,const void * p2)490 compare_indexes_by_weight_descending (const void *p1, const void *p2)
491 {
492     const index_t *i1 = (const index_t*)p1, *i2 = (const index_t*)p2;
493 
494     if (index_weights[*i1] < index_weights[*i2])
495 	return 1;
496     else if (index_weights[*i1] == index_weights[*i2])
497 	return 0;
498     return -1;
499 }
500 
501 static void
compute_index_weights(void)502 compute_index_weights (void)
503 {
504     int i;
505 
506     for (i = 0; i < NUM_INDEXES; ++i)
507 	index_weights[i] = weight_function(i);
508 
509     for (i = 0; i < NUM_INDEXES; ++i)
510 	weight_ordered_index_to_index[i] = i;
511     qsort(weight_ordered_index_to_index, NUM_INDEXES, sizeof(index_t), compare_indexes_by_weight_descending);
512     for (i = 0; i < NUM_INDEXES; ++i)
513 	index_to_weight_ordered_index[weight_ordered_index_to_index[i]] = i;
514 }
515 
516 static float
wavelet_compare(coeffs_t * coeffs,metapixel_t * pixel,float best_score)517 wavelet_compare (coeffs_t *coeffs, metapixel_t *pixel, float best_score)
518 {
519     search_coefficients_t *query = &coeffs->wavelet.coeffs;
520     float *query_means = coeffs->wavelet.means;
521     float *sums = coeffs->wavelet.sums;
522     search_coefficients_t *target = &pixel->coeffs;
523     float *target_means = pixel->means;
524     float score = 0.0;
525     int i;
526     int j;
527     int channel;
528 
529     for (channel = 0; channel < NUM_CHANNELS; ++channel)
530 	score += index_weights[compute_index(0, channel, 0)]
531 	    * fabs(query_means[channel] - target_means[channel]) * 0.05;
532 
533     j = 0;
534     for (i = 0; i < NUM_COEFFS; ++i)
535     {
536 	if (score - sums[i] > best_score)
537 	    return FLT_MAX;
538 
539 	while (target->coeffs[j] < query->coeffs[i] && j < NUM_COEFFS)
540 	    ++j;
541 
542 	if (j >= NUM_COEFFS)
543 	    break;
544 
545 	if (target->coeffs[j] > query->coeffs[i])
546 	    continue;
547 
548 	score -= index_weights[weight_ordered_index_to_index[target->coeffs[j]]];
549     }
550 
551     return score;
552 }
553 
554 static float
subpixel_compare(coeffs_t * coeffs,metapixel_t * pixel,float best_score)555 subpixel_compare (coeffs_t *coeffs, metapixel_t *pixel, float best_score)
556 {
557     int channel;
558     float score = 0.0;
559 
560     for (channel = 0; channel < NUM_CHANNELS; ++channel)
561     {
562 	int i;
563 
564 	for (i = 0; i < NUM_SUBPIXELS; ++i)
565 	{
566 	    float dist = (int)coeffs->subpixel.subpixels[channel * NUM_SUBPIXELS + i]
567 		- (int)pixel->subpixels[channel * NUM_SUBPIXELS + i];
568 
569 	    score += dist * dist * weight_factors[channel];
570 
571 	    if (score >= best_score)
572 		return FLT_MAX;
573 	}
574     }
575 
576     return score;
577 }
578 
579 void
add_metapixel(metapixel_t * pixel)580 add_metapixel (metapixel_t *pixel)
581 {
582     pixel->next = first_pixel;
583     first_pixel = pixel;
584     ++num_metapixels;
585 }
586 
587 static int
compare_indexes(const void * p1,const void * p2)588 compare_indexes (const void *p1, const void *p2)
589 {
590     index_t *i1 = (index_t*)p1;
591     index_t *i2 = (index_t*)p2;
592 
593     return *i1 - *i2;
594 }
595 
596 void
generate_search_coeffs(search_coefficients_t * search_coeffs,float sums[NUM_COEFFS],coefficient_with_index_t raw_coeffs[NUM_COEFFS])597 generate_search_coeffs (search_coefficients_t *search_coeffs, float sums[NUM_COEFFS],
598 			coefficient_with_index_t raw_coeffs[NUM_COEFFS])
599 {
600     int i;
601     float sum;
602 
603     for (i = 0; i < NUM_COEFFS; ++i)
604 	search_coeffs->coeffs[i] = index_to_weight_ordered_index[raw_coeffs[i].index];
605 
606     qsort(search_coeffs->coeffs, NUM_COEFFS, sizeof(index_t), compare_indexes);
607 
608     sum = 0.0;
609     for (i = NUM_COEFFS - 1; i >= 0; --i)
610     {
611 	sum += index_weights[weight_ordered_index_to_index[search_coeffs->coeffs[i]]];
612 	sums[i] = sum;
613     }
614 }
615 
616 void
generate_search_coeffs_for_subimage(coeffs_t * coeffs,unsigned char * image_data,int image_width,int image_height,int x,int y,int width,int height,int metric)617 generate_search_coeffs_for_subimage (coeffs_t *coeffs, unsigned char *image_data, int image_width, int image_height,
618 				     int x, int y, int width, int height, int metric)
619 {
620     static float *float_image = 0;
621 
622     if (metric == METRIC_WAVELET)
623     {
624 	coefficient_with_index_t raw_coeffs[NUM_COEFFS];
625 	int i;
626 
627 	if (float_image == 0)
628 	    float_image = (float*)malloc(sizeof(float) * IMAGE_SIZE * IMAGE_SIZE * NUM_CHANNELS);
629 
630 	if (width != IMAGE_SIZE || height != IMAGE_SIZE)
631 	{
632 	    unsigned char *scaled_data;
633 
634 	    scaled_data = scale_image(image_data, image_width, image_height, x, y, width, height, IMAGE_SIZE, IMAGE_SIZE);
635 	    assert(scaled_data != 0);
636 
637 	    for (i = 0; i < IMAGE_SIZE * IMAGE_SIZE * NUM_CHANNELS; ++i)
638 		float_image[i] = scaled_data[i];
639 
640 	    free(scaled_data);
641 	}
642 	else
643 	{
644 	    int j, channel;
645 
646 	    for (j = 0; j < IMAGE_SIZE; ++j)
647 		for (i = 0; i < IMAGE_SIZE; ++i)
648 		    for (channel = 0; channel < NUM_CHANNELS; ++channel)
649 			float_image[(j * IMAGE_SIZE + i) * NUM_CHANNELS + channel] =
650 			    image_data[((y + j) * image_width + (x + i)) * NUM_CHANNELS + channel];
651 	}
652 
653 	transform_rgb_to_yiq(float_image, IMAGE_SIZE * IMAGE_SIZE);
654 	decompose_image(float_image);
655 	find_highest_coefficients(float_image, raw_coeffs);
656 
657 	generate_search_coeffs(&coeffs->wavelet.coeffs, coeffs->wavelet.sums, raw_coeffs);
658 
659 	for (i = 0; i < NUM_CHANNELS; ++i)
660 	    coeffs->wavelet.means[i] = float_image[i];
661     }
662     else if (metric == METRIC_SUBPIXEL)
663     {
664 	unsigned char *scaled_data;
665 	int i;
666 	int channel;
667 
668 	if (float_image == 0)
669 	    float_image = (float*)malloc(sizeof(float) * NUM_SUBPIXELS * NUM_CHANNELS);
670 
671 	scaled_data = scale_image(image_data, image_width, image_height, x, y, width, height,
672 				  NUM_SUBPIXEL_ROWS_COLS, NUM_SUBPIXEL_ROWS_COLS);
673 
674 	for (i = 0; i < NUM_SUBPIXELS * NUM_CHANNELS; ++i)
675 	    float_image[i] = scaled_data[i];
676 
677 	free(scaled_data);
678 
679 	transform_rgb_to_yiq(float_image, NUM_SUBPIXELS);
680 
681 	for (channel = 0; channel < NUM_CHANNELS; ++channel)
682 	    for (i = 0; i < NUM_SUBPIXELS; ++i)
683 		coeffs->subpixel.subpixels[channel * NUM_SUBPIXELS + i] = float_image[i * NUM_CHANNELS + channel];
684     }
685     else
686 	assert(0);
687 }
688 
689 static void
generate_metapixel_coefficients(metapixel_t * pixel,unsigned char * image_data,coefficient_with_index_t raw_coeffs[NUM_COEFFS])690 generate_metapixel_coefficients (metapixel_t *pixel, unsigned char *image_data,
691 				 coefficient_with_index_t raw_coeffs[NUM_COEFFS])
692 {
693     static float float_image[NUM_CHANNELS * IMAGE_SIZE * IMAGE_SIZE];
694     static float sums[NUM_COEFFS];
695 
696     unsigned char *scaled_data;
697     int i, channel;
698 
699     /* generate wavelet coefficients */
700     if (small_width != IMAGE_SIZE || small_height != IMAGE_SIZE)
701     {
702 	scaled_data = scale_image(image_data, small_width, small_height,
703 				  0, 0, small_width, small_height, IMAGE_SIZE, IMAGE_SIZE);
704 	assert(scaled_data != 0);
705     }
706     else
707 	scaled_data = image_data;
708 
709     for (i = 0; i < IMAGE_SIZE * IMAGE_SIZE * NUM_CHANNELS; ++i)
710 	float_image[i] = scaled_data[i];
711 
712     if (scaled_data != image_data)
713 	free(scaled_data);
714 
715     transform_rgb_to_yiq(float_image, IMAGE_SIZE * IMAGE_SIZE);
716     decompose_image(float_image);
717 
718     find_highest_coefficients(float_image, raw_coeffs);
719 
720     generate_search_coeffs(&pixel->coeffs, sums, raw_coeffs);
721 
722     for (i = 0; i < NUM_CHANNELS; ++i)
723 	pixel->means[i] = float_image[i];
724 
725     /* generate subpixel coefficients */
726     if (small_width != NUM_SUBPIXEL_ROWS_COLS || small_height != NUM_SUBPIXEL_ROWS_COLS)
727     {
728 	scaled_data = scale_image(image_data, small_width, small_height, 0, 0, small_width, small_height,
729 				  NUM_SUBPIXEL_ROWS_COLS, NUM_SUBPIXEL_ROWS_COLS);
730 	assert(scaled_data != 0);
731     }
732     else
733 	scaled_data = image_data;
734 
735     assert(NUM_SUBPIXELS <= IMAGE_SIZE * IMAGE_SIZE);
736 
737     for (i = 0; i < NUM_SUBPIXELS * NUM_CHANNELS; ++i)
738 	float_image[i] = scaled_data[i];
739 
740     transform_rgb_to_yiq(float_image, NUM_SUBPIXELS);
741 
742     for (channel = 0; channel < NUM_CHANNELS; ++channel)
743 	for (i = 0; i < NUM_SUBPIXELS; ++i)
744 	    pixel->subpixels[channel * NUM_SUBPIXELS + i] = (int)float_image[i * NUM_CHANNELS + channel];
745 
746     if (scaled_data != image_data)
747 	free(scaled_data);
748 }
749 
750 static int
metapixel_in_array(metapixel_t * pixel,metapixel_t ** array,int size)751 metapixel_in_array (metapixel_t *pixel, metapixel_t **array, int size)
752 {
753     int i;
754 
755     for (i = 0; i < size; ++i)
756 	if (array[i] == pixel)
757 	    return 1;
758     return 0;
759 }
760 
761 compare_func_t
compare_func_for_metric(int metric)762 compare_func_for_metric (int metric)
763 {
764     if (metric == METRIC_WAVELET)
765 	return wavelet_compare;
766     else if (metric == METRIC_SUBPIXEL)
767 	return subpixel_compare;
768     else
769 	assert(0);
770     return 0;
771 }
772 
773 static int
manhattan_distance(int x1,int y1,int x2,int y2)774 manhattan_distance (int x1, int y1, int x2, int y2)
775 {
776     return abs(x1 - x2) + abs(y1 - y2);
777 }
778 
779 static match_t
metapixel_nearest_to(coeffs_t * coeffs,int metric,int x,int y,metapixel_t ** forbidden,int num_forbidden,int (* validity_func)(void *,metapixel_t *,int,int),void * validity_func_data)780 metapixel_nearest_to (coeffs_t *coeffs, int metric, int x, int y,
781 		      metapixel_t **forbidden, int num_forbidden,
782 		      int (*validity_func) (void*, metapixel_t*, int, int),
783 		      void *validity_func_data)
784 {
785     float best_score = FLT_MAX;
786     metapixel_t *best_fit = 0, *pixel;
787     compare_func_t compare_func = compare_func_for_metric(metric);
788     match_t match;
789 
790     for (pixel = first_pixel; pixel != 0; pixel = pixel->next)
791     {
792 	float score;
793 
794 	if (manhattan_distance(x, y, pixel->anti_x, pixel->anti_y)
795 	    < forbid_reconstruction_radius)
796 	    continue;
797 
798 	score = compare_func(coeffs, pixel, best_score);
799 
800 	if (score < best_score && !metapixel_in_array(pixel, forbidden, num_forbidden)
801 	    && (validity_func == 0 || validity_func(validity_func_data, pixel, x, y)))
802 	{
803 	    best_score = score;
804 	    best_fit = pixel;
805 	}
806     }
807 
808     match.pixel = best_fit;
809     match.score = best_score;
810 
811     return match;
812 }
813 
814 static void
get_n_metapixel_nearest_to(int n,global_match_t * matches,coeffs_t * coeffs,int metric)815 get_n_metapixel_nearest_to (int n, global_match_t *matches, coeffs_t *coeffs, int metric)
816 {
817     compare_func_t compare_func = compare_func_for_metric(metric);
818     int i;
819     metapixel_t *pixel;
820 
821     assert(num_metapixels >= n);
822 
823     i = 0;
824     for (pixel = first_pixel; pixel != 0; pixel = pixel->next)
825     {
826 	float score = compare_func(coeffs, pixel, (i < n) ? FLT_MAX : matches[n - 1].score);
827 
828 	if (i < n || score < matches[n - 1].score)
829 	{
830 	    int j, m;
831 
832 	    m = MIN(i, n);
833 
834 	    for (j = 0; j < m; ++j)
835 		if (matches[j].score > score)
836 		    break;
837 
838 	    assert(j <= m && j < n);
839 
840 	    memmove(matches + j + 1, matches + j, sizeof(global_match_t) * (MIN(n, m + 1) - (j + 1)));
841 
842 	    matches[j].pixel = pixel;
843 	    matches[j].score = score;
844 	}
845 
846 	++i;
847     }
848 
849     assert(i >= n);
850 }
851 
852 static void
paste_metapixel(metapixel_t * pixel,unsigned char * data,int width,int height,int x,int y)853 paste_metapixel (metapixel_t *pixel, unsigned char *data, int width, int height, int x, int y)
854 {
855     int i;
856     int pixel_width, pixel_height;
857     unsigned char *pixel_data;
858 
859     if (pixel->data != 0)
860     {
861 	pixel_data = pixel->data;
862 	pixel_width = pixel->width;
863 	pixel_height = pixel->height;
864     }
865     else
866     {
867 	pixel_data = read_image(pixel->filename, &pixel_width, &pixel_height);
868 
869 	if (pixel_data == 0)
870 	{
871 	    fprintf(stderr, "Error: cannot read metapixel file `%s'\n", pixel->filename);
872 	    exit(1);
873 	}
874     }
875 
876     if (pixel_width != small_width || pixel_height != small_height)
877     {
878 	unsigned char *scaled_data = scale_image(pixel_data, pixel_width, pixel_height,
879 						 0, 0, pixel_width, pixel_height,
880 						 small_width, small_height);
881 
882 	if (pixel->data == 0)
883 	    free(pixel_data);
884 	pixel_data = scaled_data;
885     }
886 
887     for (i = 0; i < small_height; ++i)
888 	memcpy(data + NUM_CHANNELS * (x + (y + i) * width),
889 	       pixel_data + NUM_CHANNELS * i * small_width, NUM_CHANNELS * small_width);
890 
891     if (pixel_data != pixel->data)
892 	free(pixel_data);
893 }
894 
895 static classic_reader_t*
init_classic_reader(char * input_name,float scale)896 init_classic_reader (char *input_name, float scale)
897 {
898     classic_reader_t *reader = (classic_reader_t*)malloc(sizeof(classic_reader_t));
899 
900     assert(reader != 0);
901 
902     reader->image_reader = open_image_reading(input_name);
903     if (reader->image_reader == 0)
904     {
905 	fprintf(stderr, "cannot read image `%s'\n", input_name);
906 	exit(1);
907     }
908 
909     reader->in_image_width = reader->image_reader->width;
910     reader->in_image_height = reader->image_reader->height;
911 
912     reader->out_image_width = (((int)((float)reader->in_image_width * scale) - 1) / small_width + 1) * small_width;
913     reader->out_image_height = (((int)((float)reader->in_image_height * scale) - 1) / small_height + 1) * small_height;
914 
915     assert(reader->out_image_width % small_width == 0);
916     assert(reader->out_image_height % small_height == 0);
917 
918     reader->metawidth = reader->out_image_width / small_width;
919     reader->metaheight = reader->out_image_height / small_height;
920 
921     reader->in_image_data = 0;
922     reader->y = 0;
923 
924     return reader;
925 }
926 
927 static void
read_classic_row(classic_reader_t * reader)928 read_classic_row (classic_reader_t *reader)
929 {
930     if (reader->in_image_data != 0)
931     {
932 	assert(reader->y > 0);
933 	free(reader->in_image_data);
934     }
935     else
936 	assert(reader->y == 0);
937 
938     reader->num_lines = (reader->y + 1) * reader->in_image_height / reader->metaheight
939 	- reader->y * reader->in_image_height / reader->metaheight;
940 
941     reader->in_image_data = (unsigned char*)malloc(reader->num_lines * reader->in_image_width * NUM_CHANNELS);
942     assert(reader->in_image_data != 0);
943 
944     read_lines(reader->image_reader, reader->in_image_data, reader->num_lines);
945 
946     ++reader->y;
947 }
948 
949 static void
compute_classic_column_coords(classic_reader_t * reader,int x,int * left_x,int * width)950 compute_classic_column_coords (classic_reader_t *reader, int x, int *left_x, int *width)
951 {
952     *left_x = x * reader->in_image_width / reader->metawidth;
953     *width = (x + 1) * reader->in_image_width / reader->metawidth - *left_x;
954 }
955 
956 static void
generate_search_coeffs_for_classic_subimage(classic_reader_t * reader,int x,coeffs_t * coeffs,int metric)957 generate_search_coeffs_for_classic_subimage (classic_reader_t *reader, int x, coeffs_t *coeffs, int metric)
958 {
959     int left_x, width;
960 
961     compute_classic_column_coords(reader, x, &left_x, &width);
962     generate_search_coeffs_for_subimage(coeffs, reader->in_image_data, reader->in_image_width, reader->num_lines,
963 					left_x, 0, width, reader->num_lines, metric);
964 }
965 
966 static void
free_classic_reader(classic_reader_t * reader)967 free_classic_reader (classic_reader_t *reader)
968 {
969     if (reader->in_image_data != 0)
970 	free(reader->in_image_data);
971     free_image_reader(reader->image_reader);
972     free(reader);
973 }
974 
975 static mosaic_t*
init_mosaic_from_reader(classic_reader_t * reader)976 init_mosaic_from_reader (classic_reader_t *reader)
977 {
978     mosaic_t *mosaic = (mosaic_t*)malloc(sizeof(mosaic_t));
979     int metawidth = reader->metawidth, metaheight = reader->metaheight;
980     int i;
981 
982     assert(mosaic != 0);
983 
984     mosaic->metawidth = metawidth;
985     mosaic->metaheight = metaheight;
986     mosaic->matches = (match_t*)malloc(sizeof(match_t) * metawidth * metaheight);
987 
988     for (i = 0; i < metawidth * metaheight; ++i)
989 	mosaic->matches[i].pixel = 0;
990 
991     return mosaic;
992 }
993 
994 static mosaic_t*
generate_local_classic(classic_reader_t * reader,int min_distance,int metric)995 generate_local_classic (classic_reader_t *reader, int min_distance, int metric)
996 {
997     mosaic_t *mosaic = init_mosaic_from_reader(reader);
998     int metawidth = reader->metawidth, metaheight = reader->metaheight;
999     int x, y;
1000     metapixel_t **neighborhood = 0;
1001     int neighborhood_diameter = min_distance * 2 + 1;
1002     int neighborhood_size = (neighborhood_diameter * neighborhood_diameter - 1) / 2;
1003 
1004     if (min_distance > 0)
1005 	neighborhood = (metapixel_t**)malloc(sizeof(metapixel_t*) * neighborhood_size);
1006 
1007     for (y = 0; y < metaheight; ++y)
1008     {
1009 	read_classic_row(reader);
1010 
1011 	for (x = 0; x < metawidth; ++x)
1012 	{
1013 	    match_t match;
1014 	    int i;
1015 	    coeffs_t coeffs;
1016 
1017 	    for (i = 0; i < neighborhood_size; ++i)
1018 	    {
1019 		int nx = x + i % neighborhood_diameter - min_distance;
1020 		int ny = y + i / neighborhood_diameter - min_distance;
1021 
1022 		if (nx < 0 || nx >= metawidth || ny < 0 || ny >= metaheight)
1023 		    neighborhood[i] = 0;
1024 		else
1025 		    neighborhood[i] = mosaic->matches[ny * metawidth + nx].pixel;
1026 	    }
1027 
1028 	    generate_search_coeffs_for_classic_subimage(reader, x, &coeffs, metric);
1029 
1030 	    match = metapixel_nearest_to(&coeffs, metric, x, y, neighborhood, neighborhood_size, 0, 0);
1031 
1032 	    if (match.pixel == 0)
1033 	    {
1034 		fprintf(stderr, "Error: cannot find a matching image - try using a shorter minimum distance.\n");
1035 		exit(1);
1036 	    }
1037 
1038 	    mosaic->matches[y * metawidth + x] = match;
1039 
1040 	    printf(".");
1041 	    fflush(stdout);
1042 	}
1043     }
1044 
1045     free(neighborhood);
1046 
1047     printf("\n");
1048 
1049     return mosaic;
1050 }
1051 
1052 static int
compare_global_matches(const void * _m1,const void * _m2)1053 compare_global_matches (const void *_m1, const void *_m2)
1054 {
1055     global_match_t *m1 = (global_match_t*)_m1;
1056     global_match_t *m2 = (global_match_t*)_m2;
1057 
1058     if (m1->score < m2->score)
1059 	return -1;
1060     if (m1->score > m2->score)
1061 	return 1;
1062     return 0;
1063 }
1064 
1065 static mosaic_t*
generate_global_classic(classic_reader_t * reader,int metric)1066 generate_global_classic (classic_reader_t *reader, int metric)
1067 {
1068     mosaic_t *mosaic = init_mosaic_from_reader(reader);
1069     int metawidth = reader->metawidth, metaheight = reader->metaheight;
1070     int x, y;
1071     global_match_t *matches, *m;
1072     /* FIXME: this will overflow if metawidth and/or metaheight are large! */
1073     int num_matches = (metawidth * metaheight) * (metawidth * metaheight);
1074     int i, ignore_forbidden;
1075     int num_locations_filled;
1076     metapixel_t *pixel;
1077 
1078     if (num_metapixels < metawidth * metaheight)
1079     {
1080 	fprintf(stderr,
1081 		"global search method needs at least as much\n"
1082 		"metapixels as there are locations\n");
1083 	exit(1);
1084     }
1085 
1086     matches = (global_match_t*)malloc(sizeof(global_match_t) * num_matches);
1087     assert(matches != 0);
1088 
1089     m = matches;
1090     for (y = 0; y < metaheight; ++y)
1091     {
1092 	read_classic_row(reader);
1093 
1094 	for (x = 0; x < metawidth; ++x)
1095 	{
1096 	    coeffs_t coeffs;
1097 
1098 	    generate_search_coeffs_for_classic_subimage(reader, x, &coeffs, metric);
1099 
1100 	    get_n_metapixel_nearest_to(metawidth * metaheight, m, &coeffs, metric);
1101 	    for (i = 0; i < metawidth * metaheight; ++i)
1102 	    {
1103 		int j;
1104 
1105 		for (j = i + 1; j < metawidth * metaheight; ++j)
1106 		    assert(m[i].pixel != m[j].pixel);
1107 
1108 		m[i].x = x;
1109 		m[i].y = y;
1110 	    }
1111 
1112 	    m += metawidth * metaheight;
1113 
1114 	    printf(".");
1115 	    fflush(stdout);
1116 	}
1117     }
1118 
1119     qsort(matches, num_matches, sizeof(global_match_t), compare_global_matches);
1120 
1121     for (pixel = first_pixel; pixel != 0; pixel = pixel->next)
1122 	pixel->flag = 0;
1123 
1124     num_locations_filled = 0;
1125     for (ignore_forbidden = 0; ignore_forbidden < 2; ++ignore_forbidden)
1126     {
1127 	for (i = 0; i < num_matches; ++i)
1128 	{
1129 	    int index = matches[i].y * metawidth + matches[i].x;
1130 
1131 	    if (!ignore_forbidden
1132 		&& manhattan_distance(matches[i].x, matches[i].y,
1133 				      matches[i].pixel->anti_x, matches[i].pixel->anti_y)
1134 		  < forbid_reconstruction_radius)
1135 		continue;
1136 
1137 	    if (matches[i].pixel->flag)
1138 		continue;
1139 
1140 	    if (num_locations_filled >= metawidth * metaheight)
1141 		break;
1142 
1143 	    if (mosaic->matches[index].pixel == 0)
1144 	    {
1145 		if (forbid_reconstruction_radius > 0 && ignore_forbidden)
1146 		{
1147 		    printf("!");
1148 		    fflush(stdout);
1149 		}
1150 		mosaic->matches[index].pixel = matches[i].pixel;
1151 		mosaic->matches[index].score = matches[i].score;
1152 
1153 		matches[i].pixel->flag = 1;
1154 
1155 		++num_locations_filled;
1156 	    }
1157 	}
1158 	if (forbid_reconstruction_radius == 0)
1159 	    break;
1160     }
1161     assert(num_locations_filled == metawidth * metaheight);
1162 
1163     free(matches);
1164 
1165     printf("\n");
1166 
1167     return mosaic;
1168 }
1169 
1170 static void
print_current_time(void)1171 print_current_time (void)
1172 {
1173     struct timeval tv;
1174 
1175     gettimeofday(&tv, 0);
1176 
1177     printf("time: %lu %lu\n", (unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec);
1178 }
1179 
1180 static void
paste_classic(mosaic_t * mosaic,char * input_name,char * output_name,int cheat)1181 paste_classic (mosaic_t *mosaic, char *input_name, char *output_name, int cheat)
1182 {
1183     image_reader_t *reader;
1184     image_writer_t *writer = 0;
1185     int out_image_width, out_image_height;
1186     int x, y;
1187     unsigned char *out_image_data;
1188     int in_image_width, in_image_height;
1189     int metawidth = mosaic->metawidth, metaheight = mosaic->metaheight;
1190 
1191     if (cheat > 0)
1192     {
1193 	reader = open_image_reading(input_name);
1194 	if (reader == 0)
1195 	{
1196 	    fprintf(stderr, "cannot read image `%s'\n", input_name);
1197 	    exit(1);
1198 	}
1199 
1200 	in_image_width = reader->width;
1201 	in_image_height = reader->height;
1202     }
1203     else
1204     {
1205 	reader = 0;
1206 	in_image_width = in_image_height = 0;
1207     }
1208 
1209     out_image_width = mosaic->metawidth * small_width;
1210     out_image_height = mosaic->metaheight * small_height;
1211 
1212     if (!benchmark_rendering)
1213     {
1214 	writer = open_image_writing(output_name, out_image_width, out_image_height, 3, out_image_width * 3, IMAGE_FORMAT_AUTO);
1215 	if (writer == 0)
1216 	{
1217 	    fprintf(stderr, "Error: cannot write image `%s'\n", output_name);
1218 	    exit(1);
1219 	}
1220     }
1221 
1222     out_image_data = (unsigned char*)malloc(out_image_width * small_height * NUM_CHANNELS);
1223 
1224     if (benchmark_rendering)
1225 	print_current_time();
1226 
1227     for (y = 0; y < metaheight; ++y)
1228     {
1229 	for (x = 0; x < metawidth; ++x)
1230 	{
1231 	    if (benchmark_rendering)
1232 		assert(mosaic->matches[y * metawidth + x].pixel->data != 0);
1233 
1234 	    paste_metapixel(mosaic->matches[y * metawidth + x].pixel, out_image_data, out_image_width,
1235 			    small_height, x * small_width, 0);
1236 	    if (!benchmark_rendering)
1237 	    {
1238 		printf("X");
1239 		fflush(stdout);
1240 	    }
1241 	}
1242 
1243 	if (cheat > 0)
1244 	{
1245 	    int num_lines = (y + 1) * in_image_height / metaheight - y * in_image_height / metaheight;
1246 	    unsigned char *in_image_data = (unsigned char*)malloc(num_lines * in_image_width * NUM_CHANNELS);
1247 	    unsigned char *source_data;
1248 
1249 	    assert(in_image_data != 0);
1250 
1251 	    read_lines(reader, in_image_data, num_lines);
1252 
1253 	    if (in_image_width != out_image_width || num_lines != small_height)
1254 		source_data = scale_image(in_image_data, in_image_width, num_lines,
1255 					  0, 0, in_image_width, num_lines,
1256 					  out_image_width, small_height);
1257 	    else
1258 		source_data = in_image_data;
1259 
1260 	    alpha_compose(out_image_data, out_image_width, small_height, source_data, cheat);
1261 
1262 	    if (source_data != in_image_data)
1263 		free(source_data);
1264 
1265 	    free(in_image_data);
1266 	}
1267 
1268 	if (!benchmark_rendering)
1269 	    write_lines(writer, out_image_data, small_height);
1270     }
1271 
1272     if (benchmark_rendering)
1273 	print_current_time();
1274 
1275     free(out_image_data);
1276 
1277     if (!benchmark_rendering)
1278 	free_image_writer(writer);
1279     if (cheat > 0)
1280 	free_image_reader(reader);
1281 
1282     printf("\n");
1283 }
1284 
1285 static void
pixel_add_collage_position(metapixel_t * pixel,int x,int y)1286 pixel_add_collage_position (metapixel_t *pixel, int x, int y)
1287 {
1288     position_t *position = (position_t*)malloc(sizeof(position_t));
1289 
1290     assert(position != 0);
1291 
1292     position->x = x;
1293     position->y = y;
1294 
1295     position->next = pixel->collage_positions;
1296     pixel->collage_positions = position;
1297 }
1298 
1299 static int
pixel_valid_for_collage_position(void * data,metapixel_t * pixel,int x,int y)1300 pixel_valid_for_collage_position (void *data, metapixel_t *pixel, int x, int y)
1301 {
1302     int min_distance = (int)(unsigned long)data;
1303     position_t *position;
1304 
1305     if (min_distance <= 0)
1306 	return 1;
1307 
1308     for (position = pixel->collage_positions; position != 0; position = position->next)
1309 	if (manhattan_distance(x, y, position->x, position->y) < min_distance)
1310 	    return 0;
1311 
1312     return 1;
1313 }
1314 
1315 static void
generate_collage(char * input_name,char * output_name,float scale,int min_distance,int metric,int cheat)1316 generate_collage (char *input_name, char *output_name, float scale, int min_distance, int metric, int cheat)
1317 {
1318     unsigned char *in_image_data, *out_image_data;
1319     int in_image_width, in_image_height;
1320     char *bitmap;
1321     int num_pixels_done = 0;
1322 
1323     in_image_data = read_image(input_name, &in_image_width, &in_image_height);
1324     if (in_image_data == 0)
1325     {
1326 	fprintf(stderr, "could not read image `%s'\n", input_name);
1327 	exit(1);
1328     }
1329 
1330     if (scale != 1.0)
1331     {
1332 	int new_width = (float)in_image_width * scale;
1333 	int new_height = (float)in_image_height * scale;
1334 	unsigned char *scaled_data;
1335 
1336 	if (new_width < small_width || new_height < small_height)
1337 	{
1338 	    fprintf(stderr, "source image or scaling factor too small\n");
1339 	    exit(1);
1340 	}
1341 
1342 	printf("scaling source image to %dx%d\n", new_width, new_height);
1343 
1344 	scaled_data = scale_image(in_image_data, in_image_width, in_image_height,
1345 				  0, 0, in_image_width, in_image_height,
1346 				  new_width, new_height);
1347 
1348 	in_image_width = new_width;
1349 	in_image_height = new_height;
1350 
1351 	free(in_image_data);
1352 	in_image_data = scaled_data;
1353     }
1354 
1355     out_image_data = (unsigned char*)malloc(in_image_width * in_image_height * NUM_CHANNELS);
1356 
1357     bitmap = (char*)malloc(in_image_width * in_image_height);
1358     memset(bitmap, 0, in_image_width * in_image_height);
1359 
1360     while (num_pixels_done < in_image_width * in_image_height)
1361     {
1362 	int i, j;
1363 	int x, y;
1364 	coeffs_t coeffs;
1365 	match_t match;
1366 
1367 	while (1)
1368 	{
1369 	    x = random() % in_image_width - small_width / 2;
1370 	    y = random() % in_image_height - small_height / 2;
1371 
1372 	    if (x < 0)
1373 		x = 0;
1374 	    if (x + small_width > in_image_width)
1375 		x = in_image_width - small_width;
1376 
1377 	    if (y < 0)
1378 		y = 0;
1379 	    if (y + small_height > in_image_height)
1380 		y = in_image_height - small_height;
1381 
1382 	    for (j = 0; j < small_height; ++j)
1383 		for (i = 0; i < small_width; ++i)
1384 		    if (!bitmap[(y + j) * in_image_width + x + i])
1385 			goto out;
1386 	}
1387 
1388     out:
1389 	generate_search_coeffs_for_subimage(&coeffs, in_image_data, in_image_width, in_image_height,
1390 					    x, y, small_width, small_height, metric);
1391 
1392 	match = metapixel_nearest_to(&coeffs, metric, x, y, 0, 0,
1393 				     pixel_valid_for_collage_position, (void*)(unsigned long)min_distance);
1394 
1395 	if (match.pixel == 0)
1396 	{
1397 	    fprintf(stderr, "Error: cannot find a matching image - try using a shorter minimum distance.\n");
1398 	    exit(1);
1399 	}
1400 
1401 	paste_metapixel(match.pixel, out_image_data, in_image_width, in_image_height, x, y);
1402 
1403 	if (min_distance > 0)
1404 	    pixel_add_collage_position(match.pixel, x, y);
1405 
1406 	for (j = 0; j < small_height; ++j)
1407 	    for (i = 0; i < small_width; ++i)
1408 		if (!bitmap[(y + j) * in_image_width + x + i])
1409 		{
1410 		    bitmap[(y + j) * in_image_width + x + i] = 1;
1411 		    ++num_pixels_done;
1412 		}
1413 
1414 	printf(".");
1415 	fflush(stdout);
1416     }
1417 
1418     write_image(output_name, in_image_width, in_image_height, out_image_data, 3, in_image_width * 3, IMAGE_FORMAT_PNG);
1419 
1420     free(bitmap);
1421     free(out_image_data);
1422     free(in_image_data);
1423 }
1424 
1425 static int
read_tables(const char * library_dir)1426 read_tables (const char *library_dir)
1427 {
1428     lisp_object_t *pattern;
1429     lisp_object_t *obj;
1430     lisp_stream_t stream;
1431     int num_subs;
1432     pools_t pools;
1433     allocator_t allocator;
1434     int dir_strlen = strlen(library_dir);
1435     char tables_name[dir_strlen + 1 + strlen(TABLES_FILENAME) + 1];
1436 
1437     strcpy(tables_name, library_dir);
1438     strcat(tables_name, "/");
1439     strcat(tables_name, TABLES_FILENAME);
1440 
1441     if (lisp_stream_init_path(&stream, tables_name) == 0)
1442 	return 0;
1443 
1444     pattern = lisp_read_from_string("(small-image #?(string) (size #?(integer) #?(integer))"
1445 				    "  (wavelet (means #?(real) #?(real) #?(real)) (coeffs . #?(list)))"
1446 				    "  (subpixel (y . #?(list)) (i . #?(list)) (q . #?(list))))");
1447     assert(pattern != 0
1448 	   && lisp_type(pattern) != LISP_TYPE_EOF
1449 	   && lisp_type(pattern) != LISP_TYPE_PARSE_ERROR);
1450     assert(lisp_compile_pattern(&pattern, &num_subs));
1451     assert(num_subs == 10);
1452 
1453     init_pools(&pools);
1454     init_pools_allocator(&allocator, &pools);
1455 
1456     for (;;)
1457     {
1458         int type;
1459 
1460 	reset_pools(&pools);
1461         obj = lisp_read_with_allocator(&allocator, &stream);
1462         type = lisp_type(obj);
1463         if (type != LISP_TYPE_EOF && type != LISP_TYPE_PARSE_ERROR)
1464         {
1465             lisp_object_t *vars[10];
1466 
1467             if (lisp_match_pattern(pattern, obj, vars, num_subs))
1468 	    {
1469 		metapixel_t *pixel = new_metapixel();
1470 		coefficient_with_index_t coeffs[NUM_COEFFS];
1471 		lisp_object_t *lst;
1472 		int channel, i;
1473 		char *filename = strip_path(lisp_string(vars[0]));
1474 
1475 		pixel->filename = (char*)malloc(dir_strlen + 1 + strlen(filename) + 1);
1476 
1477 		strcpy(pixel->filename, library_dir);
1478 		strcat(pixel->filename, "/");
1479 		strcat(pixel->filename, filename);
1480 
1481 		for (channel = 0; channel < NUM_CHANNELS; ++channel)
1482 		    pixel->means[channel] = lisp_real(vars[3 + channel]);
1483 
1484 		if (lisp_list_length(vars[6]) != NUM_COEFFS)
1485 		    fprintf(stderr, "wrong number of wavelet coefficients in `%s'\n", pixel->filename);
1486 		else
1487 		{
1488 		    static float sums[NUM_COEFFS];
1489 
1490 		    lst = vars[6];
1491 		    for (i = 0; i < NUM_COEFFS; ++i)
1492 		    {
1493 			coeffs[i].index = lisp_integer(lisp_car(lst));
1494 			lst = lisp_cdr(lst);
1495 		    }
1496 
1497 		    generate_search_coeffs(&pixel->coeffs, sums, coeffs);
1498 		}
1499 
1500 		for (channel = 0; channel < NUM_CHANNELS; ++channel)
1501 		{
1502 		    lst = vars[7 + channel];
1503 
1504 		    if (lisp_list_length(lst) != NUM_SUBPIXELS)
1505 			fprintf(stderr, "wrong number of subpixels in `%s'\n", pixel->filename);
1506 		    else
1507 			for (i = 0; i < NUM_SUBPIXELS; ++i)
1508 			{
1509 			    pixel->subpixels[channel * NUM_SUBPIXELS + i] = lisp_integer(lisp_car(lst));
1510 			    lst = lisp_cdr(lst);
1511 			}
1512 		}
1513 
1514 		pixel->data = 0;
1515 		pixel->collage_positions = 0;
1516 
1517 		add_metapixel(pixel);
1518 	    }
1519 	    else
1520 	    {
1521 		fprintf(stderr, "unknown expression ");
1522 		lisp_dump(obj, stderr);
1523 		fprintf(stderr, "\n");
1524 	    }
1525         }
1526         else if (type == LISP_TYPE_PARSE_ERROR)
1527             fprintf(stderr, "Error: parse error in tables file.\n");
1528 
1529         if (type == LISP_TYPE_EOF)
1530             break;
1531     }
1532 
1533     lisp_stream_free_path(&stream);
1534 
1535     free_pools(&pools);
1536 
1537     return 1;
1538 }
1539 
1540 static metapixel_t*
find_metapixel(char * filename)1541 find_metapixel (char *filename)
1542 {
1543     metapixel_t *pixel;
1544 
1545     for (pixel = first_pixel; pixel != 0; pixel = pixel->next)
1546 	if (strcmp(pixel->filename, filename) == 0)
1547 	    return pixel;
1548 
1549     return 0;
1550 }
1551 
1552 static mosaic_t*
read_protocol(FILE * in)1553 read_protocol (FILE *in)
1554 {
1555     lisp_object_t *obj;
1556     lisp_stream_t stream;
1557     mosaic_t *mosaic = (mosaic_t*)malloc(sizeof(mosaic_t));
1558     int type;
1559 
1560     lisp_stream_init_file(&stream, in);
1561 
1562     obj = lisp_read(&stream);
1563     type = lisp_type(obj);
1564     if (type != LISP_TYPE_EOF && type != LISP_TYPE_PARSE_ERROR)
1565     {
1566 	lisp_object_t *vars[3];
1567 
1568 	if (lisp_match_string("(mosaic (size #?(integer) #?(integer)) (metapixels . #?(list)))",
1569 			      obj, vars))
1570 	{
1571 	    int i;
1572 	    int num_pixels;
1573 	    lisp_object_t *lst;
1574 
1575 	    mosaic->metawidth = lisp_integer(vars[0]);
1576 	    mosaic->metaheight = lisp_integer(vars[1]);
1577 	    num_pixels = mosaic->metawidth * mosaic->metaheight;
1578 	    mosaic->matches = (match_t*)malloc(sizeof(match_t) * num_pixels);
1579 
1580 	    for (i = 0; i < num_pixels; ++i)
1581 		mosaic->matches[i].pixel = 0;
1582 
1583 	    if (lisp_list_length(vars[2]) != num_pixels)
1584 	    {
1585 		fprintf(stderr, "mosaic should have %d metapixels, not %d\n", num_pixels, lisp_list_length(vars[2]));
1586 		exit(1);
1587 	    }
1588 
1589 	    lst = vars[2];
1590 	    for (i = 0; i < num_pixels; ++i)
1591 	    {
1592 		lisp_object_t *vars[5];
1593 
1594 		if (lisp_match_string("(#?(integer) #?(integer) #?(integer) #?(integer) #?(string))",
1595 				      lisp_car(lst), vars))
1596 		{
1597 		    int x = lisp_integer(vars[0]);
1598 		    int y = lisp_integer(vars[1]);
1599 		    int width = lisp_integer(vars[2]);
1600 		    int height = lisp_integer(vars[3]);
1601 		    metapixel_t *pixel;
1602 
1603 		    if (width != 1 || height != 1)
1604 		    {
1605 			fprintf(stderr, "width and height in metapixel must both be 1\n");
1606 			exit(1);
1607 		    }
1608 
1609 		    if (mosaic->matches[y * mosaic->metawidth + x].pixel != 0)
1610 		    {
1611 			fprintf(stderr, "location (%d,%d) is assigned to twice\n", x, y);
1612 			exit(1);
1613 		    }
1614 
1615 		    pixel = find_metapixel(lisp_string(vars[4]));
1616 
1617 		    if (pixel == 0)
1618 		    {
1619 			fprintf(stderr, "could not find metapixel `%s'\n", lisp_string(vars[4]));
1620 			exit(1);
1621 		    }
1622 
1623 		    mosaic->matches[y * mosaic->metawidth + x].pixel = pixel;
1624 		}
1625 		else
1626 		{
1627 		    fprintf(stderr, "metapixel ");
1628 		    lisp_dump(lisp_car(lst), stderr);
1629 		    fprintf(stderr, " has wrong format\n");
1630 		    exit(1);
1631 		}
1632 
1633 		lst = lisp_cdr(lst);
1634 	    }
1635 	}
1636 	else
1637 	{
1638 	    fprintf(stderr, "malformed expression in protocol file\n");
1639 	    exit(1);
1640 	}
1641     }
1642     else
1643     {
1644 	fprintf(stderr, "error in protocol file\n");
1645 	exit(1);
1646     }
1647     lisp_free(obj);
1648 
1649     return mosaic;
1650 }
1651 
1652 void
free_mosaic(mosaic_t * mosaic)1653 free_mosaic (mosaic_t *mosaic)
1654 {
1655     free(mosaic->matches);
1656     free(mosaic);
1657 }
1658 
1659 int
make_classic_mosaic(char * in_image_name,char * out_image_name,int metric,float scale,int search,int min_distance,int cheat,char * in_protocol_name,char * out_protocol_name)1660 make_classic_mosaic (char *in_image_name, char *out_image_name,
1661 		     int metric, float scale, int search, int min_distance, int cheat,
1662 		     char *in_protocol_name, char *out_protocol_name)
1663 {
1664     mosaic_t *mosaic;
1665     int x, y;
1666 
1667     if (in_protocol_name != 0)
1668     {
1669 	FILE *protocol_in = fopen(in_protocol_name, "rb");
1670 
1671 	if (protocol_in == 0)
1672 	{
1673 	    fprintf(stderr, "cannot open protocol file for reading `%s': %s\n", in_protocol_name, strerror(errno));
1674 	    return 0;
1675 	}
1676 
1677 	mosaic = read_protocol(protocol_in);
1678 
1679 	fclose(protocol_in);
1680     }
1681     else
1682     {
1683 	classic_reader_t *reader = init_classic_reader(in_image_name, scale);
1684 
1685 	if (search == SEARCH_LOCAL)
1686 	    mosaic = generate_local_classic(reader, min_distance, metric);
1687 	else if (search == SEARCH_GLOBAL)
1688 	    mosaic = generate_global_classic(reader, metric);
1689 	else
1690 	    assert(0);
1691 
1692 	free_classic_reader(reader);
1693     }
1694 
1695     assert(mosaic != 0);
1696 
1697     if (benchmark_rendering)
1698     {
1699 	int i;
1700 
1701 	for (i = 0; i < mosaic->metawidth * mosaic->metaheight; ++i)
1702 	{
1703 	    metapixel_t *pixel = mosaic->matches[i].pixel;
1704 
1705 	    if (pixel->data == 0)
1706 	    {
1707 		pixel->data = read_image(pixel->filename, &pixel->width, &pixel->height);
1708 
1709 		assert(pixel->data != 0);
1710 	    }
1711 	}
1712     }
1713 
1714     if (out_protocol_name != 0)
1715     {
1716 	FILE *protocol_out = fopen(out_protocol_name, "wb");
1717 
1718 	if (protocol_out == 0)
1719 	{
1720 	    fprintf(stderr, "cannot open protocol file `%s' for writing: %s\n", out_protocol_name, strerror(errno));
1721 	    /* FIXME: free stuff */
1722 	    return 0;
1723 	}
1724 	else
1725 	{
1726 	    fprintf(protocol_out, "(mosaic (size %d %d)\n(metapixels\n", mosaic->metawidth, mosaic->metaheight);
1727 	    for (y = 0; y < mosaic->metaheight; ++y)
1728 	    {
1729 		for (x = 0; x < mosaic->metawidth; ++x)
1730 		{
1731 		    match_t *match = &mosaic->matches[y * mosaic->metawidth + x];
1732 		    lisp_object_t *obj = lisp_make_string(match->pixel->filename);
1733 
1734 		    fprintf(protocol_out, "(%d %d 1 1 ", x, y);
1735 		    lisp_dump(obj, protocol_out);
1736 		    fprintf(protocol_out, ") ; %f\n", match->score);
1737 
1738 		    lisp_free(obj);
1739 		}
1740 	    }
1741 	    fprintf(protocol_out, "))\n");
1742 	}
1743 
1744 	fclose(protocol_out);
1745     }
1746 
1747     paste_classic(mosaic, in_image_name, out_image_name, cheat);
1748 
1749     free_mosaic(mosaic);
1750 
1751     return 1;
1752 }
1753 
1754 #define RC_FILE_NAME      ".metapixelrc"
1755 
1756 static void
read_rc_file(void)1757 read_rc_file (void)
1758 {
1759     lisp_stream_t stream;
1760     char *homedir;
1761     char *filename;
1762 
1763     homedir = getenv("HOME");
1764 
1765     if (homedir == 0)
1766     {
1767 	fprintf(stderr, "Warning: HOME is not in environment - cannot find rc file.\n");
1768 	return;
1769     }
1770 
1771     filename = (char*)malloc(strlen(homedir) + 1 + strlen(RC_FILE_NAME) + 1);
1772     strcpy(filename, homedir);
1773     strcat(filename, "/");
1774     strcat(filename, RC_FILE_NAME);
1775 
1776     if (access(filename, R_OK) == 0)
1777     {
1778 	if (lisp_stream_init_path(&stream, filename) == 0)
1779 	    fprintf(stderr, "Warning: could not open rc file `%s'.", filename);
1780 	else
1781 	{
1782 	    for (;;)
1783 	    {
1784 		lisp_object_t *obj;
1785 		int type;
1786 
1787 		obj = lisp_read(&stream);
1788 		type = lisp_type(obj);
1789 
1790 		if (type != LISP_TYPE_EOF && type != LISP_TYPE_PARSE_ERROR)
1791 		{
1792 		    lisp_object_t *vars[3];
1793 
1794 		    if (lisp_match_string("(prepare-directory #?(string))", obj, vars))
1795 			default_prepare_directory = strdup(lisp_string(vars[0]));
1796 		    else if (lisp_match_string("(prepare-dimensions #?(integer) #?(integer))", obj, vars))
1797 		    {
1798 			default_prepare_width = lisp_integer(vars[0]);
1799 			default_prepare_height = lisp_integer(vars[1]);
1800 		    }
1801 		    else if (lisp_match_string("(library-directory #?(string))", obj, vars))
1802 			default_library_directories = string_list_prepend_copy(default_library_directories,
1803 									       lisp_string(vars[0]));
1804 		    else if (lisp_match_string("(small-image-dimensions #?(integer) #?(integer))", obj, vars))
1805 		    {
1806 			default_small_width = lisp_integer(vars[0]);
1807 			default_small_height = lisp_integer(vars[1]);
1808 		    }
1809 		    else if (lisp_match_string("(yiq-weights #?(number) #?(number) #?(number))", obj, vars))
1810 		    {
1811 			int i;
1812 
1813 			for (i = 0; i < 3; ++i)
1814 			    default_weight_factors[i] = lisp_real(vars[i]);
1815 		    }
1816 		    else if (lisp_match_string("(metric #?(or wavelet subpixel))", obj, vars))
1817 		    {
1818 			if (strcmp(lisp_symbol(vars[0]), "wavelet") == 0)
1819 			    default_metric = METRIC_WAVELET;
1820 			else
1821 			    default_metric = METRIC_SUBPIXEL;
1822 		    }
1823 		    else if (lisp_match_string("(search-method #?(or local global))", obj, vars))
1824 		    {
1825 			if (strcmp(lisp_symbol(vars[0]), "local") == 0)
1826 			    default_search = SEARCH_LOCAL;
1827 			else
1828 			    default_search = SEARCH_GLOBAL;
1829 		    }
1830 		    else if (lisp_match_string("(minimum-classic-distance #?(integer))", obj, vars))
1831 			default_classic_min_distance = lisp_integer(vars[0]);
1832 		    else if (lisp_match_string("(minimum-collage-distance #?(integer))", obj, vars))
1833 			default_collage_min_distance = lisp_integer(vars[0]);
1834 		    else if (lisp_match_string("(cheat-amount #?(integer))", obj, vars))
1835 			default_cheat_amount = lisp_integer(vars[0]);
1836 		    else if (lisp_match_string("(forbid-reconstruction-distance #?(integer))", obj, vars))
1837 			default_forbid_reconstruction_radius = lisp_integer(vars[0]);
1838 		    else
1839 		    {
1840 			fprintf(stderr, "Warning: unknown rc file option ");
1841 			lisp_dump(obj, stderr);
1842 			fprintf(stderr, "\n");
1843 		    }
1844 		}
1845 		else if (type == LISP_TYPE_PARSE_ERROR)
1846 		    fprintf(stderr, "Error: parse error in rc file.\n");
1847 
1848 		lisp_free(obj);
1849 
1850 		if (type == LISP_TYPE_EOF || type == LISP_TYPE_PARSE_ERROR)
1851 		    break;
1852 	    }
1853 
1854 	    lisp_stream_free_path(&stream);
1855 	}
1856     }
1857 
1858     free(filename);
1859 }
1860 
1861 static void
usage(void)1862 usage (void)
1863 {
1864     printf("Usage:\n"
1865 	   "  metapixel --version\n"
1866 	   "      print out version number\n"
1867 	   "  metapixel --help\n"
1868 	   "      print this help text\n"
1869 	   "  metapixel [option ...] --prepare <inimage> <outimage> <tablefile>\n"
1870 	   "      calculate and output tables for <file>\n"
1871 	   "  metapixel [option ...] --metapixel <in> <out>\n"
1872 	   "      transform <in> to <out>\n"
1873 	   "  metapixel [option ...] --batch <batchfile>\n"
1874 	   "      perform all the tasks in <batchfile>\n"
1875 	   "Options:\n"
1876 	   "  -l, --library=DIR            add the library in DIR\n"
1877 	   "  -x, --antimosaic=PIC         use PIC as an antimosaic\n"
1878 	   "  -w, --width=WIDTH            set width for small images\n"
1879 	   "  -h, --height=HEIGHT          set height for small images\n"
1880 	   "  -y, --y-weight=WEIGHT        assign relative weight for the Y-channel\n"
1881 	   "  -i, --i-weight=WEIGHT        assign relative weight for the I-channel\n"
1882 	   "  -q, --q-weight=WEIGHT        assign relative weight for the Q-channel\n"
1883 	   "  -s  --scale=SCALE            scale input image by specified factor\n"
1884 	   "  -m, --metric=METRIC          choose metric (subpixel or wavelet)\n"
1885 	   "  -e, --search=SEARCH          choose search method (local or global)\n"
1886 	   "  -c, --collage                collage mode\n"
1887 	   "  -d, --distance=DIST          minimum distance between two instances of\n"
1888 	   "                               the same constituent image\n"
1889 	   "  -a, --cheat=PERC             cheat with specified percentage\n"
1890 	   "  -f, --forbid-reconstruction=DIST\n"
1891 	   "                               forbid placing antimosaic images on their\n"
1892 	   "                               original locations or locations around it\n"
1893 	   "  --out=FILE                   write protocol to file\n"
1894 	   "  --in=FILE                    read protocol from file and use it\n"
1895 	   "\n"
1896 	   "Report bugs and suggestions to schani@complang.tuwien.ac.at\n");
1897 }
1898 
1899 #define OPT_VERSION                    256
1900 #define OPT_HELP                       257
1901 #define OPT_PREPARE                    258
1902 #define OPT_METAPIXEL                  259
1903 #define OPT_BATCH                      260
1904 #define OPT_OUT                        261
1905 #define OPT_IN                         262
1906 #define OPT_BENCHMARK_RENDERING        263
1907 #define OPT_PRINT_PREPARE_SETTINGS     264
1908 
1909 #define MODE_NONE       0
1910 #define MODE_PREPARE    1
1911 #define MODE_METAPIXEL  2
1912 #define MODE_BATCH      3
1913 
1914 int
main(int argc,char * argv[])1915 main (int argc, char *argv[])
1916 {
1917     int mode = MODE_NONE;
1918     int metric;
1919     int search;
1920     int collage = 0;
1921     int classic_min_distance, collage_min_distance;
1922     int cheat = 0;
1923     float scale = 1.0;
1924     char *out_filename = 0;
1925     char *in_filename = 0;
1926     char *antimosaic_filename = 0;
1927     string_list_t *library_directories = 0;
1928     int prepare_width = 0, prepare_height = 0;
1929 
1930     read_rc_file();
1931 
1932     small_width = default_small_width;
1933     small_height = default_small_height;
1934     prepare_width = default_prepare_width;
1935     prepare_height = default_prepare_height;
1936     memcpy(weight_factors, default_weight_factors, sizeof(weight_factors));
1937     metric = default_metric;
1938     search = default_search;
1939     classic_min_distance = default_classic_min_distance;
1940     collage_min_distance = default_collage_min_distance;
1941     cheat = default_cheat_amount;
1942     forbid_reconstruction_radius = default_forbid_reconstruction_radius + 1;
1943 
1944     while (1)
1945     {
1946 	static struct option long_options[] =
1947             {
1948 		{ "version", no_argument, 0, OPT_VERSION },
1949 		{ "help", no_argument, 0, OPT_HELP },
1950 		{ "prepare", no_argument, 0, OPT_PREPARE },
1951 		{ "metapixel", no_argument, 0, OPT_METAPIXEL },
1952 		{ "batch", no_argument, 0, OPT_BATCH },
1953 		{ "out", required_argument, 0, OPT_OUT },
1954 		{ "in", required_argument, 0, OPT_IN },
1955 		{ "benchmark-rendering", no_argument, 0, OPT_BENCHMARK_RENDERING },
1956 		{ "print-prepare-settings", no_argument, 0, OPT_PRINT_PREPARE_SETTINGS },
1957 		{ "library", required_argument, 0, 'l' },
1958 		{ "width", required_argument, 0, 'w' },
1959 		{ "height", required_argument, 0, 'h' },
1960 		{ "y-weight", required_argument, 0, 'y' },
1961 		{ "i-weight", required_argument, 0, 'i' },
1962 		{ "q-weight", required_argument, 0, 'q' },
1963 		{ "scale", required_argument, 0, 's' },
1964 		{ "collage", no_argument, 0, 'c' },
1965 		{ "distance", required_argument, 0, 'd' },
1966 		{ "cheat", required_argument, 0, 'a' },
1967 		{ "metric", required_argument, 0, 'm' },
1968 		{ "search", required_argument, 0, 'e' },
1969 		{ "antimosaic", required_argument, 0, 'x' },
1970 		{ "forbid-reconstruction", required_argument, 0, 'f' },
1971 		{ 0, 0, 0, 0 }
1972 	    };
1973 
1974 	int option, option_index;
1975 
1976 	option = getopt_long(argc, argv, "l:m:e:w:h:y:i:q:s:cd:a:x:f:", long_options, &option_index);
1977 
1978 	if (option == -1)
1979 	    break;
1980 
1981 	switch (option)
1982 	{
1983 	    case OPT_PREPARE :
1984 		mode = MODE_PREPARE;
1985 		break;
1986 
1987 	    case OPT_METAPIXEL :
1988 		mode = MODE_METAPIXEL;
1989 		break;
1990 
1991 	    case OPT_BATCH :
1992 		mode = MODE_BATCH;
1993 		break;
1994 
1995 	    case OPT_OUT :
1996 		if (out_filename != 0)
1997 		{
1998 		    fprintf(stderr, "the --out option can be used at most once\n");
1999 		    return 1;
2000 		}
2001 		out_filename = strdup(optarg);
2002 		assert(out_filename != 0);
2003 		break;
2004 
2005 	    case OPT_IN :
2006 		if (in_filename != 0)
2007 		{
2008 		    fprintf(stderr, "the --in option can be used at most once\n");
2009 		    return 1;
2010 		}
2011 		in_filename = strdup(optarg);
2012 		assert(in_filename != 0);
2013 		break;
2014 
2015 	    case OPT_BENCHMARK_RENDERING :
2016 		benchmark_rendering = 1;
2017 		break;
2018 
2019 	    case OPT_PRINT_PREPARE_SETTINGS :
2020 		printf("%d %d %s\n", default_prepare_width, default_prepare_height,
2021 		       default_prepare_directory != 0 ? default_prepare_directory : "");
2022 		exit(0);
2023 		break;
2024 
2025 	    case 'm' :
2026 		if (strcmp(optarg, "wavelet") == 0)
2027 		    metric = METRIC_WAVELET;
2028 		else if (strcmp(optarg, "subpixel") == 0)
2029 		    metric = METRIC_SUBPIXEL;
2030 		else
2031 		{
2032 		    fprintf(stderr, "metric must either be subpixel or wavelet\n");
2033 		    return 1;
2034 		}
2035 		break;
2036 
2037 	    case 'e' :
2038 		if (strcmp(optarg, "local") == 0)
2039 		    search = SEARCH_LOCAL;
2040 		else if (strcmp(optarg, "global") == 0)
2041 		    search = SEARCH_GLOBAL;
2042 		else
2043 		{
2044 		    fprintf(stderr, "search method must either be local or global\n");
2045 		    return 1;
2046 		}
2047 		break;
2048 
2049 	    case 'w' :
2050 		small_width = prepare_width = atoi(optarg);
2051 		break;
2052 
2053 	    case 'h' :
2054 		small_height = prepare_height = atoi(optarg);
2055 		break;
2056 
2057 	    case 'y' :
2058 		weight_factors[0] = atof(optarg);
2059 		break;
2060 
2061 	    case 'i' :
2062 		weight_factors[1] = atof(optarg);
2063 		break;
2064 
2065 	    case 'q' :
2066 		weight_factors[2] = atof(optarg);
2067 		break;
2068 
2069 	    case 's':
2070 		scale = atof(optarg);
2071 		break;
2072 
2073 	    case 'c' :
2074 		collage = 1;
2075 		break;
2076 
2077 	    case 'd' :
2078 		classic_min_distance = collage_min_distance = atoi(optarg);
2079 		break;
2080 
2081 	    case 'a' :
2082 		cheat = atoi(optarg);
2083 		break;
2084 
2085 	    case 'l' :
2086 		if (antimosaic_filename != 0)
2087 		{
2088 		    fprintf(stderr, "Error: --library and --antimosaic cannot be used together.\n");
2089 		    return 1;
2090 		}
2091 
2092 		library_directories = string_list_prepend_copy(library_directories, optarg);
2093 		break;
2094 
2095 	    case 'x' :
2096 		if (antimosaic_filename != 0)
2097 		{
2098 		    fprintf(stderr, "Error: at most one antimosaic picture can be specified.\n");
2099 		    return 1;
2100 		}
2101 		else if (library_directories != 0)
2102 		{
2103 		    fprintf(stderr, "Error: --library and --antimosaic cannot be used together.\n");
2104 		    return 1;
2105 		}
2106 		antimosaic_filename = strdup(optarg);
2107 		break;
2108 
2109 	    case 'f' :
2110 		forbid_reconstruction_radius = atoi(optarg) + 1;
2111 		break;
2112 
2113 	    case OPT_VERSION :
2114 		printf("metapixel " METAPIXEL_VERSION "\n"
2115 		       "\n"
2116 		       "Copyright (C) 1997-2006 Mark Probst\n"
2117 		       "\n"
2118 		       "This program is free software; you can redistribute it and/or modify\n"
2119 		       "it under the terms of the GNU General Public License as published by\n"
2120 		       "the Free Software Foundation; either version 2 of the License, or\n"
2121 		       "(at your option) any later version.\n"
2122 		       "\n"
2123 		       "This program is distributed in the hope that it will be useful,\n"
2124 		       "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2125 		       "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
2126 		       "GNU General Public License for more details.\n"
2127 		       "\n"
2128 		       "You should have received a copy of the GNU General Public License\n"
2129 		       "along with this program; if not, write to the Free Software\n"
2130 		       "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n");
2131 		exit(0);
2132 
2133 	    case OPT_HELP :
2134 		usage();
2135 		return 0;
2136 
2137 	    default :
2138 		assert(0);
2139 	}
2140     }
2141 
2142     /* check settings for soundness */
2143     if (small_height <= 0)
2144     {
2145 	fprintf(stderr, "Error: height of small images must be positive.\n");
2146 	return 1;
2147     }
2148     if (small_width <= 0)
2149     {
2150 	fprintf(stderr, "Error: width of small images must be positive.\n");
2151 	return 1;
2152     }
2153     if (scale <= 0.0)
2154     {
2155 	fprintf(stderr, "Error: scale factor must be positive.\n");
2156 	return 1;
2157     }
2158     if (classic_min_distance < 0)
2159     {
2160 	fprintf(stderr, "Error: classic minimum distance must be non-negative.\n");
2161 	return 1;
2162     }
2163     if (collage_min_distance < 0)
2164     {
2165 	fprintf(stderr, "Error: collage minimum distance must be non-negative.\n");
2166 	return 1;
2167     }
2168     if (cheat < 0 || cheat > 100)
2169     {
2170 	fprintf(stderr, "Error: cheat amount must be in the range from 0 to 100.\n");
2171 	return 1;
2172     }
2173     /* the value in forbid_reconstruction_radius is always one more
2174        than the user specified */
2175     if (forbid_reconstruction_radius <= 0)
2176     {
2177 	fprintf(stderr, "Error: forbid reconstruction distance must be non-negative.\n");
2178 	return 1;
2179     }
2180 
2181     if (in_filename != 0 || out_filename != 0)
2182     {
2183 	if (mode != MODE_METAPIXEL)
2184 	{
2185 	    fprintf(stderr, "the --in and --out options can only be used in metapixel mode\n");
2186 	    return 1;
2187 	}
2188 	if (collage)
2189 	{
2190 	    fprintf(stderr, "the --in and --out options can only be used for classic mosaics\n");
2191 	    return 1;
2192 	}
2193     }
2194 
2195     sqrt_of_two = sqrt(2);
2196     sqrt_of_image_size = sqrt(IMAGE_SIZE);
2197 
2198     compute_index_weights();
2199 
2200     if (mode == MODE_PREPARE)
2201     {
2202 	static coefficient_with_index_t highest_coeffs[NUM_COEFFS];
2203 
2204 	int i, channel;
2205 	unsigned char *image_data;
2206 	unsigned char *scaled_data;
2207 	char *inimage_name, *outimage_name, *tables_name;
2208 	FILE *tables_file;
2209 	int in_width, in_height;
2210 	metapixel_t pixel;
2211 	lisp_object_t *obj;
2212 
2213 	if (argc - optind != 3)
2214 	{
2215 	    usage();
2216 	    return 1;
2217 	}
2218 
2219 	assert(prepare_width > 0 && prepare_height > 0);
2220 
2221 	inimage_name = argv[optind + 0];
2222 	outimage_name = argv[optind + 1];
2223 	tables_name = argv[optind + 2];
2224 
2225 	image_data = read_image(inimage_name, &in_width, &in_height);
2226 
2227 	if (image_data == 0)
2228 	{
2229 	    fprintf(stderr, "could not read image `%s'\n", inimage_name);
2230 	    return 1;
2231 	}
2232 
2233 	tables_file = fopen(tables_name, "ab");
2234 	if (tables_file == 0)
2235 	{
2236 	    fprintf(stderr, "could not open file `%s' for writing\n", tables_name);
2237 	    return 1;
2238 	}
2239 
2240 	/* generate small image */
2241 	scaled_data = scale_image(image_data, in_width, in_height, 0, 0,
2242 				  in_width, in_height, prepare_width, prepare_height);
2243 	assert(scaled_data != 0);
2244 
2245 	write_image(outimage_name, prepare_width, prepare_height, scaled_data, 3, prepare_width * 3, IMAGE_FORMAT_PNG);
2246 
2247 	generate_metapixel_coefficients(&pixel, scaled_data, highest_coeffs);
2248 
2249 	free(scaled_data);
2250 
2251 	fprintf(tables_file, "(small-image ");
2252 	obj = lisp_make_string(strip_path(outimage_name));
2253 	lisp_dump(obj, tables_file);
2254 	lisp_free(obj);
2255 
2256 	fprintf(tables_file, " (size %d %d) (wavelet (means %f %f %f) (coeffs",
2257 		prepare_width, prepare_height,
2258 		pixel.means[0], pixel.means[1], pixel.means[2]);
2259 	for (i = 0; i < NUM_COEFFS; ++i)
2260 	    fprintf(tables_file, " %d", highest_coeffs[i].index);
2261 
2262 	fprintf(tables_file, ")) (subpixel");
2263 	for (channel = 0; channel < NUM_CHANNELS; ++channel)
2264 	{
2265 	    static char *channel_names[] = { "y", "i", "q" };
2266 
2267 	    fprintf(tables_file, " (%s", channel_names[channel]);
2268 	    for (i = 0; i < NUM_SUBPIXELS; ++i)
2269 		fprintf(tables_file, " %d", (int)pixel.subpixels[channel * NUM_SUBPIXELS + i]);
2270 	    fprintf(tables_file, ")");
2271 	}
2272 	fprintf(tables_file, "))\n");
2273 
2274 	fclose(tables_file);
2275     }
2276     else if (mode == MODE_METAPIXEL
2277 	     || mode == MODE_BATCH)
2278     {
2279 	if ((mode == MODE_METAPIXEL && argc - optind != 2)
2280 	    || (mode == MODE_BATCH && argc - optind != 1))
2281 	{
2282 	    usage();
2283 	    return 1;
2284 	}
2285 
2286 	if (antimosaic_filename == 0 && library_directories == 0)
2287 	    library_directories = default_library_directories;
2288 
2289 	if (antimosaic_filename != 0)
2290 	{
2291 	    classic_reader_t *reader = init_classic_reader(antimosaic_filename, scale);
2292 	    int x, y;
2293 
2294 	    for (y = 0; y < reader->metaheight; ++y)
2295 	    {
2296 		read_classic_row(reader);
2297 
2298 		for (x = 0; x < reader->metawidth; ++x)
2299 		{
2300 		    static coefficient_with_index_t highest_coeffs[NUM_COEFFS];
2301 
2302 		    unsigned char *scaled_data;
2303 		    metapixel_t *pixel = new_metapixel();
2304 		    int left_x, width;
2305 
2306 		    compute_classic_column_coords(reader, x, &left_x, &width);
2307 		    scaled_data = scale_image(reader->in_image_data, reader->in_image_width, reader->num_lines,
2308 					      left_x, 0, width, reader->num_lines, small_width, small_height);
2309 		    assert(scaled_data != 0);
2310 
2311 		    generate_metapixel_coefficients(pixel, scaled_data, highest_coeffs);
2312 
2313 		    pixel->data = scaled_data;
2314 		    pixel->width = small_width;
2315 		    pixel->height = small_height;
2316 		    pixel->anti_x = x;
2317 		    pixel->anti_y = y;
2318 		    pixel->collage_positions = 0;
2319 
2320 		    pixel->filename = (char*)malloc(64);
2321 		    sprintf(pixel->filename, "(%d,%d)", x, y);
2322 
2323 		    add_metapixel(pixel);
2324 
2325 		    printf(":");
2326 		    fflush(stdout);
2327 		}
2328 	    }
2329 
2330 	    printf("\n");
2331 
2332 	    free_classic_reader(reader);
2333 	}
2334 	else if (library_directories != 0)
2335 	{
2336 	    string_list_t *lst;
2337 
2338 	    for (lst = library_directories; lst != 0; lst = lst->next)
2339 		if (!read_tables(lst->str))
2340 		{
2341 		    fprintf(stderr, "Error: cannot read library table `%s/%s'.\n", lst->str, TABLES_FILENAME);
2342 		    return 1;
2343 		}
2344 
2345 	    forbid_reconstruction_radius = 0;
2346 	}
2347 	else
2348 	{
2349 	    fprintf(stderr, "Error: you must give one of the option --library and --antimosaic.\n");
2350 	    return 1;
2351 	}
2352 
2353 	if (mode == MODE_METAPIXEL)
2354 	{
2355 	    if (collage)
2356 		generate_collage(argv[optind], argv[optind + 1], scale, collage_min_distance,
2357 				 metric, cheat);
2358 	    else
2359 		make_classic_mosaic(argv[optind], argv[optind + 1],
2360 				    metric, scale, search, classic_min_distance, cheat,
2361 				    in_filename, out_filename);
2362 	}
2363 	else if (mode == MODE_BATCH)
2364 	{
2365 	    FILE *in = fopen(argv[optind], "rb");
2366 	    lisp_stream_t stream;
2367 
2368 	    if (in == 0)
2369 	    {
2370 		fprintf(stderr, "cannot open batch file `%s': %s\n", argv[optind], strerror(errno));
2371 		return 1;
2372 	    }
2373 
2374 	    lisp_stream_init_file(&stream, in);
2375 
2376 	    for (;;)
2377 	    {
2378 		lisp_object_t *obj = lisp_read(&stream);
2379 		int type = lisp_type(obj);
2380 
2381 		if (type != LISP_TYPE_EOF && type != LISP_TYPE_PARSE_ERROR)
2382 		{
2383 		    lisp_object_t *vars[4];
2384 
2385 		    if (lisp_match_string("(classic (#?(or image protocol) #?(string)) #?(string) . #?(list))",
2386 					  obj, vars))
2387 		    {
2388 			float this_scale = scale;
2389 			int this_search = search;
2390 			int this_min_distance = classic_min_distance;
2391 			int this_cheat = cheat;
2392 			int this_metric = metric;
2393 			char *this_prot_in_filename = in_filename;
2394 			char *this_prot_out_filename = out_filename;
2395 			char *this_image_out_filename = lisp_string(vars[2]);
2396 			char *this_image_in_filename = 0;
2397 			lisp_object_t *lst;
2398 			lisp_object_t *var;
2399 
2400 			if (strcmp(lisp_symbol(vars[0]), "image") == 0)
2401 			    this_image_in_filename = lisp_string(vars[1]);
2402 			else
2403 			    this_prot_in_filename = lisp_string(vars[1]);
2404 
2405 			for (lst = vars[3]; lisp_type(lst) != LISP_TYPE_NIL; lst = lisp_cdr(lst))
2406 			{
2407 			    if (lisp_match_string("(scale #?(real))",
2408 						  lisp_car(lst), &var))
2409 			    {
2410 				float val = lisp_real(var);
2411 
2412 				if (val <= 0.0)
2413 				    fprintf(stderr, "scale must be larger than 0\n");
2414 				else
2415 				    this_scale = val;
2416 			    }
2417 			    else if (lisp_match_string("(search #?(or local global))",
2418 						       lisp_car(lst), &var))
2419 			    {
2420 				if (strcmp(lisp_symbol(var), "local") == 0)
2421 				    this_search = SEARCH_LOCAL;
2422 				else
2423 				    this_search = SEARCH_GLOBAL;
2424 			    }
2425 			    else if (lisp_match_string("(min-distance #?(integer))",
2426 						       lisp_car(lst), &var))
2427 			    {
2428 				int val = lisp_integer(var);
2429 
2430 				if (val < 0)
2431 				    fprintf(stderr, "min-distance cannot be negative\n");
2432 				else
2433 				    this_min_distance = val;
2434 			    }
2435 			    else if (lisp_match_string("(cheat #?(integer))",
2436 						       lisp_car(lst), &var))
2437 			    {
2438 				int val = lisp_integer(var);
2439 
2440 				if (val < 0 || val > 100)
2441 				    fprintf(stderr, "cheat must be between 0 and 100, inclusively\n");
2442 				else
2443 				    this_cheat = val;
2444 
2445 			    }
2446 			    else if (lisp_match_string("(metric #?(or subpixel wavelet))",
2447 						       lisp_car(lst), &var))
2448 			    {
2449 				if (strcmp(lisp_symbol(var), "subpixel") == 0)
2450 				    this_metric = METRIC_SUBPIXEL;
2451 				else
2452 				    this_metric = METRIC_WAVELET;
2453 			    }
2454 			    else if (lisp_match_string("(protocol #?(string))",
2455 						       lisp_car(lst), &var))
2456 				this_prot_out_filename = lisp_string(var);
2457 			    else
2458 			    {
2459 				fprintf(stderr, "unknown expression ");
2460 				lisp_dump(lisp_car(lst), stderr);
2461 				fprintf(stderr, "\n");
2462 			    }
2463 			}
2464 
2465 			make_classic_mosaic(this_image_in_filename, this_image_out_filename,
2466 					    this_metric, this_scale, this_search, this_min_distance, this_cheat,
2467 					    this_prot_in_filename, this_prot_out_filename);
2468 		    }
2469 		    else
2470 		    {
2471 			fprintf(stderr, "unknown expression ");
2472 			lisp_dump(obj, stderr);
2473 			fprintf(stderr, "\n");
2474 		    }
2475 		}
2476 		else if (type == LISP_TYPE_PARSE_ERROR)
2477 		    fprintf(stderr, "parse error in batch file\n");
2478 		lisp_free(obj);
2479 
2480 		if (type == LISP_TYPE_EOF)
2481 		    break;
2482 	    }
2483 	}
2484 	else
2485 	    assert(0);
2486     }
2487     else
2488     {
2489 	usage();
2490 	return 1;
2491     }
2492 
2493     return 0;
2494 }
2495