GraphicsUtils.m
author Jens Alfke <jens@mooseyard.com>
Wed Apr 02 14:45:33 2008 -0700 (2008-04-02)
changeset 2 3d3dcc3116d5
parent 1 e55a17cdabd2
child 3 8fad19466c59
permissions -rw-r--r--
UniqueWindowController finds windows that are miniaturized.
Added some date and more graphics utilities.
jens@0
     1
//
jens@0
     2
//  GraphicsUtils.m
jens@0
     3
//  MYUtilities
jens@0
     4
//
jens@0
     5
//  Copyright 2008 Jens Alfke. All rights reserved.
jens@0
     6
//
jens@0
     7
jens@0
     8
#import "GraphicsUtils.h"
jens@0
     9
jens@0
    10
jens@0
    11
@implementation NSImage (MYUtilities)
jens@0
    12
jens@0
    13
jens@2
    14
- (NSBitmapImageRep*) my_bitmapRep
jens@2
    15
{
jens@2
    16
    NSSize max = {0,0};
jens@2
    17
    NSBitmapImageRep *bestRep = nil;
jens@2
    18
    for( NSImageRep *rep in self.representations )
jens@2
    19
        if( [rep isKindOfClass: [NSBitmapImageRep class]] ) {
jens@2
    20
            NSSize size = [rep size];
jens@2
    21
            if( size.width > max.width || size.height > max.height ) {
jens@2
    22
                bestRep = (NSBitmapImageRep*)rep;
jens@2
    23
                max = size;
jens@2
    24
            }
jens@2
    25
        }
jens@2
    26
    if( ! bestRep ) {
jens@2
    27
        NSImage *tiffImage = [[NSImage alloc] initWithData:[self TIFFRepresentation]];
jens@2
    28
        bestRep = [[tiffImage representations] objectAtIndex:0];
jens@2
    29
        [tiffImage autorelease];
jens@2
    30
    }
jens@2
    31
    return bestRep;
jens@2
    32
}
jens@2
    33
jens@2
    34
jens@0
    35
- (NSSize) my_sizeOfLargestRep
jens@0
    36
{
jens@0
    37
    NSArray *reps = [self representations];
jens@0
    38
    NSSize max = {0,0};
jens@0
    39
    int i;
jens@0
    40
    for( i=[reps count]-1; i>=0; i-- ) {
jens@0
    41
        NSImageRep *rep = [reps objectAtIndex: i];
jens@0
    42
        NSSize size = [rep size];
jens@0
    43
        if( size.width > max.width || size.height > max.height ) {
jens@0
    44
            max = size;
jens@0
    45
        }
jens@0
    46
    }
jens@0
    47
    return max;
jens@0
    48
}
jens@0
    49
jens@0
    50
jens@0
    51
- (NSImage*) my_shrunkToFitIn: (NSSize) maxSize
jens@0
    52
{
jens@0
    53
    NSSize size = self.size;
jens@1
    54
    float scale = MIN( maxSize.width/size.width, maxSize.height/size.height );
jens@0
    55
    if( scale >= 1.0 )
jens@0
    56
        return self;
jens@0
    57
    
jens@0
    58
    NSSize newSize = {roundf(size.width*scale), roundf(size.height*scale)};
jens@0
    59
    NSImage *newImage = [[NSImage alloc] initWithSize: newSize];
jens@0
    60
    [newImage lockFocus];
jens@0
    61
    NSGraphicsContext *context = [NSGraphicsContext currentContext];
jens@0
    62
    [context saveGraphicsState];
jens@0
    63
    [context setImageInterpolation: NSImageInterpolationHigh];
jens@0
    64
    [self drawInRect: NSMakeRect(0,0,newSize.width,newSize.height)
jens@0
    65
            fromRect: NSMakeRect(0,0,size.width,size.height)
jens@0
    66
           operation: NSCompositeCopy fraction: 1.0f];
jens@0
    67
    [context restoreGraphicsState];
jens@0
    68
    [newImage unlockFocus];
jens@0
    69
    return [newImage autorelease];
jens@0
    70
}
jens@0
    71
jens@0
    72
jens@0
    73
- (NSData*) my_JPEGData
jens@0
    74
{
jens@2
    75
    return [self my_dataInFormat: NSJPEGFileType quality: 0.75f];
jens@2
    76
}
jens@2
    77
jens@2
    78
jens@2
    79
- (NSData*) my_dataInFormat: (NSBitmapImageFileType)format quality: (float)quality
jens@2
    80
{
jens@2
    81
    NSBitmapImageRep *rep = self.my_bitmapRep;
jens@0
    82
    NSDictionary *props = [NSDictionary dictionaryWithObjectsAndKeys:
jens@2
    83
                           [NSNumber numberWithFloat: quality], NSImageCompressionFactor, nil];
jens@2
    84
    return [rep representationUsingType: format properties: props];
jens@0
    85
}
jens@0
    86
