2010-04-28 2 views
1

Я сохраняю NSBitmapImageRep в BMP-файле (Snow Leopard). Кажется, нормально, когда я открываю его на macos. Но это делает ошибку на моем мультимедийном устройстве (которое может отображать любой файл BMP из Интернета). Я не могу понять, что это неправильно, но когда я смотрю внутри файла (с прохладным приложением hexfiend на MacOS), 2 вещи неправильно:Сохранение NSBitmapImageRep как файл NSBMPFileType. Неверные заголовки BMP и растровое содержимое

  • заголовка имеет неверное значение для параметра biHeight: 4294966216 (шест = C8FBFFFF) заголовок имеет правильный параметр biWidth: 1920
  • Первый пиксель в содержимом растрового изображения (после 54 байтов в формате BMP) соответствует верхнему левому углу исходного изображения. В исходном файле BMP и, как указано в формате BMP, сначала должен быть первый левый угол.

Чтобы объяснить полный рабочий процесс в моем приложении, у меня есть NSImageView, где я могу перетащить BMP-образ. Этот вид связан с NSImage. After a drag & drop У меня есть действие, чтобы сохранить это изображение (с некоторым текстовым рисунком над ним) в файл 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 для рисования некоторого текста в том же контексте.

Знаете ли вы, что не так?

ответ

1

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

Был 2 проблемы:

  • неправильный параметр biHeight в заголовке BMP
  • вертикально перевернутые данные в содержание битовой карты (начать с верхнего левого угла в месте вниз левом углу первого)

Для параметра biHeight я заменил байты biHeight на хорошее значение (1080 для моего изображения)

Для перевернутой проблемы я просто переверну все строки в битах bitmap содержимого.

Может быть, это не самое изящное решение, но оно отлично работает. Просто дайте мне знать, если вы, если у вас есть другие решения.

Вот код:

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);