summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2014-01-04 00:35:57 -0800
committerKeith Packard <keithp@keithp.com>2014-01-04 00:35:57 -0800
commitf76a454566bd94c8bb5d8def93ba6bf79fe89a68 (patch)
tree3238f3fd4ca013f61a17a39f576fa0d7132cdef1
parentcb8f6b3c2200f651a4e005ecbd25e5bf6fa01139 (diff)
Autoconf. Common colors
-rw-r--r--Makefile5
-rw-r--r--Makefile.am36
-rw-r--r--configure.ac41
-rw-r--r--xtsttopng.c613
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);
+ }
}