Domanda

I have a class that draws images. It is instantiated multiple times, for multiple image sources, and it is possible to have a number of these objects up at one time; each getting a feed that is interrupt-driven (from USB devices).

Part of the function of the class, is to annotate the images fed in, so there is a routine that does some standard Core Graphics stuff to add the annotation.

I do this via a bitmap context, where I first draw the image, then add the annotations to it, using standard CGContext stuff.

The problem is that, when I do this, the images from multiple sources step all over each other. It looks like an established context; even when a bitmap context, is not thread-safe. However, I added NSLock, and that did not solve the issue, so it may not just be an issue of thread safety.

Here is a much simplified version of the routine:

- (CGImageRef)createCopiedImage:(CGImageRef)inImage
{
    CGImageRef  ret = nil;

    CGRect  imageRect = CGRectMake ( 0, 0, CGImageGetWidth ( ret ), CGImageGetHeight ( ret ) );
    size_t  rowBytes = imageRect.size.width * 4;
    size_t  bufferLen = rowBytes * imageRect.size.height;
    void    *buffer = malloc ( bufferLen );

    if ( buffer )
    {
        CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName ( kCGColorSpaceGenericRGB );

        if ( colorSpace )
        {
        CGContextRef    drawingContext = CGBitmapContextCreate ( buffer, imageRect.size.width, imageRect.size.height, 8, rowBytes, colorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedFirst );

        if ( drawingContext )
        {
            CGContextDrawImage ( drawingContext, imageRect, inImage );

            CFRelease ( backGroundImage );


            // DO ANNOTATION STUFF HERE

            CGDataProviderRef dataProvider = CGDataProviderCreateWithData ( NULL, buffer, rowBytes * imageRect.size.height, NULL );

            if ( dataProvider )
            {
                CGImageRef  ret = CGImageCreate ( imageRect.size.width, imageRect.size.height, 8, 32, rowBytes, colorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedFirst, dataProvider, NULL, false, kCGRenderingIntentDefault );

                CGDataProviderRelease ( dataProvider) ;
            }

            CGContextRelease ( drawingContext );
        }

    free ( buffer );
    }

    return ret;
}

Any ideas about how I can avoid these instances stepping on each other?

È stato utile?

Soluzione

Not withstanding the memory leak, you should be able to let the system handle the memory allocation for you and just use the newly created drawing to copy out the CGImageRef:

@implementation YourClass

- (CGImageRef)createCopiedImage:(CGImageRef)inImage
{
    CGImageRef  ret = NULL;

    CGRect  imageRect = CGRectMake ( 0, 0, CGImageGetWidth ( ret ), CGImageGetHeight ( ret ) );
    size_t  rowBytes = imageRect.size.width * 4;
    size_t  bufferLen = rowBytes * imageRect.size.height;

    CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName ( kCGColorSpaceGenericRGB );

    if ( colorSpace )
    {
        CGContextRef drawingContext = CGBitmapContextCreate ( NULL, imageRect.size.width, imageRect.size.height, 8, rowBytes, colorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedFirst );

        if ( drawingContext )
        {
            CGContextDrawImage ( drawingContext, imageRect, inImage );

            CFRelease ( backGroundImage );

            // DO ANNOTATION STUFF HERE

            // Copy image out
            ret = CGBitmapContextCreateImage(drawingContext);

            CGContextRelease ( drawingContext );
        }
    }

    return ret;
}

@end
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top