Can I save (write to file) UIImage object as bitmap file (.bmp extension) in iPhone’s document directory?
Thanks in advance.
Realize this is an old post, but in case someone finds it like I did looking for a solution. I basically needed to FTP UIImage as a small BMP, so I hacked this crude class in MonoTouch. I borrowed from zxing.Bitmap.cs and Example 1 from wikipedia BMP article. It appears to work. Might have been slicker to do an extension like AsBMP() or something like that. (I don't know what the objective-c equivalent is, but hopefully this is helpful to someone.)
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.CoreGraphics;
public class BitmapFileRGBA8888
{
public byte[] Data; // data needs to be BGRA
public const int PixelDataOffset = 54;
public BitmapFileRGBA8888(UIImage image)
{
CGImage imageRef = image.CGImage;
int width = imageRef.Width;
int height = imageRef.Height;
Initialize((uint)width, (uint)height);
CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB();
IntPtr rawData = Marshal.AllocHGlobal(height*width*4);
CGContext context = new CGBitmapContext(
rawData, width, height, 8, 4*width, colorSpace, CGImageAlphaInfo.PremultipliedLast
);
context.DrawImage(new RectangleF(0.0f,0.0f,(float)width,(float)height),imageRef); // RGBA
byte[] pixelData = new byte[height*width*4];
Marshal.Copy(rawData,pixelData,0,pixelData.Length);
Marshal.FreeHGlobal(rawData);
int di = PixelDataOffset;
int si;
for (int y = 0; y < height; y++)
{
si = (height-y-1) * 4 * width;
for (int x = 0; x < width; x++)
{
CopyFlipPixel(pixelData, si, Data, di);
di += 4; // destination marchs forward
si += 4;
}
}
}
private void CopyFlipPixel(byte[] Src, int Src_offset, byte[] Dst, int Dst_offset)
{
int S = Src_offset;
int D = Dst_offset + 2;
Dst[D--] = Src[S++]; // R
Dst[D--] = Src[S++]; // G
Dst[D--] = Src[S++]; // B
Dst[Dst_offset+3] = Src[S]; // alpha
}
private void Initialize(uint W, uint H)
{
uint RawPixelDataSize = W * H * 4;
uint Size = RawPixelDataSize + 14 + 40;
Data = new byte[Size];
Data[0] = 0x42; Data[1] = 0x4D; // BITMAPFILEHEADER "BM"
SetLong(0x2, Size); // file size
SetLong(0xA, PixelDataOffset); // offset to pixel data
SetLong(0xE, 40); // bytes in DIB header (BITMAPINFOHEADER)
SetLong(0x12, W);
SetLong(0x16, H);
SetShort(0x1A, 1); // 1 plane
SetShort(0x1C, 32); // 32 bits
SetLong(0x22, RawPixelDataSize);
SetLong(0x26, 2835); // h/v pixels per meter device resolution
SetLong(0x2A, 2835);
}
private void SetShort(int Offset, UInt16 V)
{
var byts = BitConverter.GetBytes(V);
if (!BitConverter.IsLittleEndian) Array.Reverse(byts);
Array.Copy(byts,0,Data,Offset,byts.Length);
}
private void SetLong(int Offset, UInt32 V)
{
var byts = BitConverter.GetBytes(V);
if (!BitConverter.IsLittleEndian) Array.Reverse(byts);
Array.Copy(byts,0,Data,Offset,byts.Length);
}
} // END CLASS
Basically
var Bmp = new BitmapFileRGBA8888(TempImage);
FTP.UploadBin(Bmp.Data, "test.bmp"); // or just write as binary file