initWithData
работает только для типов изображений, о которых система уже знает. Для неизвестных типов - и необработанных данных пикселей - вам нужно создать представление изображения самостоятельно. Вы можете сделать это через Core Graphics, как предлагается в ответе, на который Кирби ссылается. Кроме того, вы можете использовать NSImage
, создав и добавив NSBitmapImageRep
.
Точные детали будут зависеть от формата ваших данных пикселей, но вот пример процесса для изображения в оттенках серого, где исходные данные (массив samples
) представлены как двойные в диапазоне [0,1] :
/* generate a greyscale image representation */
NSBitmapImageRep *greyRep =
[[NSBitmapImageRep alloc]
initWithBitmapDataPlanes: nil // allocate the pixel buffer for us
pixelsWide: xDim
pixelsHigh: yDim
bitsPerSample: 8
samplesPerPixel: 1
hasAlpha: NO
isPlanar: NO
colorSpaceName: NSCalibratedWhiteColorSpace // 0 = black, 1 = white in this color space
bytesPerRow: 0 // passing 0 means "you figure it out"
bitsPerPixel: 8]; // this must agree with bitsPerSample and samplesPerPixel
NSInteger rowBytes = [greyRep bytesPerRow];
unsigned char* pix = [greyRep bitmapData];
for ( i = 0; i < yDim; ++i )
{
for ( j = 0; j < xDim; ++j )
{
pix[i * rowBytes + j] = (unsigned char)(255 * (samples[i * xDim + j]));
}
}
NSImage* greyscale = [[NSImage alloc] initWithSize:NSMakeSize(xDim,yDim)];
[greyscale addRepresentation:greyRep];
[greyRep release];
РЕДАКТИРОВАТЬ (в ответ на комментарий)
Я не знал наверняка, поддерживаются ли 16-битные сэмплы, но вы, кажется, подтвердили, что они есть.
То, что вы видите, связано с обработкой пикселей как unsigned char
, что составляет 8 бит. Таким образом, вы устанавливаете только половину каждой строки, и вы устанавливаете каждый из этих пикселей, по одному байту за раз, на значение двух байтов 0xFF00
- не совсем настоящий белый, но очень близкий. Другая половина изображения не затрагивается, но была бы инициализирована на 0, поэтому она остается черной.
Вместо этого вам нужно работать в 16 битах, сначала приведя значение, которое вы получите от представителя:
unsigned short * pix = (unsigned short*) [greyRep bitmapData];
И затем присвоение 16-битных значений пикселям:
if ( j % 2 )
{
pix[i * rowBytes + j] = 0xFFFF;
}
else
{
pix[i * rowBytes + j] = 0;
}
Поцарапайте, что rowBytes
в байтах, поэтому нам нужно придерживаться unsigned char
для pix
и приводить при назначении, что немного уродливее:
if ( j % 2 )
{
*((unsigned short*) (pix + i * rowBytes + j * 2)) = 0xFFFF;
}
else
{
*((unsigned short*) (pix + i * rowBytes + j * 2)) = 0;
}
(Я изменил порядок предложений, потому что == 0
казался излишним. На самом деле для чего-то подобного было бы гораздо удобнее использовать синтаксис ?:
, но этого C-фьюзинга достаточно.)