How do I save an UIImage as BMP?

前端 未结 4 715
遥遥无期
遥遥无期 2020-12-20 07:40

Can I save (write to file) UIImage object as bitmap file (.bmp extension) in iPhone’s document directory?

Thanks in advance.

相关标签:
4条回答
  • 2020-12-20 08:16

    I don’t think BMP is supported on iPhone. Maybe somebody wrote a category for UIImage that does saving into BMP, but I don’t know about any. I guess You’ll have to get the bitmap data from the UIImage and write them yourself, BMP is quite a simple file format. All you have to do is write out the header and then the uncompressed data. The header is a structure called BITMAPINFOHEADER, see MSDN. Getting the bitmap data of an UIImage is described in Apple’s Technical Q&A1509.

    0 讨论(0)
  • 2020-12-20 08:17

    Since BMP is not a compressed format, is this a good idea?

    Presumably, image size is even more important on portable devices.

    0 讨论(0)
  • 2020-12-20 08:18

    Right now I am not concerned about the size. Just want to know can I write image data as .bmp file.

    0 讨论(0)
  • 2020-12-20 08:21

    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
    
    0 讨论(0)
提交回复
热议问题