Помогите пожалуйста с CGBitmapContext и 16 битными изображениями - PullRequest
1 голос
/ 20 октября 2010

Я ЛЮБЛЮ, чтобы знать, что я делаю здесь не так.Я немного новичок в CGImageRefs, так что любой совет поможет.

Я пытаюсь создать растровое изображение, которое имеет в качестве своих значений пикселей взвешенную сумму пикселей из другого растрового изображения, и оба растровых изображения16 бит на канал.По какой-то причине у меня не было проблем, чтобы заставить это работать с 8-битными изображениями, но это с треском провалилось с 16-битными.Я думаю, что я просто не все правильно настраиваю.Я пытался использовать CGFloats, float и UInt16s в качестве типов данных, но ничего не получалось.Входное изображение не имеет альфа-канала.Полученное изображение выглядит как цветной снег.

соответствующий материал из заголовка:

UInt16 *inBaseAddress;
UInt16 *outBaseAddress;
CGFloat inAlpha[5];
CGFloat inRed[5];
CGFloat inGreen[5];
CGFloat inBlue[5];
CGFloat alphaSum, redSum, greenSum, blueSum;
int shifts[5];
CGFloat weight[5];
CGFloat weightSum;

Я создаю контекст для входного растрового изображения (CGImageRef, созданный с CGImageSourceCreateImageAtIndex (source, 0,NULL)) используя:

size_t width = CGImageGetWidth(inBitmap);
size_t height = CGImageGetHeight(inBitmap);
size_t bitmapBitsPerComponent = CGImageGetBitsPerComponent(inBitmap);
size_t bitmapBytesPerRow = (pixelsWide * 4 * bitmapBitsPerComponent / 8);
CGColorSpaceRef colorSpace = CGImageGetColorSpace(inImage);

CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaNoneSkipLast;


CGContextRef inContext = CGBitmapContextCreate (NULL,width,height,bitmapBitsPerComponent,bitmapBytesPerRow,colorSpace,bitmapInfo);

Контекст для выходного растрового изображения создается таким же образом.Я рисую inBitmap в inContext, используя:

CGRect rect = {{0,0},{width,height}}; 
CGContextDrawImage(inContext, rect, inBitmap);

Затем я инициализирую inBaseAddress и outBaseAddress следующим образом:

inBaseAddress = CGBitmapContextGetData(inContext);
outBaseAddress = CGBitmapContextGetData(outContext);

Затем я заполняю outBaseAddress значениями из inBaseAddress:

for (n = 0; n < 5; n++)
{
    inRed[n] = inBaseAddress[inSpot + 0 + shifts[n]];
    inGreen[n] = inBaseAddress[inSpot + 1 + shifts[n]];
    inBlue[n] = inBaseAddress[inSpot + 2 + shifts[n]];
    inAlpha[n] = inBaseAddress[inSpot + 3 + shifts[n]];

}

alphaSum = 0.0;
redSum = 0.0;
greenSum = 0.0;
blueSum = 0.0;

for (n = 0; n < 5; n++)
{
    redSum  += inRed[n] * weight[n];
    greenSum += inGreen[n] * weight[n];
    blueSum += inBlue[n] * weight[n];
    alphaSum += inAlpha[n] * weight[n];

}

outBaseAddress[outSpot + 0] = (UInt16)roundf(redSum);
outBaseAddress[outSpot + 1] = (UInt16)roundf(greenSum);
outBaseAddress[outSpot + 2] = (UInt16)roundf(blueSum);
outBaseAddress[outSpot + 3] = (UInt16)roundf(alphaSum);

В качестве простой проверки я попробовал:

outBaseAddress[outSpot + 0] = inBaseAddress[inSpot + 0];
outBaseAddress[outSpot + 1] = inBaseAddress[inSpot + 1];
outBaseAddress[outSpot + 2] = inBaseAddress[inSpot + 2];
outBaseAddress[outSpot + 3] = inBaseAddress[inSpot + 3];

, которая работает и по крайней мере означает, что контексты и указатели на растровые данные работают.

Спасибодля любого входа.Это было довольно неприятно, поскольку с 8-битными изображениями все работало нормально.

Ответы [ 3 ]

3 голосов
/ 21 октября 2010

ОК, я понял это. Мне нужно было установить для bitmapInfo значение kCGBitmapByteOrder16Little для изображений 16bit и kCGBitmapByteOrder32Little для изображений 8bit . Я немного удивлен этим на самом деле, так как ожидал, что это будет наоборот (32Little для 16 бит и 16Little для 8 бит).

Мне также нужно было ввести def указатели на растровые изображения как UInt8* и UInt16*. Также кажется, что я должен включить альфа-канал в bitmapContext. Я не уверен, почему, но возвращенный контекст всегда был нулевым без него.

1 голос
/ 20 октября 2010

Звучит как проблема с порядком байтов

0 голосов
/ 20 октября 2010

Вы проверили, что CGImageGetBitsPerComponent возвращает 16? В качестве стиля, если вы предполагаете, что создаете растровый контекст с 16 битами на пиксель (поскольку вы обрабатываете данные как UInt16*), вы должны явно установить size_t bitmapBitsPerComponent = 16.

Для чего нужен ваш массив shifts? Кажется, это наиболее вероятное место для ошибки, так как это влияет на адрес, с которого вы читаете, но вы его вообще не объясняете. Значения в shifts кратны 16?

...