Unpredictable segfault occurring during resizing of images for export

23 views
Skip to first unread message

Chris Williams

unread,
Feb 25, 2011, 12:02:36 AM2/25/11
to apertu...@lists.apple.com
Hi everyone,

I've been developing a plugin for Aperture that resizes the exported images to a maximum longest edge of 1280px, before sending them off to an FTP server, and I've come across an unusual segfault during the resizing phase.

Initially the segfault occured when processing a RAW (.RW2) image (although others had previously exported fine).

Thinking the problem was due to RAW image files in particular, I removed them from my export list and then tried again. Again a segfault resulted when processing a JPG file.

Both errors seem to be related to CGColorSpace, and occur during a CGImageSourceCreateImageAtInde
x call. My next thought was corrupt images, but the same image will export fine one time and not the next.
It's not consistent when and where it happens, and has only been apparent on largish exports (400+) images and so my guess is that must be doing something wrong with memory management somewhere.

If anyone has a clue on what is happening here, or has seen this before, any help would be greatly appreciated!

Best regards,

Chris.

Stack trace on RAW file:
====================
Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: 0x000000000000000d, 0x0000000000000000
Crashed Thread:  14

<snip>

Thread 14 Crashed:
0   com.apple.CoreGraphics            0x00007fff868cc88a CGColorSpaceGetType + 18
1   com.apple.ImageIO.framework       0x00007fff88f12936 CGImagePlusSetGeometry + 564
2   com.apple.ImageIO.framework       0x00007fff88f126e7 CGImagePluginSetImageBlockProc + 168
3   com.apple.RawCamera.bundle        0x00007fff83d371b4 GetRawPluginsInfo + 138788
4   com.apple.RawCamera.bundle        0x00007fff83d386a1 GetRawPluginsInfo + 144145
5   com.apple.RawCamera.bundle        0x00007fff83d3e6f9 GetRawPluginsInfo + 168809
6   com.apple.RawCamera.bundle        0x00007fff83d35557 GetRawPluginsInfo + 131527
7   com.apple.ImageIO.framework       0x00007fff88f10124 makeImagePlus + 511
8   com.apple.ImageIO.framework       0x00007fff88f145ec CGImageSourceCreateImageAtIndex + 216
9   ...taproofs.export.Instaproofs    0x0000000125559b64 -[Instaproofs exportManagerShouldWriteImageData:toRelativePath:forImageAtIndex:] + 163
10  com.apple.Aperture                0x000000010059c257 0x100000000 + 5882455
11  com.apple.Aperture                0x000000010021574b 0x100000000 + 2185035
12  com.apple.proxtcore               0x00000001015c3328 0x1015be000 + 21288
13  com.apple.proxtcore               0x00000001015c2c70 0x1015be000 + 19568
14  com.apple.proxtcore               0x00000001015c1726 0x1015be000 + 14118
15  com.apple.Foundation              0x00007fff8473c0a5 __NSThread__main__ + 1429
16  libSystem.B.dylib                 0x00007fff85328536 _pthread_start + 331
17  libSystem.B.dylib                 0x00007fff853283e9 thread_start + 13


Stack trace on JPG file
=========================================================
Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000000850ff685
Crashed Thread:  14

Application Specific Information:
objc_msgSend() selector name: retain

<snip>

Thread 14 Crashed:
0   libobjc.A.dylib                   0x934b6eec objc_msgSend + 44
1   com.apple.CoreGraphics            0x920ab2f7 CGColorSpaceRetain + 22
2   com.apple.CoreGraphics            0x920aae42 CGColorSpaceCreateWithIndex + 762
3   com.apple.ImageIO.framework       0x92ea8a41 initImageJPEG + 4982
4   com.apple.ImageIO.framework       0x92ea76c1 _CGImagePluginInitJPEG + 69
5   com.apple.ImageIO.framework       0x92e8f6fd makeImagePlus + 715
6   com.apple.ImageIO.framework       0x92e95c0a CGImageSourceCreateImageAtIndex + 176
7   ...taproofs.export.Instaproofs    0x1f54cff8 -[Instaproofs exportManagerShouldWriteImageData:toRelativePath:forImageAtIndex:] + 167
8   com.apple.Aperture                0x00554a92 0x1000 + 5585554
9   com.apple.Aperture                0x001f7002 0x1000 + 2056194
10  com.apple.proxtcore               0x0125e5b3 0x1258000 + 26035
11  com.apple.proxtcore               0x0125ddb6 0x1258000 + 23990
12  com.apple.proxtcore               0x0125d831 0x1258000 + 22577
13  com.apple.proxtcore               0x0125bf46 0x1258000 + 16198
14  com.apple.Foundation              0x909d6bf0 -[NSThread main] + 45
15  com.apple.Foundation              0x909d6ba0 __NSThread__main__ + 1499
16  libSystem.B.dylib                 0x95be285d _pthread_start + 345
17  libSystem.B.dylib                 0x95be26e2 thread_start + 34



Chris Williams

unread,
Feb 25, 2011, 12:10:40 AM2/25/11
to apertu...@lists.apple.com
...and here is the code for exportManagerShouldWriteImageData:

