同様の質問が寄せられていますが、常に「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 構造を実装する必要がありますか? この構造体に値を入力する方法に関するドキュメントはどこにありますか?