CIImage drawAtPoint: ...... retains image??

  • I'm trying to draw a CIImage in a view, but have come across the
    following problem:

    CIImage *drawImage;
    .......
    NSLog(@"draw image retain count: %d", [drawImage retainCount]);
    [drawImage drawAtPoint:drawPoint fromRect:drawRect
    operation:NSCompositeSourceOver fraction:1.0];
    NSLog(@"draw image retain count: %d", [drawImage retainCount]);

    NSLog output:
    draw image retain count: 1
    draw image retain count: 2

    after the drawing operation, the retain count of the image is 1
    greater than before the drawing call. From what I understand about
    memory management... that shouldn't happen?? This is causing massive
    leaks in my program.

    Any ideas?

    Cheers
    Nik
  • On 14 Dec 07, at 23:10, Nik Youdale wrote:
    > I'm trying to draw a CIImage in a view, but have come across the
    > following problem:
    >
    > CIImage *drawImage;
    > .......
    > NSLog(@"draw image retain count: %d", [drawImage retainCount]);
    > [drawImage drawAtPoint:drawPoint fromRect:drawRect
    > operation:NSCompositeSourceOver fraction:1.0];
    > NSLog(@"draw image retain count: %d", [drawImage retainCount]);
    >
    > NSLog output:
    > draw image retain count: 1
    > draw image retain count: 2
    >
    > after the drawing operation, the retain count of the image is 1
    > greater than before the drawing call. From what I understand about
    > memory management... that shouldn't happen?? This is causing massive
    > leaks in my program.

    Short version: retainCount is a false idol. Don't worship it.

    Longer version: Some AppKit routines might be temporarily retaining
    objects "behind your back". For example, I wouldn't be surprised if
    drawAtPoint were temporarily retaining the image until you finish
    drawing. This shouldn't affect your application's overall memory
    mangement, although it will make retainCount do unexpected things. The
    immediate solution is simply to not look at retainCount, as features
    such as autorelease will make it deliver results that aren't
    particularly meaningful.

    On to more permanent solutions - have you actually run MallocDebug or
    any other tools to actually look at where memory is going? In
    particular, are you sure you're appropriately managing the lifecycle
    of drawImage?
  • I see - thanks for the explanation on retain count - it makes sense.

    I'm using 'Instruments' (previously known as XRay - why did they
    change the name?....) with the object alloc tool, and it appears that
    most memory is being used by QuartzCore in a massive tree of calls
    going something like "fe_tree_create_texture > fe_texture_new >
    texture_retain > blah blah blah".

    Disabling the drawAtPoint: call clears up the memory leaks.

    So it appears that its a whole bunch of functions within QuartzCore
    and CoreGraphics causing the issue - of course appearances can be
    deceiving.

    What is the best way to be certain that I'm releasing drawImage
    properly? I've looked through the code and made sure every retain is
    balanced by a release, so i'm fairly certain that it is being released.

    Thanks,
    Nik

    On 15/12/2007, at 6:19 PM, Andrew Farmer wrote:

    > On 14 Dec 07, at 23:10, Nik Youdale wrote:
    >> I'm trying to draw a CIImage in a view, but have come across the
    >> following problem:
    >>
    >> CIImage *drawImage;
    >> .......
    >> NSLog(@"draw image retain count: %d", [drawImage retainCount]);
    >> [drawImage drawAtPoint:drawPoint fromRect:drawRect
    >> operation:NSCompositeSourceOver fraction:1.0];
    >> NSLog(@"draw image retain count: %d", [drawImage retainCount]);
    >>
    >> NSLog output:
    >> draw image retain count: 1
    >> draw image retain count: 2
    >>
    >> after the drawing operation, the retain count of the image is 1
    >> greater than before the drawing call. From what I understand about
    >> memory management... that shouldn't happen?? This is causing
    >> massive leaks in my program.
    >
    > Short version: retainCount is a false idol. Don't worship it.
    >
    > Longer version: Some AppKit routines might be temporarily retaining
    > objects "behind your back". For example, I wouldn't be surprised if
    > drawAtPoint were temporarily retaining the image until you finish
    > drawing. This shouldn't affect your application's overall memory
    > mangement, although it will make retainCount do unexpected things.
    > The immediate solution is simply to not look at retainCount, as
    > features such as autorelease will make it deliver results that
    > aren't particularly meaningful.
    >
    > On to more permanent solutions - have you actually run MallocDebug
    > or any other tools to actually look at where memory is going? In
    > particular, are you sure you're appropriately managing the lifecycle
    > of drawImage?
  • On Dec 15, 2007, at 08:36, Nik Youdale wrote:

    > I see - thanks for the explanation on retain count - it makes sense.
    >
    > I'm using 'Instruments' (previously known as XRay - why did they
    > change the name?....) with the object alloc tool, and it appears
    > that most memory is being used by QuartzCore in a massive tree of
    > calls going something like "fe_tree_create_texture > fe_texture_new
    >> texture_retain > blah blah blah".
    >
    > Disabling the drawAtPoint: call clears up the memory leaks.
    >
    > So it appears that its a whole bunch of functions within QuartzCore
    > and CoreGraphics causing the issue - of course appearances can be
    > deceiving.

    I'm seeing the same issue in my program. As soon as I try to render
    the CIImage somehow (to my view or offscreen), the whole image leaks.
    Since I'm drawing fullscreen images regularly, my application leaks
    60MB of RAM per cycle (verified using Instruments). The memory is
    never freed in any way, it just builds up.
    I haven't found a solution yet, even though I spent a whole day trying
    different ways to get the pixels out of the CIImage (all of them
    leaking). I'm thinking about scrapping CIImage altogether and re-
    implementing all CoreImage filters I'm using using direct OpenGL calls
    and some shaders. That's much more work, but at least I can fix those
    leaks that way.

    andy
  • Yeah its terribly frustrating. I've spent hours trying to debug
    this..... :-(

    After some more experimentation, ive found that the leak only occurs
    when the image is actually visible on screen and being drawn. If you
    try and draw the image in a view at a location where the image won't
    be visible on screen - no leak. But as soon as the smallest corner of
    the image is visible, my app starts leaking - depending on how far i
    push it, 1.... 2GB...

    I've tried calling the CIContext clearCaches, and reclaimResources,
    but they appear to do nothing. I've tried releasing all my CImages
    (relatively minor change in mem usage - nothing significant), manually
    deallocing images (larger regain in memory, but then nothing works
    anymore, of course).

    I must admit that I'm not an expert on using malloc debug, or
    instruments, but from what I can figure out the leak appears to be
    somewhere in core image itself...... I did a bit of googling and
    found: http://www.pcpro.co.uk/macuser/news/142938/pixelmator-uncovers-core-image-m
    emory-leak.html

    - Don't know where abouts that leak is.... but I have a feeling it
    might be related? Anybody know?

    - Nik

    On 15/12/2007, at 10:44 PM, Andreas Monitzer wrote:
    >
    > I'm seeing the same issue in my program. As soon as I try to render
    > the CIImage somehow (to my view or offscreen), the whole image
    > leaks. Since I'm drawing fullscreen images regularly, my application
    > leaks 60MB of RAM per cycle (verified using Instruments). The memory
    > is never freed in any way, it just builds up.
    > I haven't found a solution yet, even though I spent a whole day
    > trying different ways to get the pixels out of the CIImage (all of
    > them leaking). I'm thinking about scrapping CIImage altogether and
    > re-implementing all CoreImage filters I'm using using direct OpenGL
    > calls and some shaders. That's much more work, but at least I can
    > fix those leaks that way.
    >
    > andy
    >
  • On 15/12/2007, at 10:44 PM, Andreas Monitzer wrote:

    > I'm seeing the same issue in my program. As soon as I try to render
    > the CIImage somehow (to my view or offscreen), the whole image
    > leaks. Since I'm drawing fullscreen images regularly, my application
    > leaks 60MB of RAM per cycle (verified using Instruments). The memory
    > is never freed in any way, it just builds up.
    > I haven't found a solution yet, even though I spent a whole day
    > trying different ways to get the pixels out of the CIImage (all of
    > them leaking). I'm thinking about scrapping CIImage altogether and
    > re-implementing all CoreImage filters I'm using using direct OpenGL
    > calls and some shaders. That's much more work, but at least I can
    > fix those leaks that way.

    I had this exact problem and it seems to occur if you are drawing to a
    context that is not on-screen. I was leaking HUGE amounts of memory
    until I found a fix.

    I used this workaround which renders the CIImage to the context of the
    application's main window (you can use any on-screen context) and
    grabs a CGImageRef which is then drawn to the current context:

    //outputImage is the CIImage you want to draw

    CIContext *ciContext = [[[NSApp mainWindow] graphicsContext] CIContext];

    //render the CIIimage into a CGImageRef in the on-screen context
    CGImageRef cgImage = [ciContext createCGImage:outputImage fromRect:
    [outputImage extent]];

    // Draw the CGImageRef into the current context
    if (cgImage != NULL)
    {
    CGContextDrawImage ([[NSGraphicsContext currentContext]
    graphicsPort], [outputImage extent], cgImage);
    CGImageRelease (cgImage);
    }

    This eliminates the problem for me.

    --
    Rob Keniger
  • Hey,

    This is a known bug and has been for some time. Please file another
    bug report, preferably with example source code and maybe you'll be
    the one who convinces them to fix this.

    </rant>

    Chris

    On 15 Dec 2007, at 07:10, Nik Youdale <youdalen...> wrote:

    > I'm trying to draw a CIImage in a view, but have come across the
    > following problem:
    >
    > CIImage *drawImage;
    > .......
    > NSLog(@"draw image retain count: %d", [drawImage retainCount]);
    > [drawImage drawAtPoint:drawPoint fromRect:drawRect
    > operation:NSCompositeSourceOver fraction:1.0];
    > NSLog(@"draw image retain count: %d", [drawImage retainCount]);
    >
    > NSLog output:
    > draw image retain count: 1
    > draw image retain count: 2
    >
    > after the drawing operation, the retain count of the image is 1
    > greater than before the drawing call. From what I understand about
    > memory management... that shouldn't happen?? This is causing massive
    > leaks in my program.
    >
    > Any ideas?
    >
    > Cheers
    > Nik
  • Thanks a lot for the tip - it works a treat! =]

    - Nik

    On 15/12/2007, at 11:07 PM, Rob Keniger wrote:
    > I had this exact problem and it seems to occur if you are drawing to
    > a context that is not on-screen. I was leaking HUGE amounts of
    > memory until I found a fix.
    >
    > I used this workaround which renders the CIImage to the context of
    > the application's main window (you can use any on-screen context)
    > and grabs a CGImageRef which is then drawn to the current context:
    >
    > //outputImage is the CIImage you want to draw
    >
    > CIContext *ciContext = [[[NSApp mainWindow] graphicsContext]
    > CIContext];
    >
    > //render the CIIimage into a CGImageRef in the on-screen context
    > CGImageRef cgImage = [ciContext createCGImage:outputImage fromRect:
    > [outputImage extent]];
    >
    > // Draw the CGImageRef into the current context
    > if (cgImage != NULL)
    > {
    > CGContextDrawImage ([[NSGraphicsContext currentContext]
    > graphicsPort], [outputImage extent], cgImage);
    > CGImageRelease (cgImage);
    > }
    >
    > This eliminates the problem for me.
    >
    > --
    > Rob Keniger
previous month december 2007 next month
MTWTFSS
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
Go to today