mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Handle grayscale images as expected
Signed-off-by: obskyr <powpowd@gmail.com>
This commit is contained in:
@@ -18,7 +18,7 @@ static struct RawIndexedImage *indexed_png_to_raw(struct PNGImage *img);
|
|||||||
static struct RawIndexedImage *grayscale_png_to_raw(struct PNGImage *img);
|
static struct RawIndexedImage *grayscale_png_to_raw(struct PNGImage *img);
|
||||||
static struct RawIndexedImage *truecolor_png_to_raw(struct PNGImage *img);
|
static struct RawIndexedImage *truecolor_png_to_raw(struct PNGImage *img);
|
||||||
static void get_text(const struct PNGImage *img,
|
static void get_text(const struct PNGImage *img,
|
||||||
struct ImageOptions* png_options);
|
struct ImageOptions *png_options);
|
||||||
static void set_text(const struct PNGImage *img,
|
static void set_text(const struct PNGImage *img,
|
||||||
const struct ImageOptions *png_options);
|
const struct ImageOptions *png_options);
|
||||||
static void free_png_data(const struct PNGImage *png);
|
static void free_png_data(const struct PNGImage *png);
|
||||||
@@ -333,18 +333,8 @@ static void rgba_PLTE_palette(struct PNGImage *img,
|
|||||||
PNG_USER_WILL_FREE_DATA, PNG_FREE_PLTE);
|
PNG_USER_WILL_FREE_DATA, PNG_FREE_PLTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A combined struct is needed to sort colors in order of luminance. */
|
static int fit_grayscale_palette(png_color *palette, int *num_colors);
|
||||||
struct ColorWithLuminance {
|
static void order_color_palette(png_color *palette, int num_colors);
|
||||||
png_color color;
|
|
||||||
int luminance;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int compare_luminance(const void *a,const void *b)
|
|
||||||
{
|
|
||||||
struct ColorWithLuminance *x = (struct ColorWithLuminance *) a;
|
|
||||||
struct ColorWithLuminance *y = (struct ColorWithLuminance *) b;
|
|
||||||
return y->luminance - x->luminance;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rgba_build_palette(struct PNGImage *img,
|
static void rgba_build_palette(struct PNGImage *img,
|
||||||
png_color **palette_ptr_ptr, int *num_colors)
|
png_color **palette_ptr_ptr, int *num_colors)
|
||||||
@@ -353,9 +343,9 @@ static void rgba_build_palette(struct PNGImage *img,
|
|||||||
int y, value_index, i;
|
int y, value_index, i;
|
||||||
png_color cur_pixel_color;
|
png_color cur_pixel_color;
|
||||||
png_byte cur_alpha;
|
png_byte cur_alpha;
|
||||||
|
bool only_grayscale = true;
|
||||||
bool color_exists;
|
bool color_exists;
|
||||||
png_color cur_palette_color;
|
png_color cur_palette_color;
|
||||||
struct ColorWithLuminance *palette_with_luminance;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* By filling the palette up with black by default, if the image
|
* By filling the palette up with black by default, if the image
|
||||||
@@ -381,6 +371,12 @@ static void rgba_build_palette(struct PNGImage *img,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (only_grayscale &&
|
||||||
|
!(cur_pixel_color.red == cur_pixel_color.green &&
|
||||||
|
cur_pixel_color.red == cur_pixel_color.blue)) {
|
||||||
|
only_grayscale = false;
|
||||||
|
}
|
||||||
|
|
||||||
color_exists = false;
|
color_exists = false;
|
||||||
for (i = 0; i < *num_colors; i++) {
|
for (i = 0; i < *num_colors; i++) {
|
||||||
cur_palette_color = palette[i];
|
cur_palette_color = palette[i];
|
||||||
@@ -402,9 +398,79 @@ static void rgba_build_palette(struct PNGImage *img,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
palette_with_luminance =
|
/* In order not to count 100% transparent images as grayscale. */
|
||||||
malloc(sizeof(struct ColorWithLuminance) * colors);
|
only_grayscale = *num_colors ? only_grayscale : false;
|
||||||
|
|
||||||
|
if (!only_grayscale || !fit_grayscale_palette(palette, num_colors)) {
|
||||||
|
order_color_palette(palette, *num_colors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fit_grayscale_palette(png_color *palette, int *num_colors)
|
||||||
|
{
|
||||||
|
int i, shade_index;
|
||||||
|
int interval = 256 / colors;
|
||||||
|
png_color *fitted_palette = malloc(sizeof(png_color) * colors);
|
||||||
|
bool *set_indices = calloc(colors, sizeof(bool));
|
||||||
|
|
||||||
|
fitted_palette[0].red = 0xFF;
|
||||||
|
fitted_palette[0].green = 0xFF;
|
||||||
|
fitted_palette[0].blue = 0xFF;
|
||||||
|
fitted_palette[colors - 1].red = 0;
|
||||||
|
fitted_palette[colors - 1].green = 0;
|
||||||
|
fitted_palette[colors - 1].blue = 0;
|
||||||
|
if (colors == 4) {
|
||||||
|
fitted_palette[1].red = 0xA9;
|
||||||
|
fitted_palette[1].green = 0xA9;
|
||||||
|
fitted_palette[1].blue = 0xA9;
|
||||||
|
fitted_palette[2].red = 0x55;
|
||||||
|
fitted_palette[2].green = 0x55;
|
||||||
|
fitted_palette[2].blue = 0x55;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < *num_colors; i++) {
|
||||||
|
shade_index = colors - 1 - palette[i].red / interval;
|
||||||
|
if (set_indices[shade_index]) {
|
||||||
|
free(fitted_palette);
|
||||||
|
free(set_indices);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fitted_palette[shade_index] = palette[i];
|
||||||
|
set_indices[shade_index] = true;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < colors; i++) {
|
for (i = 0; i < colors; i++) {
|
||||||
|
palette[i] = fitted_palette[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
*num_colors = colors;
|
||||||
|
|
||||||
|
free(fitted_palette);
|
||||||
|
free(set_indices);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A combined struct is needed to sort csolors in order of luminance. */
|
||||||
|
struct ColorWithLuminance {
|
||||||
|
png_color color;
|
||||||
|
int luminance;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int compare_luminance(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
struct ColorWithLuminance *x = (struct ColorWithLuminance *) a;
|
||||||
|
struct ColorWithLuminance *y = (struct ColorWithLuminance *) b;
|
||||||
|
return y->luminance - x->luminance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void order_color_palette(png_color *palette, int num_colors)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct ColorWithLuminance *palette_with_luminance;
|
||||||
|
|
||||||
|
palette_with_luminance =
|
||||||
|
malloc(sizeof(struct ColorWithLuminance) * num_colors);
|
||||||
|
for (i = 0; i < num_colors; i++) {
|
||||||
/*
|
/*
|
||||||
* Normally this would be done with floats, but since it's only
|
* Normally this would be done with floats, but since it's only
|
||||||
* used for comparison, we might as well use integer math.
|
* used for comparison, we might as well use integer math.
|
||||||
@@ -414,9 +480,9 @@ static void rgba_build_palette(struct PNGImage *img,
|
|||||||
7152 * palette[i].green +
|
7152 * palette[i].green +
|
||||||
722 * palette[i].blue;
|
722 * palette[i].blue;
|
||||||
}
|
}
|
||||||
qsort(palette_with_luminance, colors,
|
qsort(palette_with_luminance, num_colors,
|
||||||
sizeof(struct ColorWithLuminance), compare_luminance);
|
sizeof(struct ColorWithLuminance), compare_luminance);
|
||||||
for (i = 0; i < colors; i++) {
|
for (i = 0; i < num_colors; i++) {
|
||||||
palette[i] = palette_with_luminance[i].color;
|
palette[i] = palette_with_luminance[i].color;
|
||||||
}
|
}
|
||||||
free(palette_with_luminance);
|
free(palette_with_luminance);
|
||||||
@@ -538,7 +604,7 @@ static void set_raw_image_palette(struct RawIndexedImage *raw_image,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void get_text(const struct PNGImage *img,
|
static void get_text(const struct PNGImage *img,
|
||||||
struct ImageOptions* png_options)
|
struct ImageOptions *png_options)
|
||||||
{
|
{
|
||||||
png_text *text;
|
png_text *text;
|
||||||
int i, numtxts, numremoved;
|
int i, numtxts, numremoved;
|
||||||
|
|||||||
Reference in New Issue
Block a user