无法在Windows上读取NSBitmapImageRep生成的BMP

时间:2011-08-24 03:26:20

标签: windows cocoa macos bmp nsbitmapimagerep

我有一个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];

这里的事情是可以在Mac OSX下正确读取和操作BMP文件,但在Windows下,它无法加载,就像在此屏幕截图中一样:

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

如果使用MS Paint打开文件(是的,MS Paint可以打开它),然后重新保存,它会起作用。

非常感谢这里的一只手。 :)

提前致谢。

1 个答案:

答案 0 :(得分:0)

我认为您的代码失败的主要原因是您创建的NSBitmapImageRep每像素为0位。这意味着您的图像代表将在其中准确地具有零信息。你几乎肯定想要每像素32位。

但是,您的代码是一种令人难以置信的错综复杂的方式,可以从磁盘上的映像文件中获取NSBitmapImageRep。为什么你在使用CIImage?这是一个Core Image对象,设计用于Core Image过滤器,根本没有任何意义。您应该使用NSImageCGImageRef

您的方法名称也很差。它应该被命名为+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];
}

您确实需要查看Cocoa Drawing GuideMemory Management Guidelines,因为您似乎遇到了一些基本概念的问题。