X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fwebcollage-helper-cocoa.m;h=fde1f0d9add7ee2824537293c078ca8e2d10ebd8;hb=78add6e627ee5f10e1fa6f3852602ea5066eee5a;hp=05f95c4e2002f66b7253019e64cb1123d680e724;hpb=c494fd2e6b3b25582375d62e40f4f5cc984ca424;p=xscreensaver diff --git a/hacks/webcollage-helper-cocoa.m b/hacks/webcollage-helper-cocoa.m index 05f95c4e..fde1f0d9 100644 --- a/hacks/webcollage-helper-cocoa.m +++ b/hacks/webcollage-helper-cocoa.m @@ -1,5 +1,5 @@ /* webcollage-helper-cocoa --- scales and pastes one image into another - * xscreensaver, Copyright (c) 2002-2006 Jamie Zawinski + * xscreensaver, Copyright (c) 2002-2018 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 @@ -20,6 +20,13 @@ #include #include + +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 + typedef int NSInteger; + typedef unsigned int NSUInteger; +#endif + + char *progname; static int verbose_p = 0; @@ -98,7 +105,7 @@ load_image (const char *file) NSImage *image = [[NSImage alloc] initWithContentsOfFile: [NSString stringWithCString: file - encoding: kCFStringEncodingUTF8]]; + encoding: NSUTF8StringEncoding]]; if (! image) image = load_ppm_image (file); @@ -107,6 +114,14 @@ load_image (const char *file) exit (1); } + + // [NSImage size] defaults to the image size in points instead of pixels, + // so if an image file specified "pixels per inch" we can end up with + // absurdly sized images. Set it back to 1:1 pixel:point. + // + NSImageRep *rep = [image.representations objectAtIndex:0]; + image.size = NSMakeSize (rep.pixelsWide, rep.pixelsHigh); + return image; } @@ -142,7 +157,7 @@ bevel_image (NSImage *img, int bevel_pct, bytesPerRow: 0 bitsPerPixel: 0]; - int xx, yy; + NSInteger xx, yy; double *ramp = (double *) malloc (sizeof(*ramp) * (bevel_size + 1)); if (!ramp) @@ -183,7 +198,7 @@ bevel_image (NSImage *img, int bevel_pct, r = rx * ry; if (r != 1) { - unsigned int p[4]; + NSUInteger p[4]; p[0] = 0xFF * r; p[1] = p[2] = p[3] = 0xFF; [rep setPixel:p atX:xx y:yy]; @@ -207,6 +222,7 @@ bevel_image (NSImage *img, int bevel_pct, fraction: 1.0]; [img unlockFocus]; + [rep release]; [bevel_img release]; if (verbose_p) @@ -240,7 +256,7 @@ paste (const char *paste_file, progname, paste_file, paste_w, paste_h); } - if (bevel_pct > 0) + if (bevel_pct > 0 && paste_w > 5 && paste_h > 5) bevel_image (paste_img, bevel_pct, from_x, from_y, w, h, from_scale); @@ -268,14 +284,94 @@ paste (const char *paste_file, } +static NSColor * +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 [NSColor colorWithRed: r / 255.0 + green: g / 255.0 + blue: b / 255.0 + alpha: 1.0]; +} + + +static void +create (const char *color, + int w, int h, + const char *file) +{ + NSColor *c = parse_color (color); + NSImage *img = [[NSImage alloc] initWithSize:NSMakeSize(w, h)]; + [img lockFocus]; + [c drawSwatchInRect:NSMakeRect(0, 0, w, h)]; + [img unlockFocus]; + write_image (img, file); + [img release]; +} + + static void write_image (NSImage *img, const char *file) { float jpeg_quality = .85; - // Load the NSImage's contents into an NSBitmapImageRep: + // Load the NSImage's contents into an NSBitmapImageRep. + +#if 0 + // If the local display is Retina, this doubles the size of the output JPEG. NSBitmapImageRep *bit_rep = [NSBitmapImageRep imageRepWithData:[img TIFFRepresentation]]; +#else + // Render the image into a rep using pixels instead of points. + NSBitmapImageRep *bit_rep = [[NSBitmapImageRep alloc] + initWithBitmapDataPlanes:NULL + pixelsWide:[img size].width + pixelsHigh:[img size].height + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSCalibratedRGBColorSpace + bytesPerRow:0 + bitsPerPixel:0]; + bit_rep.size = [img size]; + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext: + [NSGraphicsContext + graphicsContextWithBitmapImageRep:bit_rep]]; + [img drawInRect:NSMakeRect(0, 0, [img size].width, [img size].height) + fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0]; + [NSGraphicsContext restoreGraphicsState]; +#endif // Write the bitmapImageRep to a JPEG file. if (bit_rep == nil) @@ -288,15 +384,13 @@ write_image (NSImage *img, const char *file) fprintf (stderr, "%s: writing %s (q=%d%%) ", progname, file, (int) (jpeg_quality * 100)); - NSDictionary *props = [NSDictionary - dictionaryWithObject: - [NSNumber numberWithFloat:jpeg_quality] - forKey:NSImageCompressionFactor]; NSData *jpeg_data = [bit_rep representationUsingType:NSJPEGFileType - properties:props]; - + properties:@{ NSImageCompressionFactor: + [NSNumber numberWithFloat: + jpeg_quality] }]; [jpeg_data writeToFile: - [NSString stringWithCString:file] + [NSString stringWithCString:file + encoding:NSISOLatin1StringEncoding] atomically:YES]; if (verbose_p) @@ -317,14 +411,18 @@ write_image (NSImage *img, const char *file) 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); } @@ -342,38 +440,6 @@ 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(); - - // Much of Cocoa needs one of these to be available. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -381,10 +447,62 @@ main (int argc, char **argv) NSApp = [NSApplication sharedApplication]; [NSApp autorelease]; - paste (paste_file, base_file, - from_scale, opacity, bevel_pct, - from_x, from_y, to_x, to_y, - w, h); + if (!strcmp(argv[i], "-v")) + verbose_p++, i++; + + 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(); + + if (w == 0 || h == 0 || + w > 10240 || h > 10240) { + fprintf (stderr, "%s: absurd size: %d x %d\n", progname, w, h); + exit (1); + } + + 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(); + + create (color, w, h, paste_file); + } + else + { + usage(); + } [pool release];