diff options
author | Keith Packard <keithp@keithp.com> | 2014-01-04 00:35:57 -0800 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2014-01-04 00:35:57 -0800 |
commit | f76a454566bd94c8bb5d8def93ba6bf79fe89a68 (patch) | |
tree | 3238f3fd4ca013f61a17a39f576fa0d7132cdef1 | |
parent | cb8f6b3c2200f651a4e005ecbd25e5bf6fa01139 (diff) |
Autoconf. Common colors
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | Makefile.am | 36 | ||||
-rw-r--r-- | configure.ac | 41 | ||||
-rw-r--r-- | xtsttopng.c | 613 |
4 files changed, 375 insertions, 320 deletions
diff --git a/Makefile b/Makefile deleted file mode 100644 index d4b08e2..0000000 --- a/Makefile +++ /dev/null @@ -1,5 +0,0 @@ - -CFLAGS=-O0 -g - -xtsttopng: xtsttopng.c - $(CC) $(CFLAGS) -o $@ xtsttopng.c -lpng -lm
\ No newline at end of file diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..810442c --- /dev/null +++ b/Makefile.am @@ -0,0 +1,36 @@ +# +# Copyright © 2014 Keith Packard <keithp@keithp.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +# + +bin_PROGRAMS = xtsttopng + +AM_CFLAGS = $(XTSTTOPNG_CFLAGS) $(CWARNFLAGS) +xtsttopng_LDADD = $(XTSTTOPNG_LIBS) + +xtsttopng_SOURCES = \ + xtsttopng.c + +MAINTAINERCLEANFILES = ChangeLog INSTALL + +.PHONY: ChangeLog INSTALL + +INSTALL: + $(INSTALL_CMD) + +ChangeLog: + $(CHANGELOG_CMD) + +dist-hook: ChangeLog INSTALL diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..ac166f8 --- /dev/null +++ b/configure.ac @@ -0,0 +1,41 @@ +# +# Copyright © 2014 Keith Packard <keithp@keithp.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +#/ + +# Initialize Autoconf +AC_PREREQ([2.60]) +AC_INIT([xtsttopng], [1.0], + [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [xtsttopng]) +AC_CONFIG_SRCDIR([Makefile.am]) +AC_CONFIG_HEADERS([config.h]) + +# Initialize Automake +AM_INIT_AUTOMAKE([foreign dist-bzip2]) + +# Require X.Org macros 1.8 or later for MAN_SUBSTS set by XORG_MANPAGE_SECTIONS +m4_ifndef([XORG_MACROS_VERSION], + [m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen])]) +XORG_MACROS_VERSION(1.8) +XORG_DEFAULT_OPTIONS + +AC_CHECK_LIB(m,floor) + +AC_CHECK_LIB(png,png_create_write_struct) + +AC_CONFIG_FILES([ + Makefile + ]) +AC_OUTPUT diff --git a/xtsttopng.c b/xtsttopng.c index f0c7fa6..0b32459 100644 --- a/xtsttopng.c +++ b/xtsttopng.c @@ -15,6 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <stdint.h> @@ -27,235 +28,228 @@ #define MAX_LEVEL 32 struct xts_color { - uint32_t pixel; - uint16_t r, g, b; - uint16_t level; - struct xts_color *next[0]; + uint32_t pixel; + uint16_t r, g, b; + uint16_t level; + struct xts_color *next[0]; }; +struct xts_color *colors[MAX_LEVEL]; +int num_colors; + static uint16_t random_level (void) { - /* tricky bit -- each bit is '1' 75% of the time */ - long int bits = random () | random (); - uint16_t level = 0; - - while (++level < MAX_LEVEL) - { - if (bits & 1) - break; - bits >>= 1; - } - return level; + /* tricky bit -- each bit is '1' 75% of the time */ + long int bits = random () | random (); + uint16_t level = 0; + + while (++level < MAX_LEVEL) + { + if (bits & 1) + break; + bits >>= 1; + } + return level; } -struct xts_color *alloc_color (void) { - uint16_t level = random_level(); +static struct xts_color * +alloc_color (void) { + uint16_t level = random_level(); - struct xts_color *c = calloc(1, sizeof (struct xts_color) + level * sizeof (struct xts_color *)); - if (!c) - return NULL; - c->level = level; - return c; + struct xts_color *c = calloc(1, sizeof (struct xts_color) + level * sizeof (struct xts_color *)); + if (!c) + return NULL; + c->level = level; + return c; } -uint16_t +static uint16_t float_to_uint(float x) { - return floor (x * 255.0); + return floor (x * 255.0); } -void assign_hsv(struct xts_color *color, float h, float s, float v) +static void +assign_hsv(struct xts_color *color, float h, float s, float v) { - uint16_t r, g, b; - if (v == 0) { - r = g = b = 0; - } else if (s == 0) { - r = g = b = float_to_uint(s); - } else { - float h6 = h * 6; - while (h6 >= 6) - h6 -= 6; - int i = floor (h6); - float f = h6 - i; - float p = v * (1 - s); - float q = v * (1 - (s * f)); - float t = v * (1 - (s * (1 - f))); - - switch (i) { - case 0: - r = float_to_uint(v); - g = float_to_uint(t); - b = float_to_uint(p); - break; - case 1: - r = float_to_uint(q); - g = float_to_uint(v); - b = float_to_uint(p); - break; - case 2: - r = float_to_uint(p); - g = float_to_uint(v); - b = float_to_uint(t); - break; - case 3: - r = float_to_uint(p); - g = float_to_uint(q); - b = float_to_uint(v); - break; - case 4: - r = float_to_uint(t); - g = float_to_uint(p); - b = float_to_uint(v); - break; - case 5: - r = float_to_uint(v); - g = float_to_uint(p); - b = float_to_uint(q); - break; - } - } - color->r = r; - color->g = g; - color->b = b; + uint16_t r, g, b; + + printf ("%f %f %f\n", h, s, v); + if (v == 0) { + r = g = b = 0; + } else if (s == 0) { + r = g = b = float_to_uint(v); + } else { + float h6 = h * 6; + int i; + float f, p, q, t; + while (h6 >= 6) + h6 -= 6; + i = floor (h6); + f = h6 - i; + p = v * (1 - s); + q = v * (1 - (s * f)); + t = v * (1 - (s * (1 - f))); + + switch (i) { + default: + case 0: + r = float_to_uint(v); + g = float_to_uint(t); + b = float_to_uint(p); + break; + case 1: + r = float_to_uint(q); + g = float_to_uint(v); + b = float_to_uint(p); + break; + case 2: + r = float_to_uint(p); + g = float_to_uint(v); + b = float_to_uint(t); + break; + case 3: + r = float_to_uint(p); + g = float_to_uint(q); + b = float_to_uint(v); + break; + case 4: + r = float_to_uint(t); + g = float_to_uint(p); + b = float_to_uint(v); + break; + case 5: + r = float_to_uint(v); + g = float_to_uint(p); + b = float_to_uint(q); + break; + } + } + printf ("\t%d %d %d\n", r, g, b); + color->r = r; + color->g = g; + color->b = b; } struct xts_image { - int width, height, depth; - struct xts_color *colors[MAX_LEVEL]; - int num_colors; - uint32_t pixels[]; + struct xts_image *next; + char *dest_file; + int width, height, depth; + uint32_t pixels[]; }; -void assign_rgb(struct xts_image *image) { - int i; - struct xts_color *c; +static void +assign_rgb(void) { + int i; + struct xts_color *c; + + i = 0; + for (c = colors[0]; c; c = c->next[0]) { + float h, s, v; + if (i >= 2) { + h = (float) (i - 2) / (num_colors - 2); + s = 1; + v = 0.5; + } else { + h = 0; + s = 0; + v = 1-i; + } + + assign_hsv(c, h, s, v); + i++; + } +} - i = 0; - for (c = image->colors[0]; c; c = c->next[0]) { - float h = (float) i / image->num_colors; - float s = 1; - float v = 0.5; +static struct xts_color * +find_color(struct xts_image *image, uint32_t pixel) { + struct xts_color **update[MAX_LEVEL]; + struct xts_color *s, **next; + int i; + + next = colors; + for (i = MAX_LEVEL; --i >= 0;) { + for (; (s = next[i]); next = s->next) { + if (s->pixel == pixel) + return s; + if (s->pixel > pixel) + break; + } + update[i] = &next[i]; + } - assign_hsv(c, h, s, v); - i++; - } -} + s = alloc_color(); + s->pixel = pixel; + ++num_colors; -struct xts_color *find_color(struct xts_image *image, uint32_t pixel) { - struct xts_color **update[MAX_LEVEL]; - struct xts_color *s, **next; - int i, level; - - next = image->colors; - for (i = MAX_LEVEL; --i >= 0;) { - for (; (s = next[i]); next = s->next) { - if (s->pixel == pixel) - return s; - if (s->pixel > pixel) - break; - } - update[i] = &next[i]; - } - - s = alloc_color(); - s->pixel = pixel; - ++image->num_colors; - - for (i = 0; i < s->level; i++) { - struct xts_color *n = *update[i]; - s->next[i] = *update[i]; - *update[i] = s; - } - return s; + for (i = 0; i < s->level; i++) { + s->next[i] = *update[i]; + *update[i] = s; + } + return s; } -void +static void free_image(struct xts_image *image) { - struct xts_color *c, *next; - - for (c = image->colors[0]; c; c = next) { - next = c->next[0]; - free(c); - } - free (image); + free (image->dest_file); + free (image); } -struct xts_image * +static struct xts_image * read_image(FILE *file) { - int width, height, depth; - struct xts_image *image; - int count; - int run; - uint32_t pixel; - uint32_t *pixels; - char line[80]; - - if (fscanf(file, "%d %d %d\n", &width, &height, &depth) != 3) - return NULL; - - image = malloc (sizeof (struct xts_image) + - (width * height * sizeof (uint32_t))); - if (!image) - return NULL; - memset(image->colors, '\0', sizeof (image->colors)); - image->num_colors = 0; + int width, height, depth; + struct xts_image *image; + int count; + int run; + uint32_t pixel; + uint32_t *pixels; + char line[80]; + + if (fscanf(file, "%d %d %d\n", &width, &height, &depth) != 3) + return NULL; + + image = malloc (sizeof (struct xts_image) + + (width * height * sizeof (uint32_t))); + if (!image) + return NULL; - count = width * height; - pixels = image->pixels; - image->width = width; - image->height = height; - image->depth = depth; - while (count > 0) { - if (fgets(line, sizeof(line), file) == NULL) { - printf ("run bad\n"); - free(image); - return NULL; - } - if (sscanf (line, "%x,%lx\n", &run, &pixel) != 2) { - if (sscanf(line, "%x", &pixel) != 1) { - printf ("run bad\n"); - free(image); - return NULL; - } - run = 1; - } - find_color(image, pixel); - while (run > 0 && count > 0) { - *pixels++ = pixel; - run--; - count--; - } - if (run) { - printf ("run left over\n"); - free(image); - return NULL; - } - } - assign_rgb(image); - return image; -} - -/* Use a couple of simple error callbacks that do not print anything to - * stderr and rely on the user to check for errors via the #cairo_status_t - * return. - */ -static void -png_simple_error_callback (png_structp png, - png_const_charp error_msg) -{ - exit(0); + count = width * height; + pixels = image->pixels; + image->width = width; + image->height = height; + image->depth = depth; + while (count > 0) { + if (fgets(line, sizeof(line), file) == NULL) { + printf ("run bad\n"); + free(image); + return NULL; + } + if (sscanf (line, "%x,%x\n", &run, &pixel) != 2) { + if (sscanf(line, "%x", &pixel) != 1) { + printf ("run bad\n"); + free(image); + return NULL; + } + run = 1; + } + find_color(image, pixel); + while (run > 0 && count > 0) { + *pixels++ = pixel; + run--; + count--; + } + if (run) { + printf ("run left over\n"); + free(image); + return NULL; + } + } + return image; } static void -png_simple_warning_callback (png_structp png, - png_const_charp error_msg) -{ -} - - -static void png_simple_output_flush_fn (png_structp png_ptr) { } @@ -263,138 +257,127 @@ png_simple_output_flush_fn (png_structp png_ptr) static void stdio_write_func (png_structp png, png_bytep data, png_size_t size) { - FILE *fp; - - fp = png_get_io_ptr (png); - while (size) { - size_t ret = fwrite (data, 1, size, fp); - size -= ret; - data += ret; - if (size && ferror (fp)) { - exit (1); + FILE *fp; + + fp = png_get_io_ptr (png); + while (size) { + size_t ret = fwrite (data, 1, size, fp); + size -= ret; + data += ret; + if (size && ferror (fp)) { + exit (1); + } } - } } -void +static void dump_png(FILE *file, struct xts_image *image) { - png_struct *png; - png_info *info; - png_byte **rows = NULL; - int status; - uint32_t *rgb, *r; - uint32_t *pixels, pixel; - int i; - int count; - struct xts_color *color; - - rgb = malloc (image->height * image->width * sizeof (uint32_t)); - if (!rgb) - return; + png_struct *png; + png_info *info; + png_byte **rows = NULL; + int status; + uint32_t *rgb, *r; + uint32_t *pixels, pixel; + int i; + int count; + struct xts_color *color; + + rgb = malloc (image->height * image->width * sizeof (uint32_t)); + if (!rgb) + return; - r = rgb; - pixels = image->pixels; - count = image->width * image->height; - while (count-- > 0) { - pixel = *pixels++; - color = find_color(image, pixel); - *r++ = (color->b << 16) | (color->g << 8) | color->r; - } - - rows = calloc(image->height, sizeof (png_byte *)); - - for (i = 0; i < image->height; i++) - rows[i] = (png_byte *) rgb + i * image->width * sizeof (uint32_t); - - png = png_create_write_struct(PNG_LIBPNG_VER_STRING, &status, - NULL, NULL); - - info = png_create_info_struct(png); - - png_set_write_fn (png, file, stdio_write_func, png_simple_output_flush_fn); - - png_set_IHDR (png, info, - image->width, - image->height, - 8, - PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - png_write_info(png, info); - png_set_filler (png, 0, PNG_FILLER_AFTER); - png_write_image (png, rows); - png_write_end (png, info); - png_destroy_write_struct (&png, &info); - free (rows); - free (rgb); -} + r = rgb; + pixels = image->pixels; + count = image->width * image->height; + while (count-- > 0) { + pixel = *pixels++; + color = find_color(image, pixel); + *r++ = (color->b << 16) | (color->g << 8) | color->r; + } -void -dump_ppm(FILE *file, struct xts_image *image) -{ - int count; - uint32_t *pixels, pixel; - struct xts_color *color; - - fprintf (file, "P3\n"); - fprintf (file, "%d %d\n", image->width, image->height); - fprintf (file, "255\n"); - count = image->width * image->height; - pixels = image->pixels; - while (count-- > 0) { - pixel = *pixels++; - color = find_color(image, pixel); - fprintf (file, " %d %d %d\n", color->r, color->g, color->b); - } + rows = calloc(image->height, sizeof (png_byte *)); + + for (i = 0; i < image->height; i++) + rows[i] = (png_byte *) rgb + i * image->width * sizeof (uint32_t); + + png = png_create_write_struct(PNG_LIBPNG_VER_STRING, &status, + NULL, NULL); + + info = png_create_info_struct(png); + + png_set_write_fn (png, file, stdio_write_func, png_simple_output_flush_fn); + + png_set_IHDR (png, info, + image->width, + image->height, + 8, + PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + png_write_info(png, info); + png_set_filler (png, 0, PNG_FILLER_AFTER); + png_write_image (png, rows); + png_write_end (png, info); + png_destroy_write_struct (&png, &info); + free (rows); + free (rgb); } -char *newname(char *orig_name, int i, char *extension) { - char *b = basename(orig_name); - char *dot = strrchr(b, '.'); - char *new; - if (!dot) - dot = b + strlen(b); - *dot = '\0'; - - if (!asprintf(&new, "%s-%d.%s", b, i, extension)) - new = NULL; - return new; +static char * +newname(char *orig_name, int i, const char *extension) { + char *b = basename(orig_name); + char *dot = strrchr(b, '.'); + char *new; + if (!dot) + dot = b + strlen(b); + *dot = '\0'; + + if (!asprintf(&new, "%s-%d.%s", b, i, extension)) + new = NULL; + return new; } int main (int argc, char **argv) { - struct xts_image *image; - FILE *input; - FILE *output; - char *outname; - char *inname; - int f, i; - - for (f = 1; f < argc; f++) { - inname = argv[f]; - input = fopen(inname, "r"); - if (!input) { - perror(inname); - continue; - } - i = 0; - while ((image = read_image(input)) != NULL) { - outname = newname(inname, i++, "png"); - if (outname) { - output = fopen(outname, "w"); - if (!output) - perror(outname); - else { - dump_png(output, image); - fclose(output); - } - free (outname); - } - free_image(image); - } - } + struct xts_image *image; + FILE *input; + FILE *output; + char *inname; + int f, i; + struct xts_image *images = NULL, **last = &images; + + for (f = 1; f < argc; f++) { + inname = argv[f]; + input = fopen(inname, "r"); + if (!input) { + perror(inname); + continue; + } + i = 0; + while ((image = read_image(input)) != NULL) { + image->dest_file = newname(inname, i++, "png"); + image->next = NULL; + *last = image; + last = &image->next; + } + } + printf ("%d colors\n", num_colors); + assign_rgb(); + while ((image = images) != NULL) { + if (image->dest_file) { + output = fopen(image->dest_file, "w"); + if (!output) + perror(image->dest_file); + else { + dump_png(output, image); + fclose(output); + } + } + images = image->next; + free_image(image); + } } |