1

我将 NSBitmapImageRep 保存到 BMP 文件(雪豹)。当我在macos上打开它时似乎没问题。但它在我的多媒体设备上出错(可以显示来自互联网的任何 BMP 文件)。我不知道出了什么问题,但是当我查看文件内部时(在 macos 上使用很酷的 hexfiend 应用程序),有两件事错了:

  • 标头的 biHeight 参数值错误:4294966216 (hex=C8FBFFFF) 标头具有正确的 biWidth 参数:1920
  • 位图内容中的第一个像素(在 BMP 格式的 54 字节标头之后)对应于原始图像的左上角。在原始 BMP 文件中,按照 BMP 格式的规定,它应该首先是左下角像素。

为了解释我的应用程序中的完整工作流程,我有一个 NSImageView,我可以在其中拖动 BMP 图像。这个视图绑定到一个 NSImage。拖放后,我有一个操作可以将此图像(上面绘制一些文本)保存到 BMP 文件中。

这是保存新 BMP 文件的代码:

CGColorSpaceRefcolorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGContextRefcontext = CGBitmapContextCreate(NULL, (int)1920, (int)1080, 8, 4*(int)1920, colorSpace, kCGImageAlphaNoneSkipLast);

[duneScreenViewdrawBackgroundWithDuneFolder:self inContext:context inRect:NSMakeRect(0,0,1920,1080) needScale:NO];
if(folderType==DXFolderTypeMovie) {

    [duneScreenViewdrawSynopsisContentWithDuneFolder:self inContext:context inRect:NSMakeRect(0,0,1920,1080) withScale:1.0];
}


CGImageRef backgroundImageRef = CGBitmapContextCreateImage(context);
NSBitmapImageRep*bitmapBackgroundImageRef = [[NSBitmapImageRepalloc] initWithCGImage:backgroundImageRef];


NSData*data = [destinationBitmap representationUsingType:NSBMPFileType properties:nil];
[data writeToFile:[NSStringstringWithFormat:@"%@/%@", folderPath,backgroundPath] atomically: YES];

duneScreenViewdrawSynopsisContentWithDuneFolder 方法使用 CGContextDrawImage 来绘制图像。duneScreenViewdrawSynopsis 方法使用 CoreText 在同一上下文中绘制一些文本。

你知道出了什么问题吗?

4

1 回答 1

1

我刚刚注册了一个 openid 帐户,所以我无法编辑自己的问题。我找到了解决此问题的方法并想发布我的解决方案。

有两个问题:

  • BMP 标头中的 biHeight 参数错误
  • 位图内容中垂直翻转的数据(首先从左上角开始,而不是左下角)

对于 biHeight 参数,我将 biHeight 字节替换为合适的值(我的图像为 1080)

对于翻转问题,我只是翻转内容位图字节中的所有行。

可能这不是最优雅的解决方案,但它工作正常。如果您有其他解决方案,请告诉我。

这是代码:

intwidth = 1920;
intheight = 1080;

CGColorSpaceRefcolorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRefcontext = CGBitmapContextCreate(NULL, (int)width, (int)height, 8, 4* (int)width, colorSpace, kCGImageAlphaNoneSkipLast);

[duneScreenViewdrawBackgroundWithDuneFolder:selfinContext:context inRect:NSMakeRect(0,0,width,height) needScale:NO];
if(folderType==DXFolderTypeMovie) {

    [duneScreenViewdrawSynopsisContentWithDuneFolder:selfinContext:context inRect:NSMakeRect(0,0,width,height) withScale:1.0];
}

CGImageRefbackgroundImageRef = CGBitmapContextCreateImage(context);

NSBitmapImageRep*bitmapBackgroundImageRef = [[NSBitmapImageRepalloc] initWithCGImage:backgroundImageRef];

NSData*data = [bitmapBackgroundImageRef representationUsingType:NSBMPFileTypeproperties:nil];

NSMutableData*mutableData = [[NSMutableDataalloc] init];

intbitmapBytesOffset = 54;

//headers
[mutableData appendData:[data subdataWithRange:NSMakeRange(0,bitmapBytesOffset)]];

//bitmap data
intlineIndex=height-1;

while(lineIndex>=0) {

    [mutableData appendData:[data subdataWithRange:NSMakeRange(bitmapBytesOffset+lineIndex*width*3,width*3)]];

    lineIndex--;
}

//force biHeight header parameter to 1080
NSString*biHeightString = @"\x38\x04\x00\x00";
NSData*biHeightData = [biHeightString dataUsingEncoding:NSUTF8StringEncoding];
[mutableData replaceBytesInRange:NSMakeRange(22,4) withBytes:[biHeightData bytes]];

[mutableData writeToFile:[NSStringstringWithFormat:@"%@/%@", folderPath,backgroundPath] atomically: YES];

[mutableData release];


CGImageRelease(backgroundImageRef);
[bitmapBackgroundImageRef release];
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
于 2010-04-29T08:12:10.267 回答