Objective C - 将 UIImage 保存为 BMP 文件

Posted

技术标签:

【中文标题】Objective C - 将 UIImage 保存为 BMP 文件【英文标题】:Objective C - save UIImage as a BMP file 【发布时间】:2014-08-04 20:12:54 【问题描述】:

有人问过类似的问题,但它们总是包含“使用 UIImagePNGRepresentation 或 UIImageJPEGRepresentation”的答案,这对我不起作用。我需要将文件保存为位图。

据我了解,UIImage 数据已经是位图。在这种情况下,我不应该创建位图。还是我?我找到了发布this question 的人,但我不确定答案到底是什么,因为我不清楚。我什至已经创建了一个 char 指针数组,但我仍然不知道如何将它保存为位图。有没有人可以帮助我了解如何将 UIImage 保存为位图?或者告诉我步骤,我会研究步骤。

谢谢。


编辑:

我发现this tutorial(带有代码)用于将图像转换为位图,但返回的位图是一个无符号字符 *。要么我走在正确的道路上,要么我走错了方向。所以现在我要看看是否可以将 unsigned char * 写入 .bmp 文件。

【问题讨论】:

How can I save a Bitmap Image, represented by a CGContextRef, to the iPhone's hard drive? 的可能副本 我会试试看的。谢谢。 不 - 使用 UIImagePNGRepresentation。我需要将其保存为位图。 一开始是这样,但看看它是如何导出的 - 使用 CI 上下文作为 bmp。 位图上下文中的数据应该是什么? 【参考方案1】:

下面是我为 UIImage 拼凑的类别,它让我可以访问原始 BGRA 数据以及准备写入磁盘的具有适当位图标头的数据。

@interface UIImage (BitmapData)
- (NSData *)bitmapData;
- (NSData *)bitmapFileHeaderData;
- (NSData *)bitmapDataWithFileHeader;
@end



# pragma pack(push, 1)
typedef struct s_bitmap_header

    // Bitmap file header
    UInt16 fileType;
    UInt32 fileSize;
    UInt16 reserved1;
    UInt16 reserved2;
    UInt32 bitmapOffset;

    // DIB Header
    UInt32 headerSize;
    UInt32 width;
    UInt32 height;
    UInt16 colorPlanes;
    UInt16 bitsPerPixel;
    UInt32 compression;
    UInt32 bitmapSize;
    UInt32 horizontalResolution;
    UInt32 verticalResolution;
    UInt32 colorsUsed;
    UInt32 colorsImportant;
 t_bitmap_header;
#pragma pack(pop)

@implementation UIImage (BitmapData)

- (NSData *)bitmapData

    NSData          *bitmapData = nil;
    CGImageRef      image = self.CGImage;
    CGContextRef    context = NULL;
    CGColorSpaceRef colorSpace;
    UInt8           *rawData;

    size_t bitsPerPixel = 32;
    size_t bitsPerComponent = 8;
    size_t bytesPerPixel = bitsPerPixel / bitsPerComponent;

    size_t width = CGImageGetWidth(image);
    size_t height = CGImageGetHeight(image);

    size_t bytesPerRow = width * bytesPerPixel;
    size_t bufferLength = bytesPerRow * height;

    colorSpace = CGColorSpaceCreateDeviceRGB();

    if (colorSpace)
    
        // Allocate memory for raw image data
        rawData = (UInt8 *)calloc(bufferLength, sizeof(UInt8));

        if (rawData)
        
            CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst;
            context = CGBitmapContextCreate(rawData,
                                            width,
                                            height,
                                            bitsPerComponent,
                                            bytesPerRow,
                                            colorSpace,
                                            bitmapInfo);

            if (context)
            
                CGRect rect = CGRectMake(0, 0, width, height);

                CGContextTranslateCTM(context, 0, height);
                CGContextScaleCTM(context, 1.0, -1.0);
                CGContextDrawImage(context, rect, image);

                bitmapData = [NSData dataWithBytes:rawData length:bufferLength];

                CGContextRelease(context);
            

            free(rawData);
        

        CGColorSpaceRelease(colorSpace);
    

    return bitmapData;


- (NSData *)bitmapFileHeaderData

    CGImageRef image = self.CGImage;
    UInt32     width = (UInt32)CGImageGetWidth(image);
    UInt32     height = (UInt32)CGImageGetHeight(image);

    t_bitmap_header header;

    header.fileType = 0x4D42;
    header.fileSize = (height * width * 4) + 54;
    header.reserved1 = 0x0000;
    header.reserved2 = 0x0000;
    header.bitmapOffset = 0x00000036;
    header.headerSize = 0x00000028;
    header.width = width;
    header.height = height;
    header.colorPlanes = 0x0001;
    header.bitsPerPixel = 0x0020;
    header.compression = 0x00000000;
    header.bitmapSize = height * width * 4;
    header.horizontalResolution = 0x00000B13;
    header.verticalResolution = 0x00000B13;
    header.colorsUsed = 0x00000000;
    header.colorsImportant = 0x00000000;

    return [NSData dataWithBytes:&header length:sizeof(t_bitmap_header)];


- (NSData *)bitmapDataWithFileHeader

    NSMutableData *data = [NSMutableData dataWithData:[self bitmapFileHeaderData]];
    [data appendData:[self bitmapData]];

    return [NSData dataWithData:data];


@end

【讨论】:

嗨!我尝试使用您的代码(经过一些修改)生成 8 位灰度位图,但无法进行适当的更改以使其正常工作。你觉得你能帮我吗?谢谢!问题发布在这里:***.com/questions/30402929/…

以上是关于Objective C - 将 UIImage 保存为 BMP 文件的主要内容,如果未能解决你的问题,请参考以下文章

Objective- C:在 UIImage 上绘制边框

uiimage到Objective C中的XBM格式

Objective c 在转换为 UIImage 时丢失了 CIImage 内存

如何在Objective C中像Marquee Tag一样为UIImage设置动画

如何在objective-c中使UIImage为NULL

Objective c 图像集大小不失真