Ошибка NSBitmapImageRep

Этот код выдает очень странный результат. Почему? Все, что я делаю, это копирую изображение.

NSData *data = [NSData dataWithContentsOfFile: @"/Users/Jojo/Desktop/k2.jpg"];
NSBitmapImageRep *image = [NSBitmapImageRep imageRepWithData: data];

assert(image.samplesPerPixel == 3);
assert(image.isPlanar == NO);

uint8_t *buffer = [image bitmapData];

NSBitmapImageRep *rtn = [[NSBitmapImageRep alloc]
                        initWithBitmapDataPlanes:&buffer
                        pixelsWide:image.pixelsWide
                        pixelsHigh:image.pixelsHigh
                        bitsPerSample:8
                        samplesPerPixel:3
                        hasAlpha:NO
                        isPlanar:NO
                        colorSpaceName:NSDeviceRGBColorSpace
                        bytesPerRow: image.pixelsWide*3
                        bitsPerPixel: 8*3];

NSData *newJpg = [rtn representationUsingType:NSJPEGFileType properties:nil];
[newJpg writeToFile:@"/Users/Jojo/Desktop/and.jpg" atomically:YES];

Пример:

normalсломанный


person Atomix    schedule 08.03.2014    source источник


Ответы (1)


Я не знаю, чего вы хотите добиться; только копия существующего образа? [image copy] недостаточно хорош? Помимо этого в вашем коде есть по крайней мере две большие ошибки: вам нужно четко различать свойства изображения и то, как эти свойства хранятся. Вы забыли байты заполнения, которые могут существовать или не существовать. Это часто менялось от одной версии OSX к следующей версии OSX. Таким образом, в вашем исходном изображении количество выборок на пиксель равно 3, но они хранятся в 4 байтах (причина: оптимизация доступа к хранилищу). И поэтому bitsPerPixel: 8*3 неверен, и bytesPerRow тоже. Таким образом, ваше исходное изображение имеет 1600 bytes per row, и каждый пиксель хранится в 32 bits (== 1 байт заполнения). Вы должны передать новый NSBitmapImageRep с точно такими же (буферными) параметрами, что и исходный imageRep. Это означает: последние два параметра (создание нового представителя) должны быть:

bytesPerRow: [image bytesPerRow]
bitsPerPixel: [image bitsPerPixel]

И также может быть полезно использовать параметр bitmapFormat, который говорит, являются ли компоненты пикселя RGB или BGR и где находится альфа-значение (или байт заполнения).

Может быть, лучше использовать copy-метод?

person Heinrich Giesen    schedule 08.03.2014
comment
Большое спасибо, это должно помочь мне исправить это. Мне нужно работать с изображениями, у которых нет байтов заполнения... Кстати, дело не в копировании изображения, изначально я также выполнял некоторые другие манипуляции с пикселями, которые я удалил для целей отладки. - person Atomix; 08.03.2014