jens@0
    87
jens@0
    88
#if 0
jens@0
    89
jens@0
    90
// Adapted from Apple's CocoaCreateMovie sample
jens@0
    91
// <http://developer.apple.com/samplecode/Sample_Code/QuickTime/Basics/CocoaCreateMovie/MyController.m.htm>
jens@0
    92
static void CopyNSImageRepToGWorld(NSBitmapImageRep *imageRepresentation, GWorldPtr gWorldPtr)
jens@0
    93
{
jens@0
    94
    PixMapHandle  pixMapHandle;
jens@0
    95
    unsigned char*   pixBaseAddr;
jens@0
    96
jens@0
    97
    // Lock the pixels
jens@0
    98
    pixMapHandle = GetGWorldPixMap(gWorldPtr);
jens@0
    99
    LockPixels (pixMapHandle);
jens@0
   100
    pixBaseAddr = (unsigned char*) GetPixBaseAddr(pixMapHandle);
jens@0
   101
jens@0
   102
    const unsigned char* bitMapDataPtr = [imageRepresentation bitmapData];
jens@0
   103
jens@0
   104
    if ((bitMapDataPtr != nil) && (pixBaseAddr != nil))
jens@0
   105
    {
jens@0
   106
        int i,j;
jens@0
   107
        int pixmapRowBytes = GetPixRowBytes(pixMapHandle);
jens@0
   108
        NSSize imageSize = [imageRepresentation size];
jens@0
   109
        for (i=0; i< imageSize.height; i++)
jens@0
   110
        {
jens@0
   111
            const unsigned char *src = bitMapDataPtr + i * [imageRepresentation bytesPerRow];
jens@0
   112
            unsigned char *dst = pixBaseAddr + i * pixmapRowBytes;
jens@0
   113
            for (j = 0; j < imageSize.width; j++)
jens@0
   114
            {
jens@0
   115
                *dst++ = 0;  // X - our src is 24-bit only
jens@0
   116
                *dst++ = *src++; // Red component
jens@0
   117
                *dst++ = *src++; // Green component
jens@0
   118
                *dst++ = *src++; // Blue component
jens@0
   119
            }
jens@0
   120
        }
jens@0
   121
    }
jens@0
   122
    UnlockPixels(pixMapHandle);
jens@0
   123
}
jens@0
   124
jens@0
   125
jens@0
   126
- (NSData*) my_PICTData
jens@0
   127
{
jens@0
   128
    // Locate the bitmap image rep:
jens@0
   129
    NSBitmapImageRep *rep;
jens@0
   130
    NSEnumerator *e = [[self representations] objectEnumerator];
jens@0
   131
    while( (rep=[e nextObject]) != nil ) {
jens@0
   132
        if( [rep isKindOfClass: [NSBitmapImageRep class]] )
jens@0
   133
            break;
jens@0
   134
    }
jens@0
   135
    if( ! rep ) {
jens@0
   136
        Warn(@"No bitmap image rep in image");
jens@0
   137
        return nil;
jens@0
   138
    }
jens@0
   139
jens@0
   140
    // Copy the image data into a GWorld:
jens@0
   141
    Rect bounds;
jens@0
   142
    SetRect(&bounds, 0,0,[rep pixelsWide],[rep pixelsHigh]);    
jens@0
   143
    GWorldPtr gworld;
jens@0
   144
    OSStatus err = NewGWorld(&gworld, 32, &bounds, NULL, NULL, 0);
jens@0
   145
    if( err ) {
jens@0
   146
        Warn(@"NewGWorld failed with err %i",err);
jens@0
   147
        return nil;
jens@0
   148
    }
jens@0
   149
    CopyNSImageRepToGWorld(rep,gworld);
jens@0
   150
jens@0
   151
    // Draw the GWorld into a PicHandle:
jens@0
   152
    CGrafPtr oldPort;
jens@0
   153
    GDHandle oldDevice;
jens@0
   154
    GetGWorld(&oldPort,&oldDevice);
jens@0
   155
    SetGWorld(gworld,NULL);
jens@0
   156
    ClipRect(&bounds);
jens@0
   157
    PicHandle pic = OpenPicture(&bounds);
jens@0
   158
    CopyBits(GetPortBitMapForCopyBits(gworld),
jens@0
   159
             GetPortBitMapForCopyBits(gworld),
jens@0
   160
             &bounds,&bounds,srcCopy,NULL);
jens@0
   161
    ClosePicture();
jens@0
   162
    err = QDError();
jens@0
   163
    SetGWorld(oldPort,oldDevice);
jens@0
   164
    DisposeGWorld(gworld);
jens@0
   165
    
jens@0
   166
    if( err ) {
jens@0
   167
        Warn(@"Couldn't convert to PICT: error %i",err);
jens@0
   168
        return nil;
jens@0
   169
    }
jens@0
   170
jens@0
   171
    // Copy the PicHandle into an NSData:
jens@0
   172
    HLock((Handle)pic);
jens@0
   173
    //Test to put PICT on clipboard:
jens@0
   174
    /*ScrapRef scrap;
jens@0
   175
    GetCurrentScrap(&scrap);
jens@0
   176
    ClearScrap(&scrap);
jens@0
   177
    PutScrapFlavor(scrap,'PICT',0,GetHandleSize((Handle)pic),*pic);*/
jens@0
   178
    NSData *data = [NSData dataWithBytes: *pic length: GetHandleSize((Handle)pic)];
jens@0
   179
    DisposeHandle((Handle)pic);
jens@0
   180
    Log(@"Converted image to %i bytes of PICT data",[data length]);
jens@0
   181
    return data;
jens@0
   182
}
jens@0
   183
#endif
jens@0
   184
jens@0
   185
jens@0
   186
@end
jens@0
   187
jens@0
   188
jens@0
   189
jens@0
   190
jens@0
   191
@implementation NSBezierPath (MYUtilities)
jens@0
   192
jens@0
   193
+ (NSBezierPath*) my_bezierPathWithRoundRect: (NSRect)rect radius: (float)radius
jens@0
   194
{
jens@0
   195
    radius = MIN(radius, floorf(rect.size.width/2));
jens@0
   196
    float x0 = NSMinX(rect), y0 = NSMinY(rect),
jens@0
   197
          x1 = NSMaxX(rect), y1 = NSMaxY(rect);
jens@0
   198
    NSBezierPath *path = [NSBezierPath bezierPath];
jens@0
   199
    
jens@0
   200
    [path moveToPoint: NSMakePoint(x0+radius,y0)];
jens@0
   201
    
jens@0
   202
    [path appendBezierPathWithArcFromPoint: NSMakePoint(x1,y0)
jens@0
   203
                                   toPoint: NSMakePoint(x1,y1) radius: radius];
jens@0
   204
    [path appendBezierPathWithArcFromPoint: NSMakePoint(x1,y1)
jens@0
   205
                                   toPoint: NSMakePoint(x0,y1) radius: radius];
jens@0
   206
    [path appendBezierPathWithArcFromPoint: NSMakePoint(x0,y1)
jens@0
   207
                                   toPoint: NSMakePoint(x0,y0) radius: radius];
jens@0
   208
    [path appendBezierPathWithArcFromPoint: NSMakePoint(x0,y0)
jens@0
   209
                                   toPoint: NSMakePoint(x1,y0) radius: radius];
jens@0
   210
    [path closePath];
jens@0
   211
    return path;
jens@0
   212
}
jens@0
   213
jens@0
   214
@end
jens@2
   215
jens@2
   216
jens@2
   217
jens@2
   218
NSArray* OpenWindowsWithDelegateClass( Class klass )
jens@2
   219
{
jens@2
   220
    NSMutableArray *windows = $marray();
jens@2
   221
    for( NSWindow *window in [NSApp windows] ) {
jens@2
   222
        id delegate = window.delegate;
jens@2
   223
        if( (window.isVisible || window.isMiniaturized) && [delegate isKindOfClass: klass] ) 
jens@2
   224
            [windows addObject: window];
jens@2
   225
    }
jens@2
   226
    return windows;
jens@2
   227
}    
jens@2
   228
jens@2
   229
jens@2
   230
jens@2
   231
NSRect PinRect( NSRect r, NSRect container )
jens@2
   232
{
jens@2
   233
    // Push r's origin inside container, and limit its size to the container's:
jens@2
   234
    r = NSMakeRect(MAX(r.origin.x, container.origin.x),
jens@2
   235
                   MAX(r.origin.y, container.origin.y),
jens@2
   236
                   MIN(r.size.width, container.size.width),
jens@2
   237
                   MIN(r.size.height, container.size.height));
jens@2
   238
    // Push r's outside edges into the container:
jens@2
   239
    r.origin.x -= MAX(0, NSMaxX(r)-NSMaxX(container));
jens@2
   240
    r.origin.y -= MAX(0, NSMaxY(r)-NSMaxY(container));
jens@2
   241
    return r;
jens@2
   242
    
jens@2
   243
}