BMP, созданный NSBitmapImageRep, не может быть прочитан в Windows

У меня есть NSBitmapImageRep, который я создаю следующим образом:

+ (NSBitmapImageRep *)bitmapRepOfImage:(NSURL *)imageURL {
    CIImage *anImage = [CIImage imageWithContentsOfURL:imageURL];
    CGRect outputExtent = [anImage extent];

    NSBitmapImageRep *theBitMapToBeSaved = [[NSBitmapImageRep alloc]  
                                        initWithBitmapDataPlanes:NULL pixelsWide:outputExtent.size.width  
                                        pixelsHigh:outputExtent.size.height  bitsPerSample:8 samplesPerPixel:4  
                                        hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace  
                                        bytesPerRow:0 bitsPerPixel:0];

    NSGraphicsContext *nsContext = [NSGraphicsContext graphicsContextWithBitmapImageRep:theBitMapToBeSaved];

    [NSGraphicsContext saveGraphicsState];
    [NSGraphicsContext setCurrentContext: nsContext];
    CGPoint p = CGPointMake(0.0, 0.0);

    [[nsContext CIContext] drawImage:anImage atPoint:p fromRect:outputExtent];

    [NSGraphicsContext restoreGraphicsState];

    return [[theBitMapToBeSaved retain] autorelease];
}

И сохраняются как BMP таким образом:

NSBitmapImageRep *original = [imageTools bitmapRepOfImage:fileURL];
NSData *converted = [original representationUsingType:NSBMPFileType properties:nil];
[converted writeToFile:filePath atomically:YES];

Дело в том, что файл BMP можно правильно читать и управлять им в Mac OSX, но в Windows он просто не загружается, как на этом снимке экрана:

http://dl.dropbox.com/u/1661304/Grab/74a6dadb770654213cdd9290f0131880.png

Если файл открыт с помощью MS Paint (да, MS Paint может его открыть), а затем повторно сохранен, он будет работать.

Был бы признателен за руку здесь. :)

Заранее спасибо.


person EduAlm    schedule 24.08.2011    source источник


Ответы (1)


Я думаю, что основная причина того, что ваш код не работает, заключается в том, что вы создаете свой NSBitmapImageRep с 0 бит на пиксель. Это означает, что в вашем репутации изображения будет ровно нулевая информация. Вы почти наверняка захотите 32 бита на пиксель.

Однако ваш код - это невероятно запутанный способ получить NSBitmapImageRep из файла изображения на диске. С какой стати вы используете CIImage? Это объект Core Image, разработанный для использования с фильтрами Core Image, и здесь он не имеет никакого смысла. Вы должны использовать NSImage или CGImageRef.

Ваш метод тоже плохо назван. Вместо этого его следует назвать как-то вроде +bitmapRepForImageFileAtURL:, чтобы лучше указать, что он делает.

Кроме того, этот код не имеет смысла:

[[theBitMapToBeSaved retain] autorelease]

Вызов retain, а затем autorelease ничего не делает, потому что все, что он делает, увеличивает счетчик сохранения, а затем немедленно уменьшает его снова.

Вы несете ответственность за выпуск theBitMapToBeSaved, потому что вы создали его с помощью alloc. Поскольку он возвращается, вы должны позвонить по нему autorelease. Ваш дополнительный вызов retain просто вызывает утечку без причины.

Попробуй это:

+ (NSBitmapImageRep*)bitmapRepForImageFileAtURL:(NSURL*)imageURL
{
    NSImage* image = [[[NSImage alloc] initWithContentsOfURL:imageURL] autorelease];
    return [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]];
}

+ (NSData*)BMPDataForImageFileAtURL:(NSURL*)imageURL
{
    NSBitmapImageRep* bitmap = [self bitmapRepForImageFileAtURL:imageURL];
    return [bitmap representationUsingType:NSBMPFileType properties:nil];
}

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

person Rob Keniger    schedule 24.08.2011
comment
Здравствуйте, прежде всего спасибо за вашу помощь. Вы правы, что сохранять] автоспуск] вообще не имеет смысла. Ваш код кажется намного лучше, чем мой предыдущий. Единственная проблема заключается в том, что BMP по-прежнему не открывается встроенным средством просмотра файлов Windows, такая же ошибка, как и выше. (Вы также можете исправить свой второй метод, если кто-то захочет его использовать. Вы не можете вызвать self, поскольку объект не выделен, а fileURL должен быть imageURL). - person EduAlm; 24.08.2011
comment
Вы можете вызвать self, потому что это метод класса, вызывающий другой метод класса. - person Rob Keniger; 24.08.2011
comment
Ну что ж, думаю, я всегда учусь. Знаешь, что случилось с проблемой BMP? - person EduAlm; 24.08.2011
comment
Принял ваш ответ, так как он мне помог. - person EduAlm; 04.12.2011