- (BOOL)exportManagerShouldWriteImageData:(NSData *)imageData
toRelativePath:(NSString *)path forImageAtIndex:(unsigned)index
{
    NSUInteger              width, height;
    NSUInteger                longestEdge;
    double                    scaleFactor;
    BOOL                    longestEdgeIsWidth;
    NSString *resizedImagePath = [path copy];
    NSLog(@"Examining: %@", resizedImagePath);
    CGImageRef resizedImageRef = NULL;

    CFURLRef baseURLRef =
CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
(CFStringRef)_exportPath, kCFURLPOSIXPathStyle, true);

    // Create our full size CGImage from the provided data
    CGImageSourceRef imageSourceRef =
CGImageSourceCreateWithData((CFDataRef)imageData, NULL);
    if (imageSourceRef != NULL) {
    CGImageRef fullSizeImageRef =
CGImageSourceCreateImageAtIndex(imageSourceRef, 0, NULL);
    CFRelease(imageSourceRef);
    CGContextRef context = NULL;

        width = CGImageGetWidth(fullSizeImageRef);
        height = CGImageGetHeight(fullSizeImageRef);
        if (width > height) {
            longestEdge = width;
            longestEdgeIsWidth = YES;
        }
        else {
            longestEdge = height;
            longestEdgeIsWidth=NO;
        }
        if (longestEdge >1280) {
            NSLog(@" and resizing....");
            scaleFactor = 1280.0/longestEdge;

            NSUInteger newWidth = round(width*scaleFactor);
            NSUInteger newHeight = round(height*scaleFactor);
            CGColorSpaceRef colorspace = CGImageGetColorSpace(fullSizeImageRef);
            void *          bitmapData;
            int bitmapBytesPerRow   = (newWidth * 4);
            int bitmapByteCount     = (bitmapBytesPerRow * newHeight);
            bitmapData = malloc( bitmapByteCount );

            context = CGBitmapContextCreate(bitmapData, newWidth,
newHeight, 8,bitmapBytesPerRow, colorspace,
kCGImageAlphaNoneSkipFirst);

            CGContextDrawImage(context, CGRectMake(0, 0, newWidth,
newHeight), fullSizeImageRef);
            resizedImageRef= CGBitmapContextCreateImage(context);
            CFRelease(fullSizeImageRef);

            CFRelease(colorspace);
            CFRelease(context);
            free(bitmapData);


        }
    else {
        //Image is within requirements, simply use a copy.
        resizedImageRef = CGImageCreateCopy(fullSizeImageRef);
        CFRelease(fullSizeImageRef);
    }


    resizedImagePath = [resizedImagePath stringByDeletingPathExtension];
    resizedImagePath = [resizedImagePath stringByAppendingPathExtension:@"jpg"];
    NSDictionary* image_dict = [_exportManager propertiesForImageAtIndex:index];
    NSString* project_name = [[image_dict
objectForKey:kExportKeyProjectName] retain];

    CFURLRef resizedFileURLRef =
CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorDefault,
(CFStringRef)resizedImagePath, kCFURLPOSIXPathStyle, false,
baseURLRef);

    CGImageDestinationRef imageDestinationRef =
CGImageDestinationCreateWithURL(resizedFileURLRef, kUTTypeJPEG, 1,
NULL);
    NSMutableDictionary *imageProperties = [[NSMutableDictionary alloc] init];
    [imageProperties setObject:[NSNumber numberWithInt:1]
forKey:(NSString *)kCGImageDestinationLossyCompressionQuality];
    CGImageDestinationAddImage(imageDestinationRef, resizedImageRef,
(CFDictionaryRef) imageProperties);
    CGImageDestinationFinalize(imageDestinationRef);
    CFRelease(imageDestinationRef);
        [imageProperties release];
    CFRelease(resizedImageRef);

    NSNumber *fileSize = [self sizeOfFileAtPath:(NSURL*) resizedFileURLRef];
    NSString* fileRefString = [self fileSystemStringOfPath:(NSURL
*)resizedFileURLRef];
    CFRelease(resizedFileURLRef);
    CFRelease(baseURLRef);
    totalBytes += [fileSize longValue];


    // Increment the current progress
    [self lockProgress];
    exportProgress.currentValue++;
        [self unlockProgress];}

    return NO;
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Aperture-dev mailing list (Apertu...@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/aperture-dev/aperture-dev%2Bgarchive-9674%40googlegroups.com

This email sent to aperture-dev+...@googlegroups.com

Clarence Locke

unread,
Feb 25, 2011, 2:17:52 AM2/25/11
to Chris Williams, apertu...@lists.apple.com
Chris,

The CGImageGetColorSpace() function does not follow the Create Rule <http://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html>, so you should _not_ be calling CFRelease(colorSpace) — you've over-released the object.

> http://lists.apple.com/mailman/options/aperture-dev/clarence%40blueroomsoftware.com
>
> This email sent to clar...@blueroomsoftware.com

Chris Williams

unread,
Feb 25, 2011, 2:31:55 AM2/25/11
to apertu...@lists.apple.com
Hi Clarence,

You're a lifesaver :) Thank you so much! That seems to have fixed it.

Best regards,

Chris.

Reply all
Reply to author
Forward
0 new messages