X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fwebcollage-helper.c;h=46ec608a8056d5abdf20b9151f80239c7b415887;hb=39809ded547bdbb08207d3e514950425215b4410;hp=7c686db94c08d0e65f53a193195b1a7d763cb8db;hpb=9c9d475ff889ed8be02e8ce8c17da28b93278fca;p=xscreensaver diff --git a/hacks/webcollage-helper.c b/hacks/webcollage-helper.c index 7c686db9..46ec608a 100644 --- a/hacks/webcollage-helper.c +++ b/hacks/webcollage-helper.c @@ -1,5 +1,5 @@ /* webcollage-helper --- scales and pastes one image into another - * xscreensaver, Copyright (c) 2002, 2003, 2004 Jamie Zawinski + * xscreensaver, Copyright (c) 2002-2017 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -10,6 +10,10 @@ * implied warranty. */ +/* This is the GDK + JPEGlib implementation. See webcollage-helper-cocoa.m + for the Cocoa implementation. + */ + #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -24,6 +28,7 @@ #include #include +#undef HAVE_STDLIB_H /* stupid jconfig.h! */ #include #include @@ -66,17 +71,21 @@ bevel_image (GdkPixbuf **pbP, int bevel_pct, int x, int y, int w, int h) { GdkPixbuf *pb = *pbP; + int small_size = (w > h ? h : w); - int bevel_size = (w > h ? h : w) * (bevel_pct / 100.0); + int bevel_size = small_size * (bevel_pct / 100.0); - if (bevel_size < 10) /* too small to bother */ + /* Use a proportionally larger bevel size for especially small images. */ + if (bevel_size < 20 && small_size > 40) bevel_size = 20; + else if (bevel_size < 10 && small_size > 20) bevel_size = 10; + else if (bevel_size < 5) /* too small to bother bevelling */ return; /* Ensure the pixbuf has an alpha channel. */ if (! gdk_pixbuf_get_has_alpha (pb)) { GdkPixbuf *pb2 = gdk_pixbuf_add_alpha (pb, FALSE, 0, 0, 0); - gdk_pixbuf_unref (pb); + g_object_unref (pb); pb = pb2; } @@ -127,25 +136,24 @@ bevel_image (GdkPixbuf **pbP, int bevel_pct, if (r != 1) p[ch-1] *= r; - /* p[0]=p[1]=p[2]=0; / * #### */ - p += ch; } line += rs; } #if 0 /* show the ramp */ - for (xx = 0; xx < bevel_size * 2; xx++) + line = data + (rs * y); + for (yy = 0; yy < h; yy++) { - int ii = (256 * (xx >= bevel_size ? 1 : ramp[xx])); - int yy; - for (yy = 0; yy < ii; yy++) + guchar *p = line + (x * ch); + for (xx = 0; xx < w; xx++) { - data [((y + (256-yy)) * rs) + ((x + xx) * ch) + 0] = 0; - data [((y + (256-yy)) * rs) + ((x + xx) * ch) + 1] = 0; - data [((y + (256-yy)) * rs) + ((x + xx) * ch) + 2] = 0; - data [((y + (256-yy)) * rs) + ((x + xx) * ch) + 3] = 255; + int cc = 0; + for (cc = 0; cc < ch-1; cc++) + p[cc] = 255; + p += ch; } + line += rs; } #endif @@ -197,7 +205,7 @@ paste (const char *paste_file, int new_h = paste_h * from_scale; GdkPixbuf *new_pb = gdk_pixbuf_scale_simple (paste_pb, new_w, new_h, GDK_INTERP_HYPER); - gdk_pixbuf_unref (paste_pb); + g_object_unref (paste_pb); paste_pb = new_pb; paste_w = gdk_pixbuf_get_width (paste_pb); paste_h = gdk_pixbuf_get_height (paste_pb); @@ -294,20 +302,96 @@ paste (const char *paste_file, base_pb, to_x, to_y); else - gdk_pixbuf_composite (paste_pb, base_pb, - to_x, to_y, w, h, - to_x - from_x, to_y - from_y, - 1.0, 1.0, - GDK_INTERP_HYPER, - opacity * 255); + { + from_x++; /* gdk_pixbuf_composite gets confused about the bevel: */ + from_y++; /* it leaves a stripe on the top and left if we try to */ + to_x++; /* start at 0,0, so pull it right and down by 1 pixel. */ + to_y++; /* (problem seen in gtk2-2.4.14-2.fc3) */ + w--; + h--; + + if (w > 0 && h > 0) + gdk_pixbuf_composite (paste_pb, base_pb, + to_x, to_y, w, h, + to_x - from_x, to_y - from_y, + 1.0, 1.0, + GDK_INTERP_HYPER, + opacity * 255); + } if (verbose_p) fprintf (stderr, "%s: pasted %dx%d from %d,%d to %d,%d\n", progname, paste_w, paste_h, from_x, from_y, to_x, to_y); - gdk_pixbuf_unref (paste_pb); + g_object_unref (paste_pb); write_pixbuf (base_pb, base_file); - gdk_pixbuf_unref (base_pb); + g_object_unref (base_pb); +} + + +static guint32 +parse_color (const char *s) +{ + static const char hex[128] = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, + 0, 10,11,12,13,14,15,0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10,11,12,13,14,15,0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + unsigned char r=0, g=0, b=0; + + if (!strcasecmp (s, "black")) ; + else if (!strcasecmp (s, "white")) r = g = b = 0xFF; + else if (!strcasecmp (s, "red")) r = 0xFF; + else if (!strcasecmp (s, "green")) g = 0xFF; + else if (!strcasecmp (s, "blue")) b = 0xFF; + else + { + if (*s != '#' || strlen(s) != 7) + { + fprintf (stderr, "%s: unparsable color: \"%s\"\n", progname, s); + exit (1); + } + s++; + r = (hex[(int) s[0]] << 4) | hex[(int) s[1]], s += 2; + g = (hex[(int) s[0]] << 4) | hex[(int) s[1]], s += 2; + b = (hex[(int) s[0]] << 4) | hex[(int) s[1]], s += 2; + } + + return (r << 16) | (g << 8) | b; +} + + +static void +create (const char *color, + int w, int h, + const char *file) +{ + int i; + GdkPixbuf *pb; + guint32 pixel = parse_color (color); + unsigned char *bytes = malloc (w * h * 3); + if (!bytes) abort(); + for (i = 0; i < w * h * 3; i += 3) + { + bytes[i] = 0xFF & (pixel >> 16); + bytes[i+1] = 0xFF & (pixel >> 8); + bytes[i+2] = 0xFF & (pixel); + } + + pb = gdk_pixbuf_new_from_data (bytes, GDK_COLORSPACE_RGB, + FALSE, 8, /* alpha, sample size */ + w, h, + w * 3, /* rowstride */ + NULL, 0); + if (!pb) abort(); + write_pixbuf (pb, file); + g_object_unref (pb); + free (bytes); } @@ -384,7 +468,7 @@ write_pixbuf (GdkPixbuf *pb, const char *file) perror (buf); exit (1); } - fprintf (stderr, " %luK\n", (st.st_size + 1023) / 1024); + fprintf (stderr, " %luK\n", ((unsigned long) st.st_size + 1023) / 1024); } fclose (out); @@ -401,7 +485,7 @@ add_jpeg_comment (struct jpeg_compress_struct *cinfo) " Generated by WebCollage: Exterminate All Rational Thought. \r\n" " Copyright (c) 1999-%Y by Jamie Zawinski \r\n" "\r\n" - " http://www.jwz.org/webcollage/ \r\n" + " https://www.jwz.org/webcollage/ \r\n" "\r\n" " This is what the web looked like on %d %b %Y at %I:%M:%S %p %Z. \r\n" "\r\n"; @@ -416,14 +500,18 @@ add_jpeg_comment (struct jpeg_compress_struct *cinfo) static void usage (void) { - fprintf (stderr, "usage: %s [-v] paste-file base-file\n" + fprintf (stderr, + "\nusage: %s [-v] paste-file base-file\n" "\t from-scale opacity\n" "\t from-x from-y to-x to-y w h\n" "\n" "\t Pastes paste-file into base-file.\n" "\t base-file will be overwritten (with JPEG data.)\n" - "\t scaling is applied first: coordinates apply to scaled image.\n", - progname); + "\t scaling is applied first: coordinates apply to scaled image.\n" + "\n" + "usage: %s [-v] color width height output-file\n" + "\t Creates a new image of a solid color.\n\n", + progname, progname); exit (1); } @@ -441,45 +529,63 @@ main (int argc, char **argv) s = strrchr (progname, '/'); if (s) progname = s+1; - if (argc != 11 && argc != 12) usage(); - if (!strcmp(argv[i], "-v")) verbose_p++, i++; - paste_file = argv[i++]; - base_file = argv[i++]; - - if (*paste_file == '-') usage(); - if (*base_file == '-') usage(); - - s = argv[i++]; - if (1 != sscanf (s, " %lf %c", &from_scale, &dummy)) usage(); - if (from_scale <= 0 || from_scale > 100) usage(); - - s = argv[i++]; - if (1 != sscanf (s, " %lf %c", &opacity, &dummy)) usage(); - if (opacity <= 0 || opacity > 1) usage(); - - s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_x, &dummy)) usage(); - s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_y, &dummy)) usage(); - s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_x, &dummy)) usage(); - s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_y, &dummy)) usage(); - s = argv[i++]; if (1 != sscanf (s, " %d %c", &w, &dummy)) usage(); - s = argv[i++]; if (1 != sscanf (s, " %d %c", &h, &dummy)) usage(); - - bevel_pct = 10; /* #### */ - - if (w < 0) usage(); - if (h < 0) usage(); + if (argc == 11 || argc == 12) + { + paste_file = argv[i++]; + base_file = argv[i++]; + + if (*paste_file == '-') usage(); + if (*base_file == '-') usage(); + + s = argv[i++]; + if (1 != sscanf (s, " %lf %c", &from_scale, &dummy)) usage(); + if (from_scale <= 0 || from_scale > 100) usage(); + + s = argv[i++]; + if (1 != sscanf (s, " %lf %c", &opacity, &dummy)) usage(); + if (opacity <= 0 || opacity > 1) usage(); + + s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_x, &dummy)) usage(); + s = argv[i++]; if (1 != sscanf (s, " %d %c", &from_y, &dummy)) usage(); + s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_x, &dummy)) usage(); + s = argv[i++]; if (1 != sscanf (s, " %d %c", &to_y, &dummy)) usage(); + s = argv[i++]; if (1 != sscanf (s, " %d %c", &w, &dummy)) usage(); + s = argv[i]; if (1 != sscanf (s, " %d %c", &h, &dummy)) usage(); + + bevel_pct = 10; /* #### */ + + if (w < 0) usage(); + if (h < 0) usage(); + +# ifdef HAVE_GTK2 +# if !GLIB_CHECK_VERSION(2, 36 ,0) + g_type_init (); +# endif +# endif /* HAVE_GTK2 */ + + paste (paste_file, base_file, + from_scale, opacity, bevel_pct, + from_x, from_y, to_x, to_y, + w, h); + } + else if (argc == 4 || argc == 5) + { + char *color = argv[i++]; + s = argv[i++]; if (1 != sscanf (s, " %d %c", &w, &dummy)) usage(); + s = argv[i++]; if (1 != sscanf (s, " %d %c", &h, &dummy)) usage(); + paste_file = argv[i++]; + if (*paste_file == '-') usage(); -#ifdef HAVE_GTK2 - g_type_init (); -#endif /* HAVE_GTK2 */ + create (color, w, h, paste_file); + } + else + { + usage(); + } - paste (paste_file, base_file, - from_scale, opacity, bevel_pct, - from_x, from_y, to_x, to_y, - w, h); exit (0); }