static int each_conv (Babl *babl, void *data) { double error, cost; if (BABL (babl->conversion.source)->class_type != BABL_FORMAT) return 0; error = babl_conversion_error (&babl->conversion); cost = babl_conversion_cost (&babl->conversion); if (error > legal_error ()) { fprintf (output_file, "<dt style='background-color: #fcc;'>%s</dt>", babl->instance.name); fprintf (output_file, "<dd style='background-color: #fcc;'>"); } else { fprintf (output_file, "<dt>%s</dt><dd>", babl->instance.name); } fprintf (output_file, "<em>error:</em> %f <em>cost:</em> %4.0f <em>processings:</em> %i <em>pixels:</em> %li", error, cost, babl->conversion.processings, babl->conversion.pixels); fprintf (output_file, "</dd>"); return 0; }
static long babl_fish_process (Babl *babl, const void *source, void *destination, long n) { long ret = 0; switch (babl->class_type) { case BABL_FISH_REFERENCE: if (babl->fish.source == babl->fish.destination) { /* XXX: we're assuming linear buffers */ memcpy (destination, source, n * babl->fish.source->format.bytes_per_pixel); ret = n; } else { ret = babl_fish_reference_process (babl, source, destination, n); } break; case BABL_FISH_SIMPLE: if (BABL (babl->fish_simple.conversion)->class_type == BABL_CONVERSION_LINEAR) { ret = babl_conversion_process (BABL (babl->fish_simple.conversion), source, destination, n); } else { babl_fatal ("Cannot use a simple fish to process without a linear conversion"); } break; case BABL_FISH_PATH: ret = babl_fish_path_process (babl, source, destination, n); break; default: babl_log ("NYI"); ret = -1; break; } return ret; }
static void format_html (Babl *babl) { int i; printf ("<dl>"); printf ("<dt>bytes/pixel</dt><dd>%i</dd>", babl->format.bytes_per_pixel); printf ("<dt>model</dt><dd>%s</dd>", BABL (babl->format.model)->instance.name); printf ("<dt>components</dt><dd><table class='nopad'>"); for (i = 0; i < babl->format.components; i++) { printf ("<tr><td class='type'>%s</td><td class='component'>%s</td></tr>", BABL (babl->format.type[i])->instance.name, BABL (babl->format.component[i])->instance.name); } printf ("</table></dd></dl>"); }
static void conversion_introspect (Babl *babl) { babl_log ("\t\tprocessings:%i pixels:%li", babl->conversion.processings, babl->conversion.pixels); if (BABL (babl->conversion.source)->class_type == BABL_FORMAT) { babl_log ("\t\terror: %f", babl_conversion_error (&babl->conversion)); } }
Babl * babl_conversion_find (const void *source, const void *destination) { void *data = (void*)destination; babl_list_each (BABL (source)->type.from_list, match_conversion, &data); if (data == (void*)destination) /* didn't change */ return NULL; return data; }
static void model_introspect (Babl *babl) { int i; babl_log ("\t\tcomponents=%i", babl->model.components); for (i = 0; i < babl->model.components; i++) { babl_log ("\t\tindex[%i] = \"%s\"", i, BABL (babl->model.component[i])->instance.name); } }
static void model_html (Babl *babl) { int i; printf ("<dl>"); printf ("<dt>components</dt><dd><table class='nopad'>"); for (i = 0; i < babl->model.components; i++) { printf ("<tr><td class='type'>%s</td></tr>", BABL (babl->model.component[i])->instance.name); } printf ("</table></dd></dl>"); }
static void item_conversions_introspect (Babl *babl) { int i; BablList *list; list = babl->type.from_list; if (list) { babl_log ("\t\tconversions from %s: %i", babl->instance.name, babl_list_size (list)); for (i = 0; i < babl_list_size (list); i++) babl_log ("\t\t\t'%s'", BABL (list->items[i])->instance.name); } }
static int table_destination_each (Babl *babl, void *userdata) { Babl *source = userdata; Babl *destination = babl; qux++; if (qux % babl_formats_count () == qux / babl_formats_count ()) fprintf (output_file, "<td class='cell'> </td>"); else { const Babl *fish = babl_fish (source, destination); babl_assert (fish); switch (fish->class_type) { case BABL_FISH_PATH: fprintf (output_file, "<td class='cell'%s><a href='javascript:o()'>%s", fish->fish.pixels / sum_pixels > LIMIT ? " style='background-color: #69f'" : "", utf8_bar[babl_list_size (fish->fish_path.conversion_list)]); { int i; fprintf (output_file, "<div class='tooltip'>"); fprintf (output_file, "<h3><span class='g'>path</span> %s <span class='g'>to</span> %s</h3>", source->instance.name, destination->instance.name); if (fish->fish.processings > 0) { fprintf (output_file, "<span class='g'>Processings:</span>%i<br/>", fish->fish.processings); fprintf (output_file, "<span class='g'>Pixels:</span>%li<br/>", fish->fish.pixels); } fprintf (output_file, "<table>\n"); fprintf (output_file, "<tr>"); fprintf (output_file, "<td><em>conversion</em></td>"); fprintf (output_file, "<td style='text-align:right'><em>cost</em></td>"); fprintf (output_file, "<td style='text-align:right'><em>error</em></td>"); fprintf (output_file, "</tr>"); for (i = 0; i < babl_list_size (fish->fish_path.conversion_list); i++) { fprintf (output_file, "<tr>"); fprintf (output_file, "<td>%s</td>", BABL (fish->fish_path.conversion_list->items[i])->instance.name); fprintf (output_file, "<td class='r'>%li</td>", babl_conversion_cost (&BABL (fish->fish_path.conversion_list->items[i])->conversion)); fprintf (output_file, "<td class='r'>%e</td>", babl_conversion_error (&BABL (fish->fish_path.conversion_list->items[i])->conversion)); fprintf (output_file, "</tr>"); } fprintf (output_file, "<tr>"); fprintf (output_file, "<td><em>total</em></td>"); fprintf (output_file, "<td class='r'><em>%3.0f</em></td>", fish->fish_path.cost); fprintf (output_file, "<td class='r'><em>%e</em></td>", fish->fish.error); fprintf (output_file, "</tr>"); fprintf (output_file, "</table>"); fprintf (output_file, "</div>"); } fprintf (output_file, "</a></td>\n"); break; case BABL_FISH_REFERENCE: fprintf (output_file, "<td class='cell'%s><a href='javascript:o()'> ", fish->fish.pixels / sum_pixels > LIMIT ? " style='background-color: #f99'" : ""); fprintf (output_file, "<div class='tooltip'>"); fprintf (output_file, "<h3><span class='g'>Reference</span> %s <span class='g'>to</span> %s</h3>", source->instance.name, destination->instance.name); if (fish->fish.processings > 1) { fprintf (output_file, "<span class='g'>Processings:</span>%i<br/>", fish->fish.processings); fprintf (output_file, "<span class='g'>Pixels:</span>%li<br/>", fish->fish.pixels); } fprintf (output_file, "</div>"); fprintf (output_file, "</a></td>\n"); break; case BABL_FISH_SIMPLE: fprintf (output_file, "<td class='cell'%s><a href='javascript:o()'>·", fish->fish.pixels / sum_pixels > LIMIT ? " style='background-color: #69f'" : ""); fprintf (output_file, "<div class='tooltip'>"); fprintf (output_file, "<h3><span class='g'>Simple</span> %s <span class='g'>to</span> %s</h3>", source->instance.name, destination->instance.name); fprintf (output_file, "%s<br/>", BABL (fish->fish_simple.conversion)->instance.name); fprintf (output_file, "<span class='g'>cost:</span> %li<br/>", babl_conversion_cost ((fish->fish_simple.conversion))); fprintf (output_file, "<span class='g'>error:</span> %e<br/>", babl_conversion_error ((fish->fish_simple.conversion))); if (fish->fish.processings > 0) { fprintf (output_file, "<span class='g'>Processings:</span>%i<br/>", fish->fish.processings); fprintf (output_file, "<span class='g'>Pixels:</span>%li<br/>", fish->fish.pixels); } fprintf (output_file, "</div>"); fprintf (output_file, "</a></td>\n"); break; default: babl_fatal ("Unknown fish type"); break; } } return 0; }
static int table_source_each (Babl *babl, void *userdata) { char expanded_name[512]; const char *s; char *d; s = babl->instance.name; d = &expanded_name[0]; while (*s) { switch (*s) { case ' ': *(d++) = '&'; *(d++) = 'n'; *(d++) = 'b'; *(d++) = 's'; *(d++) = 'p'; *(d++) = ';'; *(d) = '\0'; s++; break; default: *(d++) = *(s++); *(d) = '\0'; break; } } fprintf (output_file, "<tr>"); fprintf (output_file, "<td class='format_name'><a href='javascript:o();'>%s", expanded_name); { int i; fprintf (output_file, "<div class='tooltip' id='format_%p'>", babl); fprintf (output_file, "<h3>%s</h3>", babl->instance.name); fprintf (output_file, "<dl>"); fprintf (output_file, "<dt>bytes/pixel</dt><dd>%i</dd>", babl->format.bytes_per_pixel); fprintf (output_file, "<dt>model</dt><dd>%s</dd>", BABL (babl->format.model)->instance.name); fprintf (output_file, "<dt>loss</dt><dd>%f</dd>", babl_format_loss (babl)); fprintf (output_file, "<dt>planar</dt><dd>%d</dd>", babl->format.planar); fprintf (output_file, "<dt>components</dt><dd><table class='nopad'>"); for (i = 0; i < babl->format.components; i++) { fprintf (output_file, "<tr><td class='type'>%s</td><td class='component'>%s</td></tr>", BABL (babl->format.type[i])->instance.name, BABL (babl->format.component[i])->instance.name); } fprintf (output_file, "</table></dd></dl>"); fprintf (output_file, "</div>\n"); } fprintf (output_file, "</a></td>"); babl_format_class_for_each (table_destination_each, babl); fprintf (output_file, "</tr>\n"); source_no++; return 0; }
static long process_conversion_path (BablList *path, const void *source_buffer, int source_bpp, void *destination_buffer, int dest_bpp, long n) { int conversions = babl_list_size (path); if (conversions == 1) { babl_conversion_process (BABL (babl_list_get_first (path)), source_buffer, destination_buffer, n); } else { long j; void *temp_buffer = align_16 (alloca (MIN(n, MAX_BUFFER_SIZE) * sizeof (double) * 5 + 16)); void *temp_buffer2 = NULL; if (conversions > 2) { /* We'll need one more auxiliary buffer */ temp_buffer2 = align_16 (alloca (MIN(n, MAX_BUFFER_SIZE) * sizeof (double) * 5 + 16)); } for (j = 0; j < n; j+= MAX_BUFFER_SIZE) { long c = MIN (n - j, MAX_BUFFER_SIZE); int i; /* this is where the loop unrolling should happen */ void *aux1_buffer = temp_buffer; void *aux2_buffer = NULL; void *swap_buffer = NULL; aux2_buffer = temp_buffer2; /* The first conversion goes from source_buffer to aux1_buffer */ babl_conversion_process (babl_list_get_first (path), (void*)(((unsigned char*)source_buffer) + (j * source_bpp)), aux1_buffer, c); /* Process, if any, conversions between the first and the last * conversion in the path, in a loop */ for (i = 1; i < conversions - 1; i++) { babl_conversion_process (path->items[i], aux1_buffer, aux2_buffer, c); /* Swap the auxiliary buffers */ swap_buffer = aux1_buffer; aux1_buffer = aux2_buffer; aux2_buffer = swap_buffer; } /* The last conversion goes from aux1_buffer to destination_buffer */ babl_conversion_process (babl_list_get_last (path), aux1_buffer, (void*)((unsigned char*)destination_buffer + (j * dest_bpp)), c); } } return n; }
static void get_conversion_path (PathContext *pc, Babl *current_format, int current_length, int max_length) { if (current_length > max_length) { /* We have reached the maximum recursion * depth, let's bail out */ return; } else if ((current_length > 0) && (current_format == pc->to_format)) { /* We have found a candidate path, let's * see about it's properties */ double path_cost = 0.0; double ref_cost = 0.0; double path_error = 1.0; int i; for (i = 0; i < babl_list_size (pc->current_path); i++) { path_error *= (1.0 + babl_conversion_error ((BablConversion *) pc->current_path->items[i])); } if (path_error - 1.0 <= legal_error ()) /* check this before the next; which does a more accurate measurement of the error */ { FishPathInstrumentation fpi; memset (&fpi, 0, sizeof (fpi)); fpi.source = (Babl*) babl_list_get_first (pc->current_path)->conversion.source; fpi.destination = pc->to_format; get_path_instrumentation (&fpi, pc->current_path, &path_cost, &ref_cost, &path_error); if ((path_cost < ref_cost) && /* do not use paths that took longer to compute than reference */ (path_cost < pc->fish_path->fish_path.cost) && (path_error <= legal_error ())) { /* We have found the best path so far, * let's copy it into our new fish */ pc->fish_path->fish_path.cost = path_cost; pc->fish_path->fish.error = path_error; babl_list_copy (pc->current_path, pc->fish_path->fish_path.conversion_list); } destroy_path_instrumentation (&fpi); } } else { /* * Bummer, we have to search deeper... */ BablList *list; int i; list = current_format->format.from_list; if (list) { /* Mark the current format in conversion path as visited */ current_format->format.visited = 1; /* Iterate through unvisited formats from the current format ...*/ for (i = 0; i < babl_list_size (list); i++) { Babl *next_conversion = BABL (list->items[i]); Babl *next_format = BABL (next_conversion->conversion.destination); if (!next_format->format.visited) { /* next_format is not in the current path, we can pay a visit */ babl_list_insert_last (pc->current_path, next_conversion); get_conversion_path (pc, next_format, current_length + 1, max_length); babl_list_remove_last (pc->current_path); } } /* Remove the current format from current path */ current_format->format.visited = 0; } } }