2013-04-18 7 views
6

jestem tworzenia NSImage z unsigned char * danych 24bit RGB tak:zarządzanie pamięcią Cocoa podczas korzystania initWithBitmapDataPlanes stworzyć NSImage

NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] 
          initWithBitmapDataPlanes:(unsigned char **)&data 
          pixelsWide:gWidth 
          pixelsHigh:gHeight 
          bitsPerSample:8 
          samplesPerPixel:3 
          hasAlpha:NO 
          isPlanar:NO 
          colorSpaceName:NSCalibratedRGBColorSpace 
          bytesPerRow:gWidth*3 
          bitsPerPixel:24]; 

NSImage *img = [[NSImage alloc] initWithSize:NSMakeSize(gWidth, gHeight)]; 
[img addRepresentation:bitmap]; 

Problem mam jest to, że ja później pisanie więcej rzeczy do "danych" i wiem, że NSImage nie robi ich kopii. Mówię to, ponieważ jeśli później piszę wszystkie 0 do mojego bufora danych, to obraz stanie się czarny.

Walczę z Celem C, więc nie przejmuj się, jeśli to jest trywialne.

Jeśli zrobię lokalną kopię „dane” i nigdy za darmo to wtedy wszystko działa dobrze, ale oczywiście przecieki:

unsigned char *copy_of_data = new unsigned char[len]; 
memcpy(copy_of_data, data, len); 

Jak mogę albo:

(1) sprawiają, że initWithBitmapDataPlanes tworzyć własna kopia i deallocation handle?

lub (2) samodzielnie uwolnić dane, gdy jest to potrzebne, po tym, jak obraz przestał go potrzebować?

Odpowiedz

6

Najprościej może być przekazanie NULL dla parametru planes. Następnie po przydzieleniu i zainicjowaniu przedstawiciela obrazu, poproś o jego numer -bitmapData i skopiuj dane do tego. Takie podejście sugeruje w docs:

przypadku samolotów jest NULL lub tablicą wskaźników NULL, metoda ta przydziela wystarczającej ilości pamięci do przechowywania obrazu opisanego przez innych argumentów. Użytkownik może następnie uzyskać wskaźniki do tej pamięci (za pomocą metody getPixel: atX: y: lub bitmapData) i wypełnić dane obrazu. W tym przypadku przydzielona pamięć będzie należeć do obiektu i zostanie zwolniona, gdy zostanie zwolniona, gdy zostanie zwolniona .

Podkreślenie dodane.

+0

Ooh! Tęsknie za tym. Dam mu wir i zobaczę, czy to działa. – spartygw

+0

To działa idealnie! Dziękuję Ci bardzo. – spartygw

1

Zgodnie z docs here, NSBitmapImageRep, nie będzie przejmować własności danych płaszczyzny, jeśli jest ważna, gdy ją przekażesz. ("Gdy obiekt jest wolny, nie będzie próbował zwolnić buforów.").

Więc jesteś sam. Najprostszym sposobem jest utrzymywanie wskaźnika na danych obok wskaźnika do obrazu, a gdy jeden jest zwolniony, uwolnij drugi. (np. jeśli są przechowywane jako pliki iv lub są używane tymczasowo). To może być trudniejsze, jeśli używasz GC.

Najwyraźniej można również utworzyć małą klasę opakowania, która jest właścicielem zarówno obiektu rep replikacji obrazu, jak i wskaźnika danych, a także w obiekcie -finalize (lub -dealloc) tego obiektu, aby pozbyć się bufora danych.