Управление памятью какао при использовании initWithBitmapDataPlanes для создания NSImage

Я создаю NSImage из беззнакового char * 24-битных данных RGB, например:

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];

Проблема, с которой я сталкиваюсь, заключается в том, что позже я пишу больше вещей в «данные», и я знаю, что NSImage не делает их копию. Я говорю это потому, что если позже я запишу все 0 в свой буфер данных, то изображение станет полностью черным.

Я борюсь с Objective C, так что терпите меня, если это тривиально.

Если я сделаю локальную копию «данных» и никогда не освобожу ее, тогда все будет работать хорошо, но, очевидно, произойдет утечка:

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

Как я могу:

(1) заставить initWithBitmapDataPlanes создать свою собственную копию и обработать освобождение?

или (2) самостоятельно освобождать данные, когда это необходимо, после того, как изображение больше не нуждается в них?


person spartygw    schedule 18.04.2013    source источник


Ответы (2)


Проще всего передать NULL для параметра planes. Затем, после того, как представление изображения было выделено и инициализировано, запросите его -bitmapData и скопируйте в него свои данные. Этот подход предлагается в документах:

Если planes имеет значение NULL или массив указателей NULL, этот метод выделяет достаточно памяти для хранения изображения, описанного другими аргументами. Затем вы можете получить указатели на эту память (с помощью метода getPixel:atX:y: или bitmapData) и заполнить данными изображения. В этом случае выделенная память будет принадлежать объекту и будет освобождается, когда освобождается.

Добавлен акцент.

person Ken Thomases    schedule 19.04.2013
comment
Ох! Я пропустил это. Я дам ему вихрь и посмотреть, если он работает. - person spartygw; 19.04.2013

Согласно здесь, NSBitmapImageRep не станет владельцем данных плоскости, если они действительны на момент их передачи. («Когда сам объект освобождается, он не будет пытаться освободить буферы».).

Так что ты сам по себе. Самый простой способ — держать указатель на данные рядом с указателем на представление изображения, а когда один освобождается, освобождать другой. (т. е. если они хранятся как ивары или используются временно.) Это может быть сложнее, если вы используете GC.

Наиболее аккуратно вы также можете создать небольшой класс-оболочку, который владеет как объектом представления изображения, так и указателем данных, и в -finalize (или -dealloc) этого объекта избавиться от буфера данных.

person Ben Zotto    schedule 19.04.2013