CIImage zu NSImage Konvertierung LEAKs (ARC)

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • CIImage zu NSImage Konvertierung LEAKs (ARC)

    Hallo,
    Versuche seit Tagen auf einen NSImage CIfilter anzusetzen. Leider kriege ich da immer Leaks.
    Eigentlich eine simple Sache die an sich funktioniert aber es leakt und leakt…..


    Es sieht etwa so aus :



    Quellcode

    1. -(NSImage*)setBlurforImage:(NSImage*)image blur:(CGFloat)blur {
    2. // NSImage => CIImage
    3. CIImage * inputImage = [[CIImage alloc] initWithData:[image TIFFRepresentation]];
    4. NSSize imageSize = [inputImage extent].size;
    5. // 2. CIFilter
    6. CIFilter * filter = [CIFilter filterWithName:@"CIGaussianBlur"];
    7. [filter setValue:inputImage forKey:kCIInputImageKey];
    8. [filter setValue:@(blur) forKey:kCIInputRadiusKey];
    9. CIImage * outputImage = [filter valueForKey:kCIOutputImageKey];
    10. // CIImage => NSImage
    11. NSImage * finalImage = [[NSImage alloc] initWithSize:imageSize];
    12. [finalImage lockFocus];
    13. [outputImage drawAtPoint:NSZeroPoint fromRect:(NSRect){NSZeroPoint, imageSize} operation:NSCompositeSourceOver fraction:1];// LEACK !!!!!
    14. [finalImage unlockFocus];
    15. return finalImage;
    16. }
    Alles anzeigen



    Habe es noch weiter vereinfacht um die Leak-Stelle einzugrenzen.




    Quellcode

    1. -(NSImage*)setBlurforImage:(NSImage*)image blur:(CGFloat)blur {
    2. // NSImage => CIImage
    3. CIImage * inputImage = [[CIImage alloc] initWithData:[image TIFFRepresentation]];
    4. NSSize imageSize = [inputImage extent].size;
    5. // 2. CIFilter
    6. // CIFilter * filter = [CIFilter filterWithName:@"CIGaussianBlur"];
    7. // [filter setValue:inputImage forKey:kCIInputImageKey];
    8. // [filter setValue:@(blur) forKey:kCIInputRadiusKey];
    9. // CIImage * outputImage = [filter valueForKey:kCIOutputImageKey];
    10. // CIImage => NSImage
    11. NSImage * finalImage = [[NSImage alloc] initWithSize:imageSize];
    12. [finalImage lockFocus];
    13. [inputImage drawAtPoint:NSZeroPoint fromRect:(NSRect){NSZeroPoint, imageSize} operation:NSCompositeSourceOver fraction:1];// LEACK !!!!!
    14. [finalImage unlockFocus];
    15. return finalImage;
    16. }
    Alles anzeigen

    Es liegt definitiv an der CIImage zu NSImage Umwandlung.

    Ist das eine geistige Umnachtung meinerseits oder reite ich einen toten Pferd?

    Werde für jeden Rat dankbar.

    marek.
  • elwieleiser schrieb:

    Ist das eine geistige Umnachtung meinerseits oder reite ich einen toten Pferd?
    Apples Code ist nicht 100% leakfrei. Mit manchen „Leaks“ muss man leben. ;)

    Entscheidend ist die Frage, ob das ein harmloser oder ein böser Leak ist. Er ist harmlos, wenn er nur einmal auftritt, und entsprechend böse, wenn bei jedem Aufruf der Methode neuer Speicher ausläuft. Um das herauszufinden, solltest du die Methode mehrmals in Instruments ausführen und dabei die Leaks beobachten.
    „Meine Komplikation hatte eine Komplikation.“
  • Hallo macmoonshine,
    danke für die Antwort.

    In meiner Anwendung wird die Methode oft aufgerufen was auch entsprechende menge an auslaufeden Zug ausmacht. Also es ist ein seeehr Böses.

    Versuche ich die Umwandlung mit NSCIImageRep zu bewerkstelligen :


    Quellcode

    1. ......
    2. NSImage *finalImage = [[NSImage alloc] initWithSize:[outputImage extent].size];
    3. NSCIImageRep *rep = [NSCIImageRep imageRepWithCIImage:outputImage];
    4. [finalImage addRepresentation:rep];
    5. return finalImage;

    wird die Methode schön „sauber“, es läuft aber auf anderen Stellen der Anwendung aus, und zwar da wo es die drawReckt bzw. drawAtPoint durchgeführt werden.

    marek
  • Hallo volker,
    danke für die Antwort.

    Versuche ich die Umwandlung mit NSCIImageRep (wie bei dem Link), leakt es an anderen Stellen der Anwendung, und zwar da wo es die drawReckt bzw. drawAtPoint (wie vorher bei der Methode) durchgeführt werden.


    Der NSImage wird in dem View dann gezeichnet nach dem er noch (zum Teil mehrmals) modifiziert wird .

    marek
  • Moin Marek,


    habe meine Quellen zu letzt vor zwei Jahren auf Leaks getestet, kann gerade nur das Binary testen. Ich habe nen Filter baum mit einigen Effekten und male dann das Ergebnis direkt in den NSView. Wenn ich meine App auf 10.10 (da sitze ich grade dran) mit Instruments auf leaks teste, dann bekomme ich 4 Stück im Radeon Treiber . Dazu musste ich durch schnelles Scrollen ca. 400 mal malen :| Sprich, war gar nicht leicht ;) Kannst Du es eingrenzen? Meine Quellen sind leider nicht so schnell ins passende Format fürs Forum gebracht um das mal als Vergleich ranzuziehen ...

    Ich zeichne das Bild über einen CIContext den ich mir aus dem aktuellen NSContext in der drawRect einer NSView Klasse hole. Also grob so:


    Quellcode

    1. CIContext *ciContext = [[NSGraphicsContext currentContext] CIContext];
    2. if(ciContext == nil)
    3. {
    4. NSLog(@"The CIContext of the window could not be accessed. Bailing out of the image creation process.");
    5. return;
    6. }
    7. int wS = WAVESPACE;
    8. if (delegate.isCreatingImageFromVisible) {
    9. CGContextRef cgContext = [[NSGraphicsContext currentContext] graphicsPort];
    10. [delegate getImageFrom:NSMinX(myRect) size:&sizeTo];
    11. CGRect cg = CGRectMake(NSMinX(myRect), 0+wS, sizeTo, NSHeight(rect));
    12. CGRect imgRect = CGRectMake(0, NSMinY(rect), sizeTo, NSHeight(rect));
    13. [[NSColor whiteColor] setFill];
    14. NSRectFill(rect);
    15. [[NSColor blackColor] setFill];
    16. CGContextTranslateCTM(cgContext,-myRect.origin.x,0);
    17. [ciContext drawImage:[delegate resultImage] atPoint: cg.origin fromRect: imgRect];
    18. }
    19. und noch mehr....
    Alles anzeigen
    Das delegate.resultImage ist dabei mein CIImage, wie es am Ende der Filterkette aufläuft.

    Grüße,
    Volker
  • Hi Volker,
    danke für Deine Infos.

    Habe viel hin und her getestet, mehrere Male auf dem Zahnfleisch gekrochen und auf die Decke gegangen.
    Das mit dem direkten in View zeichnen (draw’en) wird glaube ich nicht gehen. Dazu müßte ich den ganzen Project umschreiben und sogar wenn es dazu käme, würde es noch unübersichtlicher als es schon ohne hin ist. Dazu muss ich glaube ich erklären, dass ich eine Art des Grafikgenerators (Kunst) erstelle der hunderte (mindestens) Bildmaterialien (externe (meinst pdf) und selbst-generierte) kombiniert.

    Daher werde ich gerne in der Lage sei, manche Gruppen von Bild-Material modifiziert zu einem MSImage zusammenzufügen bevor ich diesen unter Angabe von Positionsparameter und Reihenfolge in der Tiefenstruktur auf den View „werfe“. So ein Konzept erleichtert mir ungemein die Handhabung.
    Ich habe noch die Hoffnung, dass es doch irgendwie möglich sein muss, ein CIImage in ein NSImage umzuwandeln ohne das es auf anderen Stellen des Programms Katastrophen verursacht.

    Lasse ich zum Test der Methode einfach das NSImage returnen den sie einnimmt, ist bei Instrumenten alles grün, wandle ich für den CIFilter das NSImage zu CIImage und wieder zurück, Leakt es bei jedem drawReckt bzw. drawAtPoint im weiterem Verlauf ohne Ende. ||

    Am Rande:

    Quellcode

    1. // [ciContext drawImage:[delegate resultImage] atPoint: cg.origin fromRect: imgRect]; // deprecated 10.8
    2. // [ciContext drawImage:[delegate resultImage] inRect:someRect fromRect:someRect];



    Gruß

    marek.