如何将UIImage保存为文档目录中的BMP文件

类似的问题已经被问到,但他们总是包含答案“使用UIImagePNGRepresentation或UIImageJPEGRepresentation”但是这不会为我工作,因为我必须将此文件发送到只接受BMP图像的外部Web服务。

这是我迄今为止所实施的

-(NSData*)getBitmapRepresentationFromUIImage:(UIImage*)img{ CGImageRef cgiImg =[img CGImage]; CGColorSpaceRef colorSpaceRef = CGImageGetColorSpace(cgiImg); size_t bitsPerComponent = CGImageGetBitsPerComponent(cgiImg); size_t bytesPerRow = CGImageGetBytesPerRow(cgiImg); size_t dataSize = bytesPerRow * CGImageGetHeight(cgiImg); void* imgBuf = malloc(dataSize); CGContextRef bmpContext = CGBitmapContextCreate(imgBuf, CGImageGetWidth(cgiImg), CGImageGetHeight(cgiImg), bitsPerComponent, bytesPerRow, colorSpaceRef, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGContextDrawImage(bmpContext, CGRectMake(0, 0, CGImageGetWidth(cgiImg), CGImageGetHeight(cgiImg)), cgiImg); NSData* dataToReturn = nil; if (imgBuf!=NULL) { dataToReturn = [[NSData alloc] initWithBytes:imgBuf length:dataSize]; free(imgBuf); /*debug*/ [self saveNSDataAsBitmap:dataToReturn fileName:@"signature"]; /**/ } return dataToReturn; } -(void)saveNSDataAsBitmap:(NSData*)data fileName:(NSString*)name{ NSString* fileName = [NSString stringWithFormat:@"%@%@",name,@".bmp"]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *completePath = [documentsDirectory stringByAppendingPathComponent:fileName]; [data writeToFile:completePath atomically:YES]; } 

这将文件保存到文档目录,但我无法预览打开该文件。

我究竟做错了什么 ? 有更容易的方法吗 ?

编辑

我现在添加了文件头的结构

 #pragma pack(1) typedef struct { UInt16 magic; //specifies the file type "BM" 0x424d UInt32 bfSize; //specifies the size in bytes of the bitmap file UInt16 bfReserved1; //reserved; must be 0 UInt16 bfReserved2; //reserved; must be 0 UInt32 bOffBits; } BmpFileHeaderStruct, *BmpFileHeaderStructRef; #pragma pack(0) #pragma pack(1) typedef struct { UInt32 biSize; int32_t biWidth; int32_t biHeight; UInt16 biPlanes; UInt16 biBitCount; UInt32 biCompression; UInt32 biSizeImage; int32_t biXPelsPerMeter; int32_t biYPelsPerMeter; UInt32 biClrUsed; UInt32 biClrImportant; } BmpFileInfoStruct,*BmpFileInfoStructRef; #pragma pack(0) 

我也实现了一个函数来为imgBuf的开头附加一个头文件

 -(void*)attatchBmpFileHeaderFor:(void*)imgBuf sizeOfBuff:(size_t)buffSize forImage:(CGImageRef)img{ BmpFileHeaderStruct headerStruct = {0}; headerStruct.magic = 0x424d; headerStruct.bfSize = buffSize; headerStruct.bOffBits = (sizeof(BmpFileHeaderStruct)*8) + (sizeof(BmpFileInfoStruct)*8);//hmmm ? BmpFileInfoStruct infoStruct = {0}; infoStruct.biSize = sizeof(BmpFileInfoStruct); infoStruct.biWidth = CGImageGetWidth(img); infoStruct.biHeight = CGImageGetHeight(img); infoStruct.biPlanes = 1; infoStruct.biBitCount = CGImageGetBitsPerPixel(img); infoStruct.biSizeImage = buffSize; void * fileBmpBuf = malloc(sizeof(BmpFileInfoStruct)+sizeof(BmpFileHeaderStruct)+sizeof(buffSize)); void *pIter = fileBmpBuf; memcpy(pIter, &headerStruct, sizeof(BmpFileHeaderStruct)); pIter += sizeof(BmpFileHeaderStruct); memcpy(pIter, &infoStruct, sizeof(BmpFileInfoStruct)); pIter += sizeof(BmpFileInfoStruct); memcpy(pIter, imgBuf, buffSize); return fileBmpBuf; } 

这是行不通的,有时它由于错误指针被释放而没有分配到最后的memcpy调用,这是奇怪的,因为我没有实际上释放任何数据在这一点上崩溃。 当它工作时,会产生一个不能被读取的文件。
我必须实现一个bitmapv5header结构吗? 我在哪里可以find关于如何填充这个结构的值的文档?

你不能保存数据,你必须添加一个特定的标题和调色板。 看看文件格式: http : //en.wikipedia.org/wiki/BMP_file_format