From 763efda3098f8098b18ce37f29e67f6485f0836f Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Wed, 25 May 2022 18:26:40 +0200 Subject: Initial commit --- Makefile | 15 ++++++ genclockimg.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 Makefile create mode 100644 genclockimg.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3ec2468 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ + +CFLAGS = -I/usr/include/cairo -D_XOPEN_SOURCE -g +LDDFLAGS = -lcairo -lpopt -lm + +SRC = genclockimg.o +TARGET = genclockimg + +$(TARGET): $(SRC) + gcc $(SRC) -o $(TARGET) $(LDDFLAGS) + +all: + +clean: + rm *.o $(TARGET) + diff --git a/genclockimg.c b/genclockimg.c new file mode 100644 index 0000000..e85a4ee --- /dev/null +++ b/genclockimg.c @@ -0,0 +1,152 @@ +/* + genclockimg + generates a clock face PNG image +*/ +#include +#include +#include +#include +#include +#include + +#include + +int main (int argc, const char **argv) +{ + + /* configuration options */ + int img_width; + int img_height; + char *img_filename; + char img_filename_default[] = "out.png\0"; + char *timestr; + + /* timestamp represeting what time to draw */ + time_t clock_timestamp; + struct tm *clock_localtime; + int h; + int m; + + /* cairo surface and context */ + cairo_surface_t *surface; + cairo_t *context; + + /* popt options table */ + struct poptOption options_table[] = { + {"out", 'o', POPT_ARG_STRING, &img_filename, 0, "output filename", NULL }, + {"width", 'w', POPT_ARG_INT, &img_width, 0, "output image width", NULL }, + {"height", 'h', POPT_ARG_INT, &img_height, 0, "output image height", NULL }, + {"hours", '\0', POPT_ARG_INT, &h, 0, "hour to display", NULL }, + {"minutes", '\0', POPT_ARG_INT, &m, 0, "minutes to display", NULL }, + {"time", 't', POPT_ARG_STRING, ×tr, 0, "time to display as HH:MM", NULL}, + POPT_AUTOHELP + {NULL, '\0', 0, NULL, 0, NULL, NULL} + }; + /* popt context */ + poptContext options_context; + + /* default filename is out.png */ + img_filename = NULL; + + timestr = NULL; + + /* default image size is 128x128 */ + img_width = 128; + img_height = 128; + + /* default timestamp is current localtime */ + clock_timestamp = time(NULL); + clock_localtime = localtime(&clock_timestamp); + h = clock_localtime->tm_hour % 12; + m = clock_localtime->tm_min; + + /* parse command line options */ + options_context = poptGetContext(NULL, argc, argv, options_table, 0); + + int result; + while ((result = poptGetNextOpt(options_context)) > 0 ) { + } + if (result < -1) { + /* an error occurred during option processing */ + fprintf(stderr, "%s: %s\n", poptBadOption(options_context, POPT_BADOPTION_NOALIAS), poptStrerror(result)); + exit(1); + } + + if (img_filename == NULL) { + img_filename = img_filename_default; + } + + if (timestr != NULL ) { + /* note: clock_localtime is already initialized here */ + strptime(timestr, "%H:%M", clock_localtime); + h = clock_localtime->tm_hour % 12; + m = clock_localtime->tm_min; + } + + /* keep hours and minutes into range */ + h %= 12; + m %= 60; + + /* create the cairo drawing context and an RGBA drawing surface */ + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, img_width, img_height); + context = cairo_create(surface); + + /* draw image */ + cairo_set_source_rgba(context, 0.0, 0.0, 0.0, 0.0); + cairo_rectangle(context, 0, 0, img_width, img_height); + cairo_fill(context); + + int x1 = img_width / 2 -1; + int y1 = img_height / 2 -1; + + float r; + if (img_width < img_height) { + r = img_width / 2; + } else { + r = img_height /2; + } + float angle = 2.0f * M_PI / 12.0f; + + /* draw clock face */ + cairo_set_source_rgba (context, 1.0, 1.0, 1.0, 1.0); + cairo_arc(context, x1, y1, r-4, 0, 2 * M_PI); + cairo_fill(context); + + cairo_set_source_rgba (context, 0.0, 0.0, 0.0, 1.0); + cairo_set_line_width (context, 1); + cairo_arc(context, x1, y1, r-4, 0, 2 * M_PI); + cairo_stroke(context); + + /* draw markers */ + cairo_set_source_rgba (context, 0.0, 0.0, 0.0, 1.0); + cairo_set_line_width (context, 2); + for (int h = 0; h < 12; h++) { + cairo_move_to(context, x1 + (r - 10) * cosf(angle * h), y1 + (r - 10) * sinf(angle * h)); + cairo_line_to(context, x1 + (r - 4) * cosf(angle * h), y1 + (r - 4)* sinf(angle * h)); + } + cairo_stroke(context); + + /* draw handles */ + cairo_set_line_width (context, 4); + + /* hours handle */ + cairo_move_to(context, x1, y1); + cairo_line_to(context, x1 + (r/2 - 4) * sinf(angle * h + angle / 60 * m), y1 - (r/2 - 4) * cosf(angle * h + angle / 60 * m)); + + /* minutes handle */ + cairo_move_to(context, x1, y1); + cairo_line_to(context, x1 + (r - 10) * sinf(M_PI / 30.0f * m ), y1 - (r - 10) * cosf(M_PI / 30.0f * m)); + cairo_stroke(context); + + + /* write image file */ + if (cairo_surface_write_to_png(surface, img_filename) != CAIRO_STATUS_SUCCESS) { + fprintf(stderr, "Error saving %s\n", img_filename); + } + + /* cleanup */ + cairo_surface_destroy(surface); + poptFreeContext(options_context); + + return 0; +} -- cgit v1.2.3