예제 #1
0
        internal void CreateNativeContext()
        {
            var bmh = new BITMAPV5HEADER()
            {
                bV5Size        = (uint)Marshal.SizeOf(typeof(BITMAPV5HEADER)),
                bV5Width       = Size.Width,
                bV5Height      = -Size.Height,
                bV5Planes      = 1,
                bV5BitCount    = 32,
                bV5Compression = BitmapCompressionMode.BI_RGB,
                bV5AlphaMask   = ColorMask.Alpha,
                bV5RedMask     = ColorMask.Red,
                bV5GreenMask   = ColorMask.Green,
                bV5BlueMask    = ColorMask.Blue
            };

            blendFunc = new BLENDFUNCTION()
            {
                BlendOp             = AC_SRC_OVER,
                BlendFlags          = 0,
                SourceConstantAlpha = 255,
                AlphaFormat         = AC_SRC_ALPHA
            };

            screenDc = GetDC(IntPtr.Zero);
            memDc    = CreateCompatibleDC(screenDc);

            native    = CreateDIBSection(screenDc, ref bmh, 0, out scan0, IntPtr.Zero, 0);
            oldBitmap = SelectObject(memDc, native);
        }
예제 #2
0
        internal Cursor CreateCursor(BitmapSource renderBitmap, int width, int height)
        {
            // unfortunately, this byte array will get placed on the large object heap more than likely ...
            byte[] pixels = GetBitmapPixels(renderBitmap, width, height);

            // -height specifies top-down bitmap
            BITMAPV5HEADER bInfo = new BITMAPV5HEADER(width, -height, 32);
            IntPtr ppvBits = IntPtr.Zero;
            BitmapHandle dibSectionHandle = null;

            try
            {
                dibSectionHandle = new BitmapHandle(CreateDIBSection(IntPtr.Zero, ref bInfo, DIB_RGB_COLORS, out ppvBits, IntPtr.Zero, 0));

                // copy the pixels into the DIB section now ...
                Marshal.Copy(pixels, 0, ppvBits, pixels.Length);

                if (!dibSectionHandle.IsInvalid && ppvBits != IntPtr.Zero)
                {
                    return CreateCursor(width, height, dibSectionHandle);
                }
            }
            finally
            {
                if (dibSectionHandle != null)
                {
                    dibSectionHandle.Dispose();
                }
            }

            return null;
        }
예제 #3
0
        public uint GetImageSizeFromBitmapHeader(BITMAPV5HEADER bmi)
        {
            var imageSize = bmi.bV5SizeImage;

            if (bmi.bV5Compression == 0)
            {
                imageSize = (uint)(bmi.bV5Height * bmi.bV5Width * (bmi.bV5BitCount / 8));
            }

            return(imageSize);
        }
예제 #4
0
        static Bitmap CreateDrawingBitmapFromVersionOnePointer(IntPtr pointer, BITMAPV5HEADER infoHeader)
        {
            var stride = (int)(infoHeader.bV5SizeImage / infoHeader.bV5Height);
            var bitmap = new Bitmap(
                infoHeader.bV5Width,
                infoHeader.bV5Height,
                stride,
                infoHeader.bV5BitCount == 24 ? DrawingPixelFormat.Format24bppRgb : DrawingPixelFormat.Format32bppPArgb,
                new IntPtr(pointer.ToInt64() + infoHeader.bV5Size));

            return(ConvertBitmapTo32Bit(bitmap));
        }
예제 #5
0
        private static void SetClipboardBitmap(Bitmap bitmap, byte[] pngData)
        {
            // https://stackoverflow.com/questions/15689541/win32-clipboard-and-alpha-channel-images
#if !USE_V5_BITMAP_HEADER
            bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); // GDI+ bitmap data is flipped vertically, unflip before accessing bytes
            BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            BITMAPINFOHEADER header = new BITMAPINFOHEADER();
            header.biSize        = Marshal.SizeOf(header);
            header.biWidth       = bitmap.Width;
            header.biHeight      = bitmap.Height;
            header.biPlanes      = 1;
            header.biBitCount    = 32;
            header.biCompression = (int)BitmapCompressionMode.BI_RGB;
            header.biSizeImage   = bitmap.Width * bitmap.Height * 4;

            IntPtr hGlobal = Marshal.AllocHGlobal(Marshal.SizeOf(header) + header.biSizeImage);
            Marshal.StructureToPtr(header, hGlobal, false);
            memcpy(hGlobal + Marshal.SizeOf(header), data.Scan0, (uint)header.biSizeImage);
            SetClipboardData((uint)ClipboardType.CF_DIB, hGlobal);
            Marshal.FreeHGlobal(hGlobal);

            bitmap.UnlockBits(data);
#else
            bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); // GDI+ bitmap data is flipped vertically, unflip before accessing bytes
            BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            BITMAPV5HEADER header = new BITMAPV5HEADER();
            header.bV5Size        = Marshal.SizeOf(header);
            header.bV5Width       = bitmap.Width;
            header.bV5Height      = bitmap.Height;
            header.bV5Planes      = 1;
            header.bV5BitCount    = 32;
            header.bV5Compression = (int)BitmapCompressionMode.BI_BITFIELDS;
            header.bV5SizeImage   = bitmap.Width * bitmap.Height * 4;
            header.bV5RedMask     = 0x00FF0000;
            header.bV5GreenMask   = 0x0000FF00;
            header.bV5BlueMask    = 0x000000FF;
            header.bV5AlphaMask   = 0xFF000000;
            header.bV5CSType      = (uint)LogicalColorSpace.LCS_WINDOWS_COLOR_SPACE;
            header.bV5Intent      = (uint)GamutMappingIntent.LCS_GM_IMAGES;

            IntPtr hGlobal = Marshal.AllocHGlobal(Marshal.SizeOf(header) + header.bV5SizeImage);
            Marshal.StructureToPtr(header, hGlobal, false);
            //Marshal.Copy(pngData, 0, hGlobal + Marshal.SizeOf(header), pngData.Length);
            memcpy(hGlobal + Marshal.SizeOf(header), data.Scan0, (uint)header.bV5SizeImage);
            SetClipboardData((uint)ClipboardType.CF_DIBV5, hGlobal);
            Marshal.FreeHGlobal(hGlobal);

            bitmap.UnlockBits(data);
#endif
        }
예제 #6
0
        const int CBM_INIT = 0x04;//   /* initialize bitmap */

        public static IntPtr Create32BppBitmap(Image sourceImage)
        {
            BITMAPV5HEADER bi = new BITMAPV5HEADER();

            bi.bV5Size        = (uint)Marshal.SizeOf(bi);
            bi.bV5Width       = sourceImage.Width;
            bi.bV5Height      = sourceImage.Height;
            bi.bV5Planes      = 1;
            bi.bV5BitCount    = 32;
            bi.bV5Compression = BI_BITFIELDS;
            // The following mask specification specifies a supported 32 BPP
            // alpha format for Windows XP.
            bi.bV5RedMask   = 0x00FF0000;
            bi.bV5GreenMask = 0x0000FF00;
            bi.bV5BlueMask  = 0x000000FF;
            bi.bV5AlphaMask = 0xFF000000;

            IntPtr hdc  = User32.GetDC(IntPtr.Zero);
            IntPtr bits = IntPtr.Zero;

            // Create the DIB section with an alpha channel.
            IntPtr hBitmap = Gdi32.CreateDIBSection(hdc, bi, (uint)DIB.DIB_RGB_COLORS,
                                                    out bits, IntPtr.Zero, 0);

            var hMemDC = Gdi32.CreateCompatibleDC(hdc);

            Gdi32.ReleaseDC(IntPtr.Zero, hdc);

            var sourceBits = ((Bitmap)sourceImage).LockBits(
                new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), ImageLockMode.ReadOnly,
                PixelFormat.Format32bppArgb);

            var stride = sourceImage.Width * 4;

            for (int y = 0; y < sourceImage.Height; y++)
            {
                IntPtr DstDib = (IntPtr)(bits.ToInt32() + (y * stride));
                IntPtr SrcDib = (IntPtr)(sourceBits.Scan0.ToInt32() + ((sourceImage.Height - 1 - y) *
                                                                       stride));

                for (int x = 0; x < sourceImage.Width; x++)
                {
                    Marshal.WriteInt32(DstDib, Marshal.ReadInt32(SrcDib));
                    DstDib = (IntPtr)(DstDib.ToInt32() + 4);
                    SrcDib = (IntPtr)(SrcDib.ToInt32() + 4);
                }
            }

            return(hBitmap);
        }
예제 #7
0
        byte[] GetImageBytesFromAllBytes(byte[] bytes, BITMAPV5HEADER bmi)
        {
            var stride = GetStrideFromBitmapHeader(bmi);

            var offset = bmi.bV5Size;

            if (bmi.bV5ClrUsed > 0)
            {
                offset += bmi.bV5ClrUsed * (uint)Marshal.SizeOf <RGBQUAD>();
            }

            var imageSize  = imageNativeApi.GetImageSizeFromBitmapHeader(bmi);
            var imageBytes = new byte[imageSize];

            Array.Copy(bytes, offset, imageBytes, 0, imageBytes.Length);

            return(imageBytes);
        }
예제 #8
0
파일: mscms.cs 프로젝트: clowd/bmplib
    public static unsafe SafeProfileHandle CreateProfileFromLogicalColorSpace(BITMAPV5HEADER info)
    {
        // https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-logcolorspacew
        var lcs = new LOGCOLORSPACE
        {
            lcsCSType       = ColorSpaceType.LCS_CALIBRATED_RGB,
            lcsVersion      = 0x400,
            lcsSignature    = 0x50534F43, // 'PSOC'
            lcsFilename     = "\0",
            lcsIntent       = info.bV5Intent,
            lcsEndpoints_1x = info.bV5Endpoints_1x,
            lcsEndpoints_1y = info.bV5Endpoints_1y,
            lcsEndpoints_1z = info.bV5Endpoints_1z,
            lcsEndpoints_2x = info.bV5Endpoints_2x,
            lcsEndpoints_2y = info.bV5Endpoints_2y,
            lcsEndpoints_2z = info.bV5Endpoints_2z,
            lcsEndpoints_3x = info.bV5Endpoints_3x,
            lcsEndpoints_3y = info.bV5Endpoints_3y,
            lcsEndpoints_3z = info.bV5Endpoints_3z,
            lcsGammaBlue    = info.bV5GammaBlue,
            lcsGammaGreen   = info.bV5GammaGreen,
            lcsGammaRed     = info.bV5GammaRed,
        };

        var success = CreateProfileFromLogColorSpace(ref lcs, out var hGlobal);

        if (!success)
        {
            throw new Win32Exception();
        }

        var hsize = GlobalSize(hGlobal);
        var hptr  = GlobalLock(hGlobal);

        try
        {
            return(OpenProfile((void *)hptr, (uint)hsize));
        }
        finally
        {
            GlobalUnlock(hGlobal);
            GlobalFree(hGlobal);
        }
    }
예제 #9
0
        private static void WriteDibV5ToStream(Stream stream, Bitmap image, byte[] imageData)
        {
            BITMAPV5HEADER bmi = new BITMAPV5HEADER {
                bV5Size     = Marshal.SizeOf <BITMAPV5HEADER>(),
                bV5Width    = image.Width,
                bV5Height   = image.Height,
                bV5Planes   = 1,
                bV5BitCount = 32,
                //bV5Compression = 3,
                bV5SizeImage = imageData.Length,
                bV5RedMask   = 0x00FF0000,
                bV5GreenMask = 0x0000FF00,
                bV5BlueMask  = 0x000000FF,
                bV5AlphaMask = 0xFF000000,
                bV5CSType    = 0x73524742,             // LCS_WINDOWS_COLOR_SPACE;
                //bV5CSType = 0x206E6957,// GLITCHED
                bV5Intent = 4,
            };

            /*BITMAPV5HEADER bmi = new BITMAPV5HEADER();
             * bmi.bV5Size = Marshal.SizeOf<BITMAPV5HEADER>();
             * bmi.bV5Width = image.Width;
             * bmi.bV5Height = image.Height;
             * bmi.bV5Planes = 1;
             * bmi.bV5BitCount = 32;
             * //bmi.bV5Compression = 3;
             * bmi.bV5SizeImage = imageData.Length;
             * bmi.bV5RedMask   = 0x00FF0000;
             * bmi.bV5GreenMask = 0x0000FF00;
             * bmi.bV5BlueMask  = 0x000000FF;
             * bmi.bV5AlphaMask = 0xFF000000;
             * bmi.bV5CSType = 0x73524742;// LCS_WINDOWS_COLOR_SPACE;
             * //bmi.bV5CSType = 0x206E6957;// GLITCHED
             * bmi.bV5Intent = 4;*/

            BinaryWriter writer = new BinaryWriter(stream);

            writer.WriteUnmanaged(bmi);

            /*writer.Write(0x000001E0);
            *  writer.Write(0x000001E0);
            *  writer.Write(0x00FF0000);*/
            writer.Write(imageData);
        }
예제 #10
0
        public GhostCursor(Visual visual)
        {
            BitmapSource renderBitmap = CaptureScreen(visual);

            BitmapSource actualCursor = CaptureCursor();

            byte[]          pixels = GetBitmapPixels(actualCursor, (int)actualCursor.Width, (int)actualCursor.Height);
            WriteableBitmap wrbmp  = new WriteableBitmap(renderBitmap);

            wrbmp.WritePixels(new Int32Rect(0, 0, (int)actualCursor.Width, (int)actualCursor.Height), pixels, actualCursor.PixelWidth * actualCursor.Format.BitsPerPixel / 8, 0);

            int width  = renderBitmap.PixelWidth;
            int height = renderBitmap.PixelHeight;
            int stride = width * 4;

            // unfortunately, this byte array will get placed on the large object heap more than likely ...
            pixels = GetBitmapPixels(wrbmp, width, height);

            // -height specifies top-down bitmap
            BITMAPV5HEADER bInfo            = new BITMAPV5HEADER(width, -height, 32);
            IntPtr         ppvBits          = IntPtr.Zero;
            BitmapHandle   dibSectionHandle = null;

            try
            {
                dibSectionHandle = new BitmapHandle(CreateDIBSection(IntPtr.Zero, ref bInfo, DIB_RGB_COLORS, out ppvBits, IntPtr.Zero, 0));

                // copy the pixels into the DIB section now ...
                Marshal.Copy(pixels, 0, ppvBits, pixels.Length);


                if (!dibSectionHandle.IsInvalid && ppvBits != IntPtr.Zero)
                {
                    CreateCursor(width, height, dibSectionHandle);
                }
            }
            finally
            {
                if (dibSectionHandle != null)
                {
                    dibSectionHandle.Dispose();
                }
            }
        }
예제 #11
0
        byte[] HandleBitmapVersionFive(IntPtr pointer, BITMAPV5HEADER infoHeader)
        {
            using (var drawingBitmap = CreateDrawingBitmapFromVersionOnePointer(pointer, infoHeader))
            {
                var renderTargetBitmapSource = new RenderTargetBitmap(infoHeader.bV5Width,
                                                          infoHeader.bV5Height,
                                                          96, 96, PixelFormats.Pbgra32);
                var visual = new DrawingVisual();
                var drawingContext = visual.RenderOpen();

                drawingContext.DrawImage(CreateBitmapSourceFromBitmap(drawingBitmap),
                                         new Rect(0, 0, infoHeader.bV5Width,
                                                  infoHeader.bV5Height));

                renderTargetBitmapSource.Render(visual);

                return imagePersistenceService.ConvertBitmapSourceToByteArray(renderTargetBitmapSource);
            }
        }
예제 #12
0
        byte[] HandleBitmapVersionFive(IntPtr pointer, BITMAPV5HEADER infoHeader)
        {
            using (var drawingBitmap = CreateDrawingBitmapFromVersionOnePointer(pointer, infoHeader))
            {
                var renderTargetBitmapSource = new RenderTargetBitmap(infoHeader.bV5Width,
                                                                      infoHeader.bV5Height,
                                                                      96, 96, PixelFormats.Pbgra32);
                var visual         = new DrawingVisual();
                var drawingContext = visual.RenderOpen();

                drawingContext.DrawImage(CreateBitmapSourceFromBitmap(drawingBitmap),
                                         new Rect(0, 0, infoHeader.bV5Width,
                                                  infoHeader.bV5Height));

                renderTargetBitmapSource.Render(visual);

                return(imagePersistenceService.ConvertBitmapSourceToByteArray(renderTargetBitmapSource));
            }
        }
예제 #13
0
        public GhostCursor(Visual visual)
        {
            BitmapSource renderBitmap = CaptureScreen(visual);

            BitmapSource actualCursor = CaptureCursor();
            byte[] pixels = GetBitmapPixels(actualCursor, (int)actualCursor.Width, (int)actualCursor.Height);
            WriteableBitmap wrbmp = new WriteableBitmap(renderBitmap);
            wrbmp.WritePixels(new Int32Rect(0, 0, (int)actualCursor.Width, (int)actualCursor.Height), pixels, actualCursor.PixelWidth * actualCursor.Format.BitsPerPixel / 8, 0);

            int width = renderBitmap.PixelWidth;
            int height = renderBitmap.PixelHeight;
            int stride = width * 4;

            // unfortunately, this byte array will get placed on the large object heap more than likely ...
            pixels = GetBitmapPixels(wrbmp, width, height);

            // -height specifies top-down bitmap
            BITMAPV5HEADER bInfo = new BITMAPV5HEADER(width, -height, 32);
            IntPtr ppvBits = IntPtr.Zero;
            BitmapHandle dibSectionHandle = null;

            try
            {
                dibSectionHandle = new BitmapHandle(CreateDIBSection(IntPtr.Zero, ref bInfo, DIB_RGB_COLORS, out ppvBits, IntPtr.Zero, 0));

                // copy the pixels into the DIB section now ...
                Marshal.Copy(pixels, 0, ppvBits, pixels.Length);

                if (!dibSectionHandle.IsInvalid && ppvBits != IntPtr.Zero)
                {
                    CreateCursor(width, height, dibSectionHandle);
                }
            }
            finally
            {
                if (dibSectionHandle != null)
                {
                    dibSectionHandle.Dispose();
                }
            }
        }
예제 #14
0
        internal void CreateNativeContext()
        {
            var bmh = new BITMAPV5HEADER()
            {
                bV5Size        = (uint)Marshal.SizeOf(typeof(BITMAPV5HEADER)),
                bV5Width       = Size.Width,
                bV5Height      = -Size.Height,
                bV5Planes      = 1,
                bV5BitCount    = 32,
                bV5Compression = BitmapCompressionMode.BI_RGB,
                bV5AlphaMask   = ColorMask.Alpha,
                bV5RedMask     = ColorMask.Red,
                bV5GreenMask   = ColorMask.Green,
                bV5BlueMask    = ColorMask.Blue
            };

            screenDc  = GetDC(IntPtr.Zero);
            Skia_DC   = CreateCompatibleDC(screenDc);
            native    = CreateDIBSection(screenDc, ref bmh, 0, out scan0, IntPtr.Zero, 0);
            oldBitmap = SelectObject(Skia_DC, native);
        }
예제 #15
0
            const int CBM_INIT = 0x04;            //   /* initialize bitmap */

            /*public static IntPtr Create32BppBitmap(Image sourceImage) {
             *      BITMAPV5HEADER bi = new BITMAPV5HEADER();
             *      bi.bV5Size = (uint) Marshal.SizeOf(bi);
             *      bi.bV5Width = sourceImage.Width;
             *      bi.bV5Height = sourceImage.Height;
             *      bi.bV5Planes = 1;
             *      bi.bV5BitCount = 32;
             *      bi.bV5Compression = BI_BITFIELDS;
             *      // The following mask specification specifies a supported 32 BPP
             *      // alpha format for Windows XP.
             *      bi.bV5RedMask = 0x00FF0000;
             *      bi.bV5GreenMask = 0x0000FF00;
             *      bi.bV5BlueMask = 0x000000FF;
             *      bi.bV5AlphaMask = 0xFF000000;
             *
             *      IntPtr hdc = User32.GetDC(IntPtr.Zero);
             *      IntPtr bits = IntPtr.Zero;
             *
             *      // Create the DIB section with an alpha channel.
             *      IntPtr hBitmap = Gdi32.CreateDIBSection(hdc, bi, (uint) DIB.DIB_RGB_COLORS,
             *                                                                                      out bits, IntPtr.Zero, 0);
             *
             *      var hMemDC = Gdi32.CreateCompatibleDC(hdc);
             *      Gdi32.ReleaseDC(IntPtr.Zero, hdc);
             *
             *      var sourceBits = ((Bitmap) sourceImage).LockBits(
             *              new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), ImageLockMode.ReadOnly,
             *              PixelFormat.Format32bppArgb);
             *
             *      var stride = sourceImage.Width*4;
             *      for (int y = 0; y < sourceImage.Height; y++) {
             *              IntPtr DstDib = (IntPtr) (bits.ToInt32() + (y * stride));
             *              IntPtr SrcDib = (IntPtr) (sourceBits.Scan0.ToInt32() + ((sourceImage.Height - 1 - y) *
             *                                                                                                                         stride));
             *
             *              for (int x = 0; x < sourceImage.Width; x++) {
             *                      Marshal.WriteInt32(DstDib, Marshal.ReadInt32(SrcDib));
             *                      DstDib = (IntPtr) (DstDib.ToInt32() + 4);
             *                      SrcDib = (IntPtr) (SrcDib.ToInt32() + 4);
             *              }
             *      }
             *
             *      return hBitmap;
             * }*/

            public static byte[] CreatePackedDIBV5(Bitmap image)
            {
                BitmapData bmData;

                using (Bitmap bm32b = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb)) {
                    using (Graphics g = Graphics.FromImage(bm32b))
                        g.DrawImage(image, new Rectangle(0, 0, bm32b.Width, bm32b.Height));
                    // Bitmap format has its lines reversed.
                    bm32b.RotateFlip(RotateFlipType.Rotate180FlipX);
                    bmData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
                                            ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
                }
                uint bufferLen = (uint)(Marshal.SizeOf(typeof(BITMAPV5HEADER)) +
                                        (Marshal.SizeOf(typeof(uint)) * 3) + bmData.Height * bmData.Stride);
                //IntPtr hMem = GlobalAlloc(GHND | GMEM_DDESHARE, bufferLen);
                //IntPtr packedDIBV5 = GlobalLock(hMem);
                BITMAPV5HEADER bmi = new BITMAPV5HEADER();                // (BITMAPV5HEADER) Marshal.PtrToStructure(packedDIBV5,

                //				 typeof(BITMAPV5HEADER));
                bmi.bV5Size          = (uint)Marshal.SizeOf(typeof(BITMAPV5HEADER));
                bmi.bV5Width         = bmData.Width;
                bmi.bV5Height        = bmData.Height;
                bmi.bV5BitCount      = 32;
                bmi.bV5Planes        = 1;
                bmi.bV5Compression   = 0;              // BI_BITFIELDS;
                bmi.bV5XPelsPerMeter = 0;
                bmi.bV5YPelsPerMeter = 0;
                bmi.bV5ClrUsed       = 0;
                bmi.bV5ClrImportant  = 0;
                bmi.bV5RedMask       = 0x000000FF;
                bmi.bV5GreenMask     = 0x0000FF00;
                bmi.bV5BlueMask      = 0x00FF0000;
                bmi.bV5AlphaMask     = 0xFF000000;
                bmi.bV5CSType        = 0x206E6957;         // LCS_WINDOWS_COLOR_SPACE;
                bmi.bV5GammaBlue     = 0;
                bmi.bV5GammaGreen    = 0;
                bmi.bV5GammaRed      = 0;
                bmi.bV5ProfileData   = 0;
                bmi.bV5ProfileSize   = 0;
                bmi.bV5Reserved      = 0;
                bmi.bV5Intent        = 0;         // LCS_GM_IMAGES;
                bmi.bV5SizeImage     = (uint)(bmData.Height * bmData.Stride);
                bmi.bV5Endpoints.ciexyzBlue.ciexyzX          =
                    bmi.bV5Endpoints.ciexyzBlue.ciexyzY      =
                        bmi.bV5Endpoints.ciexyzBlue.ciexyzZ  = 0;
                bmi.bV5Endpoints.ciexyzGreen.ciexyzX         =
                    bmi.bV5Endpoints.ciexyzGreen.ciexyzY     =
                        bmi.bV5Endpoints.ciexyzGreen.ciexyzZ = 0;
                bmi.bV5Endpoints.ciexyzRed.ciexyzX           =
                    bmi.bV5Endpoints.ciexyzRed.ciexyzY       =
                        bmi.bV5Endpoints.ciexyzRed.ciexyzZ   = 0;
                //Marshal.StructureToPtr(bmi, packedDIBV5, false);

                BITFIELDS Masks = new BITFIELDS();                // (BITFIELDS) Marshal.PtrToStructure(

                //(IntPtr) (packedDIBV5.ToInt32() + bmi.bV5Size), typeof(BITFIELDS));
                Masks.BlueMask  = 0x000000FF;
                Masks.GreenMask = 0x0000FF00;
                Masks.RedMask   = 0x00FF0000;
                //Marshal.StructureToPtr(Masks, (IntPtr) (packedDIBV5.ToInt32() +
                //										bmi.bV5Size), false);

                //byte[] dibData = new byte[bufferLen];
                byte[] imageData = new byte[bmi.bV5SizeImage];

                using (MemoryStream ms = new MemoryStream()) {
                    var writer = new BinaryWriter(ms);
                    writer.WriteStruct(bmi);
                    //writer.WriteStruct(Masks);
                    Marshal.Copy(bmData.Scan0, imageData, 0, imageData.Length);
                    writer.Write(imageData);
                    return(ms.ToArray());
                }

                /*long offsetBits = bmi.bV5Size + Marshal.SizeOf(typeof(uint))*3;
                 * IntPtr bits = (IntPtr) (packedDIBV5.ToInt32() + offsetBits);
                 *
                 * for (int y = 0; y < bmData.Height; y++) {
                 *      IntPtr DstDib = (IntPtr) (bits.ToInt32() + (y*bmData.Stride));
                 *      IntPtr SrcDib = (IntPtr) (bmData.Scan0.ToInt32() + ((bmData.Height - 1 - y)*
                 *                                                                                                              bmData.Stride));
                 *
                 *      for (int x = 0; x < bmData.Width; x++) {
                 *              Marshal.WriteInt32(DstDib, Marshal.ReadInt32(SrcDib));
                 *              DstDib = (IntPtr) (DstDib.ToInt32() + 4);
                 *              SrcDib = (IntPtr) (SrcDib.ToInt32() + 4);
                 *      }
                 * }
                 *
                 * // Create the DIB section with an alpha channel.
                 * IntPtr hdc = User32.GetDC(IntPtr.Zero);
                 * //IntPtr hdc = Gdi32.CreateCompatibleDC(IntPtr.Zero);
                 * GCHandle handle = GCHandle.Alloc(bmi, GCHandleType.Pinned);
                 * IntPtr hBitmap = Gdi32.CreateDIBitmap(hdc, handle.AddrOfPinnedObject(), CBM_INIT,
                 *                                                                        bits, handle.AddrOfPinnedObject(), (uint) DIB.DIB_RGB_COLORS);
                 * bm.UnlockBits(bmData);
                 *
                 * GlobalUnlock(hMem);
                 *
                 *
                 * return hBitmap;*/
            }
예제 #16
0
 internal static extern IntPtr CreateDIBSection(IntPtr hdc, [In] ref BITMAPV5HEADER pbmi,
                                                uint iUsage, out IntPtr ppvBits, IntPtr hSection, uint dwOffset);
예제 #17
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);
    }
예제 #18
0
 public static extern IntPtr CreateDIBSection(IntPtr hdc, [In] ref BITMAPV5HEADER pbmi, uint pila, out IntPtr ppvBits, IntPtr hSection, uint dwOffset);
예제 #19
0
        public static IntPtr CreatePackedDIBV5(Bitmap bm)
        {
            BitmapData bmData = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height),
                                            ImageLockMode.ReadOnly, bm.PixelFormat);
            uint bufferLen = (uint)(Marshal.SizeOf(typeof(BITMAPV5HEADER)) +
                                    (Marshal.SizeOf(typeof(uint)) * 3) + bmData.Height * bmData.Stride);
            IntPtr         hMem        = GlobalAlloc(GHND | GMEM_DDESHARE, bufferLen);
            IntPtr         packedDIBV5 = GlobalLock(hMem);
            BITMAPV5HEADER bmi         = (BITMAPV5HEADER)Marshal.PtrToStructure(packedDIBV5,
                                                                                typeof(BITMAPV5HEADER));

            bmi.bV5Size          = (uint)Marshal.SizeOf(typeof(BITMAPV5HEADER));
            bmi.bV5Width         = bmData.Width;
            bmi.bV5Height        = bmData.Height;
            bmi.bV5BitCount      = 32;
            bmi.bV5Planes        = 1;
            bmi.bV5Compression   = BI_BITFIELDS;
            bmi.bV5XPelsPerMeter = 0;
            bmi.bV5YPelsPerMeter = 0;
            bmi.bV5ClrUsed       = 0;
            bmi.bV5ClrImportant  = 0;
            bmi.bV5BlueMask      = 0x000000FF;
            bmi.bV5GreenMask     = 0x0000FF00;
            bmi.bV5RedMask       = 0x00FF0000;
            bmi.bV5AlphaMask     = 0xFF000000;
            bmi.bV5CSType        = LCS_WINDOWS_COLOR_SPACE;
            bmi.bV5GammaBlue     = 0;
            bmi.bV5GammaGreen    = 0;
            bmi.bV5GammaRed      = 0;
            bmi.bV5ProfileData   = 0;
            bmi.bV5ProfileSize   = 0;
            bmi.bV5Reserved      = 0;
            bmi.bV5Intent        = LCS_GM_IMAGES;
            bmi.bV5SizeImage     = (uint)(bmData.Height * bmData.Stride);
            bmi.bV5Endpoints.ciexyzBlue.ciexyzX          =
                bmi.bV5Endpoints.ciexyzBlue.ciexyzY      =
                    bmi.bV5Endpoints.ciexyzBlue.ciexyzZ  = 0;
            bmi.bV5Endpoints.ciexyzGreen.ciexyzX         =
                bmi.bV5Endpoints.ciexyzGreen.ciexyzY     =
                    bmi.bV5Endpoints.ciexyzGreen.ciexyzZ = 0;
            bmi.bV5Endpoints.ciexyzRed.ciexyzX           =
                bmi.bV5Endpoints.ciexyzRed.ciexyzY       =
                    bmi.bV5Endpoints.ciexyzRed.ciexyzZ   = 0;
            Marshal.StructureToPtr(bmi, packedDIBV5, false);

            BITFIELDS Masks = (BITFIELDS)Marshal.PtrToStructure(
                (IntPtr)(packedDIBV5.ToInt32() + bmi.bV5Size), typeof(BITFIELDS));

            Masks.BlueMask  = 0x000000FF;
            Masks.GreenMask = 0x0000FF00;
            Masks.RedMask   = 0x00FF0000;
            Marshal.StructureToPtr(Masks, (IntPtr)(packedDIBV5.ToInt32() +
                                                   bmi.bV5Size), false);

            long   offsetBits = bmi.bV5Size + Marshal.SizeOf(typeof(uint)) * 3;
            IntPtr bits       = (IntPtr)(packedDIBV5.ToInt32() + offsetBits);


            for (int y = 0; y < bmData.Height; y++)
            {
                IntPtr DstDib = (IntPtr)(bits.ToInt32() + (y * bmData.Stride));
                IntPtr SrcDib = (IntPtr)(bmData.Scan0.ToInt32() + ((bmData.Height - 1 - y) *
                                                                   bmData.Stride));

                for (int x = 0; x < bmData.Width; x++)
                {
                    Marshal.WriteInt32(DstDib, Marshal.ReadInt32(SrcDib));
                    DstDib = (IntPtr)(DstDib.ToInt32() + 4);
                    SrcDib = (IntPtr)(SrcDib.ToInt32() + 4);
                }
            }

            // Create the DIB section with an alpha channel.
            IntPtr hdc = User32.GetDC(IntPtr.Zero);
            //IntPtr hdc = Gdi32.CreateCompatibleDC(IntPtr.Zero);
            GCHandle handle = GCHandle.Alloc(bmi, GCHandleType.Pinned);

            /*IntPtr hBitmap = Gdi32.CreateDIBSection(hdc, handle.AddrOfPinnedObject(), (uint)SharpThumbnailHandler.DIB.DIB_RGB_COLORS,
             *  out bits, IntPtr.Zero, 0);*/
            IntPtr hBitmap = Gdi32.CreateDIBitmap(hdc, handle.AddrOfPinnedObject(), CBM_INIT,
                                                  bits, handle.AddrOfPinnedObject(), (uint)DIB.DIB_RGB_COLORS);

            bm.UnlockBits(bmData);

            GlobalUnlock(hMem);


            return(hBitmap);
        }
예제 #20
0
 static Bitmap CreateDrawingBitmapFromVersionOnePointer(IntPtr pointer, BITMAPV5HEADER infoHeader)
 {
     var stride = (int)(infoHeader.bV5SizeImage / infoHeader.bV5Height);
     var bitmap = new Bitmap(
         infoHeader.bV5Width,
         infoHeader.bV5Height,
         stride,
         infoHeader.bV5BitCount == 24 ? DrawingPixelFormat.Format24bppRgb : DrawingPixelFormat.Format32bppPArgb,
         new IntPtr(pointer.ToInt64() + infoHeader.bV5Size));
     return ConvertBitmapTo32Bit(bitmap);
 }
예제 #21
0
        int GetStrideFromBitmapHeader(BITMAPV5HEADER bmi)
        {
            var imageSize = imageNativeApi.GetImageSizeFromBitmapHeader(bmi);

            return((int)(imageSize / bmi.bV5Height));
        }