long babl_process (const Babl *cbabl, const void *source, void *destination, long n) { Babl *babl = (Babl*)cbabl; babl_assert (babl); babl_assert (source); babl_assert (destination); babl_assert (BABL_IS_BABL (babl)); if (n == 0) return 0; babl_assert (n > 0); /* first check if it is a fish since that is our fast path */ if (babl->class_type >= BABL_FISH && babl->class_type <= BABL_FISH_PATH) { babl->fish.processings++; babl->fish.pixels += babl_fish_process (babl, source, destination, n); return n; } /* matches all conversion classes */ if (babl->class_type >= BABL_CONVERSION && babl->class_type <= BABL_CONVERSION_PLANAR) return babl_conversion_process (babl, source, destination, n); babl_fatal ("eek"); return -1; }
static BablPalette * make_pal (const Babl *pal_space, const Babl *format, const void *data, int count) { BablPalette *pal = NULL; int bpp = babl_format_get_bytes_per_pixel (format); babl_assert (count > 0); pal = babl_malloc (sizeof (BablPalette)); pal->count = count; pal->format = format; pal->data = babl_malloc (bpp * count); pal->data_double = babl_malloc (4 * sizeof(double) * count); pal->data_u8 = babl_malloc (4 * sizeof(char) * count); pal->radii = babl_malloc (sizeof (BablPaletteRadius) * (pal->count - 1) * pal->count); memcpy (pal->data, data, bpp * count); babl_process (babl_fish (format, babl_format_with_space ("RGBA double", pal_space)), data, pal->data_double, count); babl_process (babl_fish (format, babl_format_with_space ("R'G'B'A u8", pal_space)), data, pal->data_u8, count); babl_palette_init_radii (pal); babl_palette_reset_hash (pal); return pal; }
static Babl * type_new (const char *name, int id, int bits) { Babl *babl; babl_assert (bits != 0); babl_assert (bits % 8 == 0); babl = babl_malloc (sizeof (BablType) + strlen (name) + 1); babl_set_destructor (babl, babl_type_destroy); babl->instance.name = (void *) ((char *) babl + sizeof (BablType)); babl->class_type = BABL_TYPE; babl->instance.id = id; strcpy (babl->instance.name, name); babl->type.bits = bits; babl->type.from_list = NULL; return babl; }
static int table_destination_sum_each (Babl *babl, void *userdata) { const Babl *source = userdata; const Babl *destination = babl; if (source != destination) { const Babl *fish = babl_fish (source, destination); babl_assert (fish); sum_pixels += fish->fish.pixels; } return 0; }
const Babl * babl_fish (const void *source, const void *destination) { const Babl *source_format = NULL; const Babl *destination_format = NULL; babl_assert (source); babl_assert (destination); if (BABL_IS_BABL (source)) source_format = source; if (!source_format) source_format = babl_format ((char *) source); if (!source_format) { babl_log ("args=(%p, %p) source format invalid", source, destination); return NULL; } if (BABL_IS_BABL (destination)) destination_format = destination; if (!destination_format) destination_format = babl_format ((char *) destination); if (!destination_format) { babl_log ("args=(%p, %p) destination format invalid", source, destination); return NULL; } { int hashval; BablHashTable *id_htable; BablFindFish ffish = {(Babl *) NULL, (Babl *) NULL, (Babl *) NULL, 0, (Babl *) NULL, (Babl *) NULL}; /* some vendor compilers can't compile non-constant elements of * compound struct initializers */ ffish.source = source_format; ffish.destination = destination_format; id_htable = (babl_fish_db ())->id_hash; hashval = babl_hash_by_int (id_htable, babl_fish_get_id (source_format, destination_format)); if (source_format == destination_format) { /* In the case of equal source and destination formats * we will search through the fish database for reference fish * to handle the memcpy */ babl_hash_table_find (id_htable, hashval, find_memcpy_fish, (void *) &ffish); } else { /* In the case of different source and destination formats * we will search through the fish database for appropriate fish path * to handle the conversion. In the case that preexistent * fish path is found, we'll return it. In the case BABL_FISH * instance with the same source/destination is found, we'll * return reference fish. * In the case neither fish path nor BABL_FISH path are found, * we'll try to construct new fish path for requested * source/destination. In the case new fish path is found, we'll * return it, otherwise we'll create dummy BABL_FISH instance and * insert it into the fish database to indicate non-existent fish * path. */ babl_hash_table_find (id_htable, hashval, find_fish_path, (void *) &ffish); if (ffish.fish_path) { /* we have found suitable fish path in the database */ return ffish.fish_path; } if (!ffish.fish_fish) { /* we haven't tried to search for suitable path yet */ Babl *fish_path = babl_fish_path (source_format, destination_format); if (fish_path) { return fish_path; } else { /* there isn't a suitable path for requested formats, * let's create a dummy BABL_FISH instance and insert * it into the fish database to indicate that such path * does not exist. */ char *name = "X"; /* name does not matter */ Babl *fish = babl_calloc (1, sizeof (BablFish) + strlen (name) + 1); fish->class_type = BABL_FISH; fish->instance.id = babl_fish_get_id (source_format, destination_format); fish->instance.name = ((char *) fish) + sizeof (BablFish); strcpy (fish->instance.name, name); fish->fish.source = source_format; fish->fish.destination = destination_format; babl_db_insert (babl_fish_db (), fish); } } } if (ffish.fish_ref) { /* we have already found suitable reference fish */ return ffish.fish_ref; } else { /* we have to create new reference fish */ return babl_fish_reference (source_format, destination_format); } } }
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; }