void image_add_thumbnail_frame(GdkPixbuf *img) { guint32 outline = IMAGEFU_COLOR(0xFF, 0x55, 0x55, 0x55); guint32 transparent = IMAGEFU_COLOR(0x00, 0xFF, 0xFF, 0xFF); guint32 shadow = IMAGEFU_COLOR(0x22, 0x00, 0x00, 0x00); int width = gdk_pixbuf_get_width(img); int height = gdk_pixbuf_get_height(img); if (width <= 2) return; if (height <= 2) return; image_draw_rect_outline(img, 0, 0, width, height, transparent); image_draw_rect_outline(img, 1, 1, width-2, height-2, outline); image_draw_hline(img, 2, height-1, width-2, shadow); image_draw_vline(img, width-1, 2, height-2, shadow); }
static void histogram_imager_generate_color_table (HistogramImager *self, gboolean force) { /* Regenerate the contents of the color mapping table, a mapping from all * possible histogram values to the corresponding ARGB color, in the current image. */ guint count; float pixel_scale = histogram_imager_get_pixel_scale (self); gulong usable_density = histogram_imager_get_max_usable_density (self); float luma; double one_over_gamma = 1/self->gamma; float distance = 0; gulong color_table_size; struct { int r, g, b, a; } current, previous; /* Our actual color table size should be either the maximum * usable density, or our histogram's current peak density, * whichever is smaller. */ if (usable_density > self->peak_density) usable_density = self->peak_density; /* If the table is already the right size and we aren't being * forced to regenerate it, stop now. */ color_table_size = usable_density + 1; if ((!force) && self->color_table.filled_size == color_table_size) return; /* Make sure our table is appropriately sized */ histogram_imager_resize_color_table (self, color_table_size); /* Generate one color for every currently-possible count value that * doesn't fully saturate our image, as determined by histogram_imager_get_max_usable_density */ for (count=0; count < self->color_table.filled_size; count++) { /* Scale and gamma-correct */ luma = count * pixel_scale; luma = pow(luma, one_over_gamma); /* Optionally clamp before interpolating */ if (self->clamped && luma > 1) luma = 1; /* Linearly interpolate between fgcolor and bgcolor */ current.r = ((int)(self->bgcolor.red * (1-luma) + self->fgcolor.red * luma)) >> 8; current.g = ((int)(self->bgcolor.green * (1-luma) + self->fgcolor.green * luma)) >> 8; current.b = ((int)(self->bgcolor.blue * (1-luma) + self->fgcolor.blue * luma)) >> 8; current.a = ((int)(self->bgalpha * (1-luma) + self->fgalpha * luma)) >> 8; /* Always clamp color components */ if (current.r<0) current.r = 0; if (current.r>255) current.r = 255; if (current.g<0) current.g = 0; if (current.g>255) current.g = 255; if (current.b<0) current.b = 0; if (current.b>255) current.b = 255; if (current.a<0) current.a = 0; if (current.a>255) current.a = 255; /* Colors are always ARGB order in little endian */ self->color_table.table[count] = IMAGEFU_COLOR(current.a, current.r, current.g, current.b); /* Update our elapsed distance */ if (count > 0) { distance += sqrt( (current.r - previous.r) * (current.r - previous.r) + (current.g - previous.g) * (current.g - previous.g) + (current.b - previous.b) * (current.b - previous.b) + (current.a - previous.a) * (current.a - previous.a) ); } previous = current; /* "distance" is the distance we've traveled from the background to this * point in the color hypercube. Our quality metric is based on the number * of histogram samples per color cube samples: our 'quality' table stores * the current count divided by its corresponding distance. */ if (distance > 0) { self->color_table.quality[count] = count / distance; } else { /* We shouldn't ever use quality entries where the distance * is zero- this value is pretty arbitrary. */ self->color_table.quality[count] = 0; } } }