32-битные / компонентные Изображения с CGImageCreate на самом деле только 8-битные / компонентные - PullRequest
1 голос
/ 31 марта 2011

Последние 4-5 часов я боролся с этой очень странной проблемой.У меня есть массив байтов, которые содержат значения пикселей, из которых я хотел бы сделать изображение.Массив представляет 32-битные значения для каждого компонента.Альфа-канал отсутствует, поэтому изображение имеет размер 96 бит / пиксель.

Я указал все это для функции CGImageCreate следующим образом:

  CGImageRef img = CGImageCreate(width, height, 32, 96, bytesPerRow, space, kCGImageAlphaNone , provider, NULL, NO, kCGRenderingIntentDefault);

bytesPerRow равно 3*width*4.Это связано с тем, что на пиксель приходится 3 компонента, а каждый компонент занимает 4 байта (32 бита).Таким образом, общее количество байтов в строке составляет 3 * 4 * ширины.Поставщик данных определяется следующим образом:

     CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,bitmapData,3*4*width*height,NULL);

Здесь все становится странным.В моем массиве я просто устанавливаю значения 0x000000FF (для всех 3 каналов), и все же изображение получается полностью белым.Если я установлю значение 0xFFFFFF00, изображение получится черным.Это говорит мне о том, что программа по какой-то причине не читает все 4 байта для каждого компонента и вместо этого читает наименее значимый байт.Я перепробовал все виды комбинаций - даже включая альфа-канал, но это ничего не изменило.

Программа слепа к этому: 0xAAAAAA00.Он просто читает это как 0. Когда я просто указываю, что биты на компонент 32-битные, не должна ли функция принять это во внимание и фактически прочитать 4 байта из массива?

Массив байтовопределяется как: bitmapData = (char*)malloc(bytesPerRow*height); И я присваиваю значения массиву следующим образом

 for(i=0;i<width*height;i++)
{
    *((unsigned int *)(bitmapData + 12*i + 0)) = 0xFFFFFF00;
    *((unsigned int *)(bitmapData + 12*i + 4)) = 0xFFFFFF00;
    *((unsigned int *)(bitmapData + 12*i + 8)) = 0xFFFFFF00;
}

Обратите внимание, что я адрес массива как int для адресации 4 байта памяти.i умножается на 12, потому что на пиксель приходится 12 байтов.Добавление 4 и 8 позволяет петле обращаться к зеленому и синему каналам.Обратите внимание, что я проверил память массива в отладчике, и, похоже, все в порядке.Цикл записи в 4 байта.Любые указатели на это были бы САМЫМИ полезными.Моя конечная цель - прочитать 32-битные файлы FITS, для которых я уже написал программу.Я только тестирую приведенный выше код с указанным выше массивом.

Здесь приведен полный код, если он имеет значение.Это метод drawRect:(NSRect)dirtyRect моего пользовательского представления:

int width, height, bytesPerRow;
int i;

width = 256;
height = 256;
bytesPerRow = 3*width*4;

char *bitmapData;
bitmapData = (char*)malloc(bytesPerRow*height);
for(i=0;i<width*height;i++)
{
    *((unsigned int *)(bitmapData + 12*i + 0)) = 0xFFFFFF00;
    *((unsigned int *)(bitmapData + 12*i + 4)) = 0xFFFFFF00;
    *((unsigned int *)(bitmapData + 12*i + 8)) = 0xFFFFFF00;
}
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,bitmapData,3*4*width*height,NULL);
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();

CGImageRef img = CGImageCreate(width, height, 32, 96, bytesPerRow, space, kCGImageAlphaNone, provider, NULL, NO, kCGRenderingIntentDefault);

CGColorSpaceRelease(space);
CGDataProviderRelease(provider);

CGContextRef theContext = [[NSGraphicsContext currentContext] graphicsPort];
CGContextDrawImage(theContext, CGRectMake(0,0,width,height), img);

1 Ответ

2 голосов
/ 31 марта 2011

Я вижу несколько вещей, на которые стоит обратить внимание:

Во-первых, в Руководстве по программированию в Quartz 2D не перечисляется 96-бит / с RGB в качестве поддерживаемого формата.Вы можете попробовать RGB со скоростью 128 бит / с.

Во-вторых, вы работаете в системе с прямым порядком байтов *, что означает, что LSB стоит первым.Измените значения, для которых вы устанавливаете каждый компонент на 0x33000000EE, и вы увидите светло-серый (EE), а не темно-серый (33).

Самое главное, bbum абсолютно прав, когдаон указывает, что ваш дисплей не может отобразить этот диапазон цвета **.Это сокращается до 8 бит на канал только для отображения.Если это правильно в памяти, то это правильно в памяти.


*: Больше жаль.RIP PPC.

**: Может, у НАСА есть такой, который может?

...