예제 #1
0
 /// <summary>Initializes a new instance of the <see cref="BITMAPINFOHEADER"/> structure.</summary>
 /// <param name="width">The width.</param>
 /// <param name="height">The height.</param>
 /// <param name="bitCount">The bit count.</param>
 public BITMAPINFOHEADER(int width, int height, ushort bitCount = 32)
     : this()
 {
     biSize        = Marshal.SizeOf(typeof(BITMAPINFO));
     biWidth       = width;
     biHeight      = height;
     biPlanes      = 1;
     biBitCount    = bitCount;
     biCompression = BitmapCompressionMode.BI_RGB;
     biSizeImage   = 0;               // (uint)width * (uint)height * bitCount / 8;
 }
예제 #2
0
 public BITMAPINFOHEADER(int width, int height, ushort bitCount)
 {
     biSize          = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADER));
     biWidth         = width;
     biHeight        = height;
     biPlanes        = 1;
     biBitCount      = bitCount;
     biCompression   = BitmapCompressionMode.BI_RGB;
     biSizeImage     = 0;
     biXPelsPerMeter = 0;
     biYPelsPerMeter = 0;
     biClrUsed       = 0;
     biClrImportant  = 0;
 }
예제 #3
0
 public BITMAPINFOHEADER(int width, int height, uint sizeImg = 0, uint bSize = 40, uint clrUsed = 256,
     uint clrImportant = 0, BitmapCompressionMode mode = BitmapCompressionMode.BI_RGB, ushort bpp = 8, ushort planes = 1)
 {
     biSize = bSize;
     biWidth = width;
     biHeight = height;
     biPlanes = planes;
     biBitCount = bpp;
     biCompression = mode;
     biSizeImage = sizeImg;
     biXPelsPerMeter = 0;
     biYPelsPerMeter = 0;
     biClrUsed = clrUsed;
     biClrImportant = clrImportant;
 }
예제 #4
0
파일: BitmapCore.cs 프로젝트: clowd/bmplib
    public static byte[] WriteToBMP(ref BITMAP_WRITE_REQUEST info, byte *sourceBufferStart, BITMASKS masks, ushort nbits, uint bcwFlags)
    {
        bool skipFileHeader = (bcwFlags & BC_WRITE_SKIP_FH) > 0;
        bool forceV5        = (bcwFlags & BC_WRITE_V5) > 0;
        bool forceInfo      = (bcwFlags & BC_WRITE_VINFO) > 0;

        if (forceV5 && forceInfo)
        {
            throw new ArgumentException("ForceV5 and ForceInfo flags can not be used at the same time.");
        }

        // NOT SUPPORTED RIGHT NOW
        bool iccEmbed = false;

        byte[] iccProfileData = new byte[0];

        var hasAlpha = masks.maskAlpha != 0;

        if (nbits < 16 && (info.imgColorTable == null || info.imgColorTable.Length == 0))
        {
            throw new InvalidOperationException("A indexed bitmap must have a color table / palette.");
        }

        //int dpiToPelsPM(double dpi)
        //{
        //    if (Math.Round(dpi) == 96d) return 0;
        //    return (int)Math.Round(dpi / 0.0254d);
        //}

        uint paletteSize = info.imgColorTable == null ? 0 : (uint)info.imgColorTable.Length;

        var fhSize   = (uint)Marshal.SizeOf <BITMAPFILEHEADER>();
        var quadSize = (uint)Marshal.SizeOf <RGBQUAD>();

        byte[] buffer;
        uint   pxOffset, pxSize;

        // BI_BITFIELDS is not valid for 24bpp, so if the masks are not RGB we need to use a V5 header.
        //var nonStandard24bpp = nbits == 24 && !BitmapCorePixelFormat2.Bgr24.IsMatch(24, masks);

        BitmapCompressionMode compr = BitmapCompressionMode.BI_RGB;

        // some parsers do not respect the v5 header masks unless BI_BITFIELDS is used...
        // this is true of Chrome (only for 16bpp) and is also true of FireFox (16 and 32bpp)
        if (nbits == 16 || nbits == 32)
        {
            compr = BitmapCompressionMode.BI_BITFIELDS;
        }

        // write V5 header if embedded color profile or has alpha data
        if (forceV5 || hasAlpha || iccEmbed)
        {
            var v5Size = (uint)Marshal.SizeOf <BITMAPV5HEADER>();
            // Typical structure:
            // - BITMAPFILEHEADER (Optional)
            // - BITMAPV5HEADER
            // - * Note, never write BI_BITFIELDS at the end of a V5 header, these masks are contained within the header itself
            // - Color Table (Optional)
            // - Pixel Data
            // - Embedded Color Profile (Optional)

            var fh = new BITMAPFILEHEADER
            {
                bfType = BFH_BM,
            };

            var v5 = new BITMAPV5HEADER
            {
                bV5Size          = v5Size,
                bV5Planes        = 1,
                bV5BitCount      = nbits,
                bV5Height        = info.imgTopDown ? -info.imgHeight : info.imgHeight,
                bV5Width         = info.imgWidth,
                bV5Compression   = compr,
                bV5XPelsPerMeter = 0,
                bV5YPelsPerMeter = 0,

                bV5RedMask   = masks.maskRed,
                bV5GreenMask = masks.maskGreen,
                bV5BlueMask  = masks.maskBlue,
                bV5AlphaMask = masks.maskAlpha,

                bV5ClrImportant = paletteSize,
                bV5ClrUsed      = paletteSize,
                bV5SizeImage    = (uint)(info.imgStride * info.imgHeight),

                bV5CSType = ColorSpaceType.LCS_sRGB,
                bV5Intent = Bv5Intent.LCS_GM_IMAGES,
            };

            uint offset = skipFileHeader ? 0 : fhSize;
            offset += v5Size;
            offset += paletteSize * quadSize;

            // fh offset points to beginning of pixel data
            fh.bfOffBits = pxOffset = offset;
            pxSize       = v5.bV5SizeImage;

            offset += v5.bV5SizeImage;

            if (iccEmbed)
            {
                v5.bV5CSType      = ColorSpaceType.PROFILE_EMBEDDED;
                v5.bV5ProfileData = offset;
                v5.bV5ProfileSize = (uint)iccProfileData.Length;
                offset           += v5.bV5ProfileSize;
            }

            // fh size must be total file size
            fh.bfSize = offset;

            buffer = new byte[offset];
            offset = 0;

            if (!skipFileHeader)
            {
                StructUtil.SerializeTo(fh, buffer, ref offset);
            }

            StructUtil.SerializeTo(v5, buffer, ref offset);

            if (info.imgColorTable != null)
            {
                foreach (var p in info.imgColorTable)
                {
                    StructUtil.SerializeTo(p, buffer, ref offset);
                }
            }

            Marshal.Copy((IntPtr)sourceBufferStart, buffer, (int)offset, (int)v5.bV5SizeImage);
            offset += v5.bV5SizeImage;

            if (iccEmbed)
            {
                Buffer.BlockCopy(iccProfileData, 0, buffer, (int)offset, iccProfileData.Length);
            }
        }
        else
        {
            var infoSize = (uint)Marshal.SizeOf <BITMAPINFOHEADER>();
            // Typical structure:
            // - BITMAPFILEHEADER (Optional)
            // - BITMAPINFOHEADER
            // - BI_BITFIELDS (Optional)
            // - Color Table (Optional)
            // - Pixel Data

            // this would be ideal, we can specify transparency in VINFO headers... but many applications incl FireFox do not support this.
            // if (hasAlpha) compr = BitmapCompressionMode.BI_ALPHABITFIELDS;

            var fh = new BITMAPFILEHEADER
            {
                bfType = BFH_BM,
            };

            var vinfo = new BITMAPINFOHEADER
            {
                bV5Size          = infoSize,
                bV5Planes        = 1,
                bV5BitCount      = nbits,
                bV5Height        = info.imgTopDown ? -info.imgHeight : info.imgHeight,
                bV5Width         = info.imgWidth,
                bV5Compression   = compr,
                bV5XPelsPerMeter = 0,
                bV5YPelsPerMeter = 0,

                bV5ClrImportant = paletteSize,
                bV5ClrUsed      = paletteSize,
                bV5SizeImage    = (uint)(info.imgStride * info.imgHeight),
            };

            uint offset = skipFileHeader ? 0 : fhSize;
            offset += infoSize;

            if (compr == BitmapCompressionMode.BI_BITFIELDS)
            {
                offset += sizeof(uint) * 3;
            }

            offset += paletteSize * quadSize;

            // fh offset points to beginning of pixel data
            fh.bfOffBits = pxOffset = offset;
            pxSize       = vinfo.bV5SizeImage;

            offset += vinfo.bV5SizeImage;

            // fh size must be total file size
            fh.bfSize = offset;

            buffer = new byte[offset];
            offset = 0;

            if (!skipFileHeader)
            {
                StructUtil.SerializeTo(fh, buffer, ref offset);
            }

            StructUtil.SerializeTo(vinfo, buffer, ref offset);

            if (compr == BitmapCompressionMode.BI_BITFIELDS)
            {
                Buffer.BlockCopy(masks.BITFIELDS(), 0, buffer, (int)offset, sizeof(uint) * 3);
                offset += sizeof(uint) * 3;
            }

            if (info.imgColorTable != null)
            {
                foreach (var p in info.imgColorTable)
                {
                    StructUtil.SerializeTo(p, buffer, ref offset);
                }
            }

            Marshal.Copy((IntPtr)sourceBufferStart, buffer, (int)offset, (int)vinfo.bV5SizeImage);
        }

        return(buffer);
    }
예제 #5
0
 public BITMAPINFOHEADER(int width, int height, ushort bitCount)
 {
     biSize = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADER));
     biWidth = width;
     biHeight = height;
     biPlanes = 1;
     biBitCount = bitCount;
     biCompression = BitmapCompressionMode.BI_RGB;
     biSizeImage = 0;
     biXPelsPerMeter = 0;
     biYPelsPerMeter = 0;
     biClrUsed = 0;
     biClrImportant = 0;
 }