diff options
author | Simon Rettberg | 2024-09-06 14:42:37 +0200 |
---|---|---|
committer | Simon Rettberg | 2024-09-06 14:42:37 +0200 |
commit | badef32037f52f79abc1f1440b786cd71afdf270 (patch) | |
tree | 412b792d4cab4a7a110db82fcf74fe8a1ac55ec1 /hacks/webcollage-helper-cocoa.m | |
parent | Delete pre-6.00 files (diff) | |
download | xscreensaver-master.tar.gz xscreensaver-master.tar.xz xscreensaver-master.zip |
Diffstat (limited to 'hacks/webcollage-helper-cocoa.m')
-rw-r--r-- | hacks/webcollage-helper-cocoa.m | 510 |
1 files changed, 0 insertions, 510 deletions
diff --git a/hacks/webcollage-helper-cocoa.m b/hacks/webcollage-helper-cocoa.m deleted file mode 100644 index fde1f0d..0000000 --- a/hacks/webcollage-helper-cocoa.m +++ /dev/null @@ -1,510 +0,0 @@ -/* webcollage-helper-cocoa --- scales and pastes one image into another - * 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 - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - */ - -/* This is the Cocoa implementation. See webcollage-helper.c for the - GDK + JPEGlib implementation. - */ - -#import <Cocoa/Cocoa.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/stat.h> - - -#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; - -static void write_image (NSImage *img, const char *file); - - -/* NSImage can't load PPMs by default... - */ -static NSImage * -load_ppm_image (const char *file) -{ - FILE *in = fopen (file, "r"); - if (! in) return 0; - - char buf[255]; - - char *s = fgets (buf, sizeof(buf)-1, in); /* P6 */ - if (!s || !!strcmp (s, "P6\n")) - return 0; - - s = fgets (buf, sizeof(buf)-1, in); /* W H */ - if (!s) - return 0; - - int w = 0, h = 0, d = 0; - if (2 != sscanf (buf, " %d %d \n", &w, &h)) - return 0; - if (w <= 0 || h <= 0) - return 0; - - s = fgets (buf, sizeof(buf)-1, in); /* 255 */ - if (!s) - return 0; - - if (1 != sscanf (buf, " %d \n", &d)) - return 0; - if (d != 255) - return 0; - - int size = (w * (h+1) * 3); - unsigned char *bits = malloc (size); - if (!bits) return 0; - - int n = read (fileno (in), (void *) bits, size); /* body */ - if (n < 20) return 0; - - fclose (in); - - NSBitmapImageRep *rep = - [[NSBitmapImageRep alloc] - initWithBitmapDataPlanes: &bits - pixelsWide: w - pixelsHigh: h - bitsPerSample: 8 - samplesPerPixel: 3 - hasAlpha: NO - isPlanar: NO - colorSpaceName: NSDeviceRGBColorSpace - bitmapFormat: NSAlphaFirstBitmapFormat - bytesPerRow: w * 3 - bitsPerPixel: 8 * 3]; - - NSImage *image = [[NSImage alloc] initWithSize: NSMakeSize (w, h)]; - [image addRepresentation: rep]; - [rep release]; - - // #### 'bits' is leaked... the NSImageRep doesn't free it when freed. - - return image; -} - - -static NSImage * -load_image (const char *file) -{ - NSImage *image = [[NSImage alloc] - initWithContentsOfFile: - [NSString stringWithCString: file - encoding: NSUTF8StringEncoding]]; - if (! image) - image = load_ppm_image (file); - - if (! image) { - fprintf (stderr, "%s: unable to load %s\n", progname, 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 void -bevel_image (NSImage *img, int bevel_pct, - int x, int y, int w, int h, double scale) -{ - int small_size = (w > h ? h : w); - - int bevel_size = small_size * (bevel_pct / 100.0); - - bevel_size /= scale; - - /* 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; - - - NSBitmapImageRep *rep = - [[NSBitmapImageRep alloc] - initWithBitmapDataPlanes: NULL - pixelsWide: w - pixelsHigh: h - bitsPerSample: 8 - samplesPerPixel: 4 - hasAlpha: YES - isPlanar: NO - colorSpaceName: NSDeviceRGBColorSpace - bitmapFormat: NSAlphaFirstBitmapFormat - bytesPerRow: 0 - bitsPerPixel: 0]; - - NSInteger xx, yy; - double *ramp = (double *) malloc (sizeof(*ramp) * (bevel_size + 1)); - - if (!ramp) - { - fprintf (stderr, "%s: out of memory (%d)\n", progname, bevel_size); - exit (1); - } - - for (xx = 0; xx <= bevel_size; xx++) - { -# if 0 /* linear */ - ramp[xx] = xx / (double) bevel_size; - -# else /* sinusoidal */ - double p = (xx / (double) bevel_size); - double s = sin (p * M_PI / 2); - ramp[xx] = s; -# endif - } - - memset ([rep bitmapData], 0xFFFFFFFF, - [rep bytesPerRow] * h); - - for (yy = 0; yy < h; yy++) - { - for (xx = 0; xx < w; xx++) - { - double rx, ry, r; - - if (xx < bevel_size) rx = ramp[xx]; - else if (xx >= w - bevel_size) rx = ramp[w - xx - 1]; - else rx = 1; - - if (yy < bevel_size) ry = ramp[yy]; - else if (yy >= h - bevel_size) ry = ramp[h - yy - 1]; - else ry = 1; - - r = rx * ry; - if (r != 1) - { - NSUInteger p[4]; - p[0] = 0xFF * r; - p[1] = p[2] = p[3] = 0xFF; - [rep setPixel:p atX:xx y:yy]; - } - } - } - - free (ramp); - - NSImage *bevel_img = [[NSImage alloc] - initWithData: [rep TIFFRepresentation]]; - - [img lockFocus]; - y = [img size].height - (y + h); - [bevel_img drawAtPoint: NSMakePoint (x, y) - fromRect: NSMakeRect (0, 0, w, h) - operation: NSCompositeDestinationIn /* Destination image - wherever both images are - opaque, transparent - elsewhere. */ - fraction: 1.0]; - [img unlockFocus]; - - [rep release]; - [bevel_img release]; - - if (verbose_p) - fprintf (stderr, "%s: added %d%% bevel (%d px)\n", progname, - bevel_pct, bevel_size); -} - - -static void -paste (const char *paste_file, - const char *base_file, - double from_scale, - double opacity, int bevel_pct, - int from_x, int from_y, int to_x, int to_y, - int w, int h) -{ - NSImage *paste_img = load_image (paste_file); - NSImage *base_img = load_image (base_file); - - int paste_w = [paste_img size].width; - int paste_h = [paste_img size].height; - - int base_w = [base_img size].width; - int base_h = [base_img size].height; - - if (verbose_p) - { - fprintf (stderr, "%s: loaded %s: %dx%d\n", - progname, base_file, base_w, base_h); - fprintf (stderr, "%s: loaded %s: %dx%d\n", - progname, paste_file, paste_w, paste_h); - } - - if (bevel_pct > 0 && paste_w > 5 && paste_h > 5) - bevel_image (paste_img, bevel_pct, - from_x, from_y, w, h, - from_scale); - - int scaled_w = w * from_scale; - int scaled_h = h * from_scale; - - from_y = paste_h - (from_y + h); // Cocoa flipped coordinate system - to_y = base_h - (to_y + scaled_h); - - [base_img lockFocus]; - [paste_img drawInRect: NSMakeRect (to_x, to_y, scaled_w, scaled_h) - fromRect: NSMakeRect (from_x, from_y, w, h) - operation: NSCompositeSourceOver - fraction: opacity]; - [base_img unlockFocus]; - - if (verbose_p) - fprintf (stderr, "%s: pasted %dx%d (%dx%d) from %d,%d to %d,%d\n", - progname, w, h, scaled_w, scaled_h, from_x, from_y, to_x, to_y); - - [paste_img release]; - write_image (base_img, base_file); - [base_img release]; -} - - -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. - -#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: error converting image?\n", progname); - exit (1); - } - - if (verbose_p) - fprintf (stderr, "%s: writing %s (q=%d%%) ", progname, file, - (int) (jpeg_quality * 100)); - - NSData *jpeg_data = [bit_rep representationUsingType:NSJPEGFileType - properties:@{ NSImageCompressionFactor: - [NSNumber numberWithFloat: - jpeg_quality] }]; - [jpeg_data writeToFile: - [NSString stringWithCString:file - encoding:NSISOLatin1StringEncoding] - atomically:YES]; - - if (verbose_p) - { - struct stat st; - if (stat (file, &st)) - { - char buf[255]; - sprintf (buf, "%.100s: %.100s", progname, file); - perror (buf); - exit (1); - } - fprintf (stderr, " %luK\n", ((unsigned long) st.st_size + 1023) / 1024); - } -} - - -static void -usage (void) -{ - 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" - "\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); -} - - -int -main (int argc, char **argv) -{ - int i; - char *paste_file, *base_file, *s, dummy; - double from_scale, opacity; - int from_x, from_y, to_x, to_y, w, h, bevel_pct; - - i = 0; - progname = argv[i++]; - s = strrchr (progname, '/'); - if (s) progname = s+1; - - // Much of Cocoa needs one of these to be available. - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - //Need an NSApp instance to make [NSImage TIFFRepresentation] work - NSApp = [NSApplication sharedApplication]; - [NSApp autorelease]; - - 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]; - - exit (0); -} |