Search code examples
cocoapluginsphotoshoppreview

Photoshop Plugin using Cocoa - How to get a preview


I'm implementing a Photoshop plugin on the Mac, and I'm doing it using Cocoa. Doing ok so far, but the next step is to provide a "preview" image, as a part of my plugin window, and I'm stuck. I'm a n00b Obj-C programmer, which isn't really helping :-)

So far I've got something like this:

int dataSize = gFilterRecord->bigDocumentData->wholeSize32.v *
               gFilterRecord->bigDocumentData->wholeSize32.h *
               gFilterRecord->planes; 

NSData *inData = [[NSData alloc] initWithBytesNoCopy:gFilterRecord->inData length:dataSize freeWhenDone:NO];
NSLog(@"LoadImageFromSDK : Data created");
NSImage *imageTmp = [[NSImage alloc] initWithData:inData];
NSLog(@"LoadImageFromSDK : Image created");

//Save to PNG file as a test of this image creation
[[imageTmp TIFFRepresentation] writeToFile:@"/tmp/imageTmp.tif" atomically:YES];
NSLog(@"LoadImageFromSDK : Wrote image to disk");

At the moment, it crashes horribly on:
09/07/22 10:23:32 AM Adobe Photoshop Elements[46628] *** NSCopyMemoryPages(0x0, 0x245f4000, 2265088) failed

I'm probably calculating the size of inData incorrectly. Help?

Also, is NSImage going to be able to interpret that image data blob correctly? Or should I give it up and just do a pixel-by-pixel mapping into the NSImage?


Solution

  • Ok, that was way more painful to figure out than I had anticipated. Also, kudos to NVidia for posting this PDF which is a better explanation of the Photoshop SDK filter record than the actual SDK docs.

    This code actually reads the inData and produces a usable NSImage (lots of logging just to figure out what it is doing, feel free to remove) in addition to the sample tif file for debugging purposes.

    NSLog(@"Entering LoadImageFromSDK");
    
    unsigned char *bitmapPlanes[4];    
    bitmapPlanes[0] = (unsigned char *) (gFilterRecord->inData);
    
    NSLog(@"Params to create bitmap");
    NSLog(@"pixelsWide = %d", gFilterRecord->bigDocumentData->imageSize32.h );
    NSLog(@"pixelsHigh = %d", gFilterRecord->bigDocumentData->imageSize32.v );
    NSLog(@"bitsPerSample = %d", gFilterRecord->depth );
    NSLog(@"samplesPerPixel = %d", gFilterRecord->planes );
    NSLog(@"hasAlpha = %d", NO );
    NSLog(@"isPlanar = %d", NO );
    NSLog(@"colorSpaceName = %@", mapImageModeToColorSpace(gFilterRecord->imageMode) );
    NSLog(@"bytesPerRow = %d", gFilterRecord->inRowBytes );
    NSLog(@"bitsPerPixel = %d", gFilterRecord->depth*gFilterRecord->planes );    
    
    NSBitmapImageRep *bitmapTmp = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:bitmapPlanes
                                                                          pixelsWide:gFilterRecord->bigDocumentData->imageSize32.h
                                                                          pixelsHigh:gFilterRecord->bigDocumentData->imageSize32.v
                                                                       bitsPerSample:gFilterRecord->depth
                                                                     samplesPerPixel:gFilterRecord->planes
                                                                            hasAlpha:NO 
                                                                            isPlanar:NO 
                                                                      colorSpaceName:mapImageModeToColorSpace(gFilterRecord->imageMode) 
                                                                         bytesPerRow:gFilterRecord->inRowBytes
                                                                        bitsPerPixel:gFilterRecord->depth*gFilterRecord->planes];
    
    NSLog(@"LoadImageFromSDK : Bitmap created = %@", bitmapTmp);
    
    [[bitmapTmp TIFFRepresentation] writeToFile:@"/Users/someuser/temp/sample.tif" atomically:YES];
    
    
    NSImage *imageTmp = [[NSImage alloc] initWithSize:[bitmapTmp size]];
    [imageTmp addRepresentation:bitmapTmp];
    NSLog(@"LoadImageFromSDK : Image created = %@", imageTmp);