/* webcollage-helper-cocoa --- scales and pastes one image into another
- * xscreensaver, Copyright (c) 2002-2009 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 2002-2018 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
NSImage *image = [[NSImage alloc]
initWithContentsOfFile:
[NSString stringWithCString: file
- encoding: kCFStringEncodingUTF8]];
+ encoding: NSUTF8StringEncoding]];
if (! image)
image = load_ppm_image (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;
}
}
+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)
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
encoding:NSISOLatin1StringEncoding]
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);
}
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 (w == 0 || h == 0 ||
- w > 10240 || h > 10240) {
- fprintf (stderr, "%s: absurd size: %d x %d\n", progname, w, h);
- exit (1);
- }
-
-
// Much of Cocoa needs one of these to be available.
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
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];