void babl_palette_set_palette (const Babl *babl, const Babl *format, void *data, int count) { BablPalette **palptr = babl_get_user_data (babl); babl_palette_reset (babl); if (count > 256) { babl_log ("attempt to create a palette with %d colors. " "truncating to 256 colors.", count); count = 256; } if (count > 0) { *palptr = make_pal (babl_format_get_space (babl), format, data, count); } else { babl_log ("attempt to create a palette with %d colors. " "using default palette instead.", count); } }
static void sampling_introspect (Babl *babl) { babl_log ("\t\thorizontal = %i", babl->sampling.horizontal); babl_log ("\t\tvertical = %i", babl->sampling.vertical); }
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)); } }
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 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 test (void) { int components; int OK = 1; for (components = 1; components < 2048; components ++) { const Babl *fish; const Babl *src_fmt; const Babl *dst_fmt; int i; src_fmt = babl_format_n (babl_type ("float"), components); dst_fmt = babl_format_n (babl_type ("u8"), components); fish = babl_fish (src_fmt, dst_fmt); babl_process (fish, source_buf, destination_buf, PIXELS); for (i = 0; i < PIXELS * components; i++) { if (abs (destination_buf[i] - reference_buf[i]) > TOLERANCE) { babl_log ("%i-components, pixel %i component %i is %i should be %i", components, i / components, i % components, destination_buf[i], reference_buf[i]); OK = 0; } } } if (!OK) return -1; return 0; }
static void fish_path_introspect (Babl *babl) { babl_log ("\t\tcost:%f error:%.12f", babl->fish_path.cost, babl->fish.error); babl_list_each(babl->fish_path.conversion_list, each_introspect, NULL); }
static void format_introspect (Babl *babl) { int i; babl_log ("\t\tmodel=\"%s\"", babl->format.model->instance.name); babl_log ("\t\tplanar=%i", babl->format.planar); babl_log ("\t\tcomponents=%i", babl->format.components); for (i = 0; i < babl->format.components; i++) { babl_log ("\t\tband[%i] type=\"%s\" sampling=\"%s\" component=\"%s\"", i, babl->format.type[i]->instance.name, babl->format.sampling[i]->instance.name, babl->format.component[i]->instance.name); } }
static long babl_fish_path_process (Babl *babl, const void *source, void *destination, long n) { const Babl *babl_source = babl->fish.source; const Babl *babl_dest = babl->fish.destination; int source_bpp = 0; int dest_bpp = 0; switch (babl_source->instance.class_type) { case BABL_FORMAT: source_bpp = babl_source->format.bytes_per_pixel; break; case BABL_TYPE: source_bpp = babl_source->type.bits / 8; break; default: babl_log ("=eeek{%i}\n", babl_source->instance.class_type - BABL_MAGIC); } switch (babl_dest->instance.class_type) { case BABL_FORMAT: dest_bpp = babl_dest->format.bytes_per_pixel; break; case BABL_TYPE: dest_bpp = babl_dest->type.bits / 8; break; default: babl_log ("-eeek{%i}\n", babl_dest->instance.class_type - BABL_MAGIC); } return process_conversion_path (babl->fish_path.conversion_list, source, source_bpp, destination, dest_bpp, n); }
static int each_introspect (Babl *babl, void *user_data) { babl_log ("\t\"%s\"\t%i\t%s", babl->instance.name, babl->instance.id, babl_class_name (babl->class_type)); switch (babl->class_type) { case BABL_TYPE: type_introspect (babl); item_conversions_introspect (babl); break; case BABL_COMPONENT: break; case BABL_MODEL: model_introspect (babl); item_conversions_introspect (babl); break; case BABL_FORMAT: format_introspect (babl); item_conversions_introspect (babl); break; case BABL_SAMPLING: sampling_introspect (babl); item_conversions_introspect (babl); break; case BABL_CONVERSION: case BABL_CONVERSION_PLANE: case BABL_CONVERSION_PLANAR: case BABL_CONVERSION_LINEAR: conversion_introspect (babl); break; case BABL_FISH: case BABL_FISH_REFERENCE: case BABL_FISH_SIMPLE: fish_introspect (babl); break; case BABL_FISH_PATH: fish_path_introspect (babl); break; default: break; } return 0; }
static int test (void) { int i = 0; int OK = 1; while (reference[i].klass) { if (strcmp (reference[i].name, babl_class_name (reference[i].klass))) { OK = 0; babl_log ("'%s'!='%s'\n", reference[i].name, babl_class_name (reference[i].klass)); } i++; } return !OK; }
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 int test (void) { const Babl *fish; int i; int OK = 1; fish = babl_fish ( babl_format_new ( babl_model ("Y"), babl_type ("float"), babl_component ("Y"), NULL ), babl_format_new ( babl_model ("RGB"), babl_type ("float"), babl_component ("R"), babl_component ("G"), babl_component ("B"), NULL ) ); babl_process (fish, grayscale_buf, rgb_buf, PIXELS); for (i = 0; i < PIXELS * 3; i++) { if (rgb_buf[i] != rgb_buf_ref[i]) { babl_log ("index %i is problematic : %f instead of %f", i, rgb_buf[i], rgb_buf_ref[i]); OK = 0; } } if (!OK) return -1; return 0; }
static int test (void) { const Babl *fish; int i; int OK = 1; fish = babl_fish ( babl_format_new ( babl_model ("RGB"), babl_type ("u8"), babl_component ("R"), babl_component ("G"), babl_component ("B"), NULL ), babl_format_new ( babl_model ("RGB"), babl_type ("u8"), babl_component ("B"), babl_component ("G"), babl_component ("R"), NULL ) ); babl_process (fish, source_buf, destination_buf, PIXELS); for (i = 0; i < PIXELS * 3; i++) { if (abs (destination_buf[i] - reference_buf[i]) > TOLERANCE) { babl_log ("%2i (%2i%%3=%i, %2i/3=%i) is %i should be %i", i, i, i % 3, i, i / 3, destination_buf[i], reference_buf[i]); OK = 0; } } if (!OK) return -1; return 0; }
const Babl * babl_type_new (void *first_arg, ...) { va_list varg; Babl *babl; int id = 0; int is_integer = 0; int bits = 0; long min = 0; long max = 255; double min_val = 0.0; double max_val = 0.0; const char *name = first_arg; const char *arg; va_start (varg, first_arg); while (1) { arg = va_arg (varg, char *); if (!arg) break; if (BABL_IS_BABL (arg)) { #ifdef BABL_LOG Babl *babl = (Babl *) arg; babl_log ("%s unexpected", babl_class_name (babl->class_type)); #endif } /* if we didn't point to a babl, we assume arguments to be strings */ else if (!strcmp (arg, "id")) { id = va_arg (varg, int); } else if (!strcmp (arg, "bits"))
static int test (void) { int i; int OK = 1; babl_process (babl_fish (babl_format_with_space ("R'G'B' u8", babl_space("Apple")), "R'G'B' u8"), source_buf, destination_buf, PIXELS); for (i = 0; i < PIXELS * 3; i++) { if (abs (destination_buf[i] - reference_buf[i]) > TOLERANCE) { babl_log ("%2i (%2i%%3=%i, %2i/3=%i) is %i should be %i", i, i, i % 3, i, i / 3, destination_buf[i], reference_buf[i]); OK = 0; } } if (!OK) return -1; return 0; }
void babl_introspect (Babl *babl) { #ifdef BABL_LOG Babl *extender_backup = babl_extender (); babl_set_extender (babl_extension_quiet_log ()); if (babl) { each_introspect (babl, NULL); return; } babl_log ("Introspection report"); babl_log ("===================================================="); babl_log (""); babl_log ("Data Types:"); babl_type_class_for_each (each_introspect, NULL); babl_log (""); babl_log ("Sampling (chroma subsampling) factors:"); babl_sampling_class_for_each (each_introspect, NULL); babl_log (""); babl_log ("Components:"); babl_component_class_for_each (each_introspect, NULL); babl_log (""); babl_log ("Models (of components):"); babl_model_class_for_each (each_introspect, NULL); babl_log (""); babl_log ("Pixel formats:"); babl_format_class_for_each (each_introspect, NULL); babl_log (""); babl_log ("conversions:"); babl_conversion_class_for_each (each_introspect, NULL); babl_log (""); babl_log ("extensions:"); babl_extension_class_for_each (each_introspect, NULL); babl_log (""); babl_log ("fishes"); babl_fish_class_for_each (each_introspect, NULL); babl_log (""); babl_set_extender (extender_backup); #endif }
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 void get_path_instrumentation (FishPathInstrumentation *fpi, BablList *path, double *path_cost, double *ref_cost, double *path_error) { long ticks_start = 0; long ticks_end = 0; Babl *babl_source = fpi->source; Babl *babl_destination = fpi->destination; int source_bpp = 0; int dest_bpp = 0; switch (babl_source->instance.class_type) { case BABL_FORMAT: source_bpp = babl_source->format.bytes_per_pixel; break; case BABL_TYPE: source_bpp = babl_source->type.bits / 8; break; default: babl_log ("=eeek{%i}\n", babl_source->instance.class_type - BABL_MAGIC); } switch (babl_destination->instance.class_type) { case BABL_FORMAT: dest_bpp = babl_destination->format.bytes_per_pixel; break; case BABL_TYPE: dest_bpp = babl_destination->type.bits / 8; break; default: babl_log ("-eeek{%i}\n", babl_destination->instance.class_type - BABL_MAGIC); } if (!fpi->init_instrumentation_done) { /* this initialization can be done only once since the * source and destination formats do not change during * the search */ init_path_instrumentation (fpi, babl_source, babl_destination); fpi->init_instrumentation_done = 1; } /* calculate this path's view of what the result should be */ ticks_start = babl_ticks (); process_conversion_path (path, fpi->source, source_bpp, fpi->destination, dest_bpp, NUM_TEST_PIXELS); ticks_end = babl_ticks (); *path_cost = babl_process_cost (ticks_start, ticks_end); /* transform the reference and the actual destination buffers to RGBA * for comparison with each other */ babl_process (fpi->fish_destination_to_rgba, fpi->destination, fpi->destination_rgba_double, NUM_TEST_PIXELS); *path_error = babl_rel_avg_error (fpi->destination_rgba_double, fpi->ref_destination_rgba_double, NUM_TEST_PIXELS * 4); #if 0 fpi->fish_rgba_to_source->fish.processings--; fpi->fish_reference->fish.processings--; fpi->fish_destination_to_rgba->fish.processings -= 2; fpi->fish_rgba_to_source->fish.pixels -= NUM_TEST_PIXELS; fpi->fish_reference->fish.pixels -= NUM_TEST_PIXELS; fpi->fish_destination_to_rgba->fish.pixels -= 2 * NUM_TEST_PIXELS; #endif *ref_cost = fpi->reference_cost; }
static void fish_introspect (Babl *babl) { babl_log ("\t\tprocessings:%i pixels:%li", babl->fish.processings, babl->fish.pixels); }
static void type_introspect (Babl *babl) { babl_log ("\t\tbits=%i", babl->type.bits); }