/// <summary> /// Renders a bitmap to a DIB bitmap in HGLOBAL format. It is neccessary that the provided bitmap has a pixel format of PixelFormat.Format24bppRgb. /// </summary> /// <param name="bitmap">The provided bitmap. Must have PixelFormat.Format24bppRgb.</param> /// <returns>HGLOBAL pointer to the DIB bitmap.</returns> public static IntPtr RenderDIBBitmapToHGLOBAL(Bitmap bitmap) { if (null == bitmap) { throw new ArgumentNullException("bitmap"); } if (bitmap.PixelFormat != PixelFormat.Format24bppRgb) { throw new ArgumentException(string.Format("bitmap must have PixelFormat.Format24bppRgb, but it has {0}", bitmap.PixelFormat)); } var bmpStream = new System.IO.MemoryStream(); // ImageFormat.MemoryBmp work (will save to PNG!). Therefore use BMP and strip header. bitmap.Save(bmpStream, ImageFormat.Bmp); byte[] bmpBytes = bmpStream.ToArray(); int offset = Marshal.SizeOf(typeof(BITMAPFILEHEADER)); IntPtr hdib = Kernel32Func.GlobalAlloc(GlobalAllocFlags.GHND, (int)(bmpStream.Length - offset)); if (!(hdib != IntPtr.Zero)) { throw new InvalidOperationException("GlobalAlloc operation was not successful"); } IntPtr buf = Kernel32Func.GlobalLock(hdib); Marshal.Copy(bmpBytes, offset, buf, (int)bmpStream.Length - offset); Kernel32Func.GlobalUnlock(hdib); return(hdib); }
public static IntPtr RenderLinkedObjectDescriptor(TYMED tymed) { ComDebug.ReportInfo("GraphDocumentDataObject.RenderLinkedObjectDescriptor"); // Brockschmidt, Inside Ole 2nd ed. page 991 if (!(tymed == TYMED.TYMED_HGLOBAL)) { throw new ArgumentException(nameof(tymed) + " is not TYMED_HGLOBAL"); } // Fill in the basic information. var od = new OBJECTDESCRIPTOR { // According to the documentation this is used just to find an icon. clsid = typeof(GraphDocumentLinkedComObject).GUID, dwDrawAspect = DVASPECT.DVASPECT_CONTENT, sizelcx = 0, // zero in imitation of Word/Excel, but could be box.Extent.cx; sizelcy = 0, // zero in imitation of Word/Excel, but could be box.Extent.cy; pointlx = 0, pointly = 0 }; od.dwStatus = MiscStatus((int)od.dwDrawAspect); // Descriptive strings to tack on after the struct. string name = GraphDocumentLinkedComObject.USER_TYPE; int name_size = (name.Length + 1) * sizeof(char); string source = "Altaxo"; int source_size = (source.Length + 1) * sizeof(char); int od_size = Marshal.SizeOf(typeof(OBJECTDESCRIPTOR)); od.dwFullUserTypeName = od_size; od.dwSrcOfCopy = od_size + name_size; int full_size = od_size + name_size + source_size; od.cbSize = full_size; // To avoid 'unsafe', we will arrange the strings in a byte array. byte[] strings = new byte[full_size]; Encoding unicode = Encoding.Unicode; Array.Copy(unicode.GetBytes(name), 0, strings, od.dwFullUserTypeName, name.Length * sizeof(char)); Array.Copy(unicode.GetBytes(source), 0, strings, od.dwSrcOfCopy, source.Length * sizeof(char)); // Combine the strings and the struct into a single block of mem. IntPtr hod = Kernel32Func.GlobalAlloc(GlobalAllocFlags.GHND, full_size); if (!(hod != IntPtr.Zero)) { throw new InvalidOperationException("GlobalAlloc operation was not successful"); } IntPtr buf = Kernel32Func.GlobalLock(hod); Marshal.Copy(strings, 0, buf, full_size); Marshal.StructureToPtr(od, buf, false); Kernel32Func.GlobalUnlock(hod); return(hod); }
/// <summary> /// Renders a bitmap to a DIBV5 bitmap in HGLOBAL format. It is neccessary that the provided bitmap has a pixel format of PixelFormat.Format32bppRgb. /// </summary> /// <param name="bm">The provided bitmap. Must have PixelFormat.Format24bppRgb.</param> /// <returns>HGLOBAL pointer to the DIB bitmap.</returns> /// <remarks> /// See <see href="https://groups.google.com/forum/#!msg/microsoft.public.dotnet.framework.drawing/0sSPCrzf8yE/WNEIU324YtwJ"/> for the original source code and the discussion./> /// </remarks> public static IntPtr RenderDIBV5BitmapToHGLOBAL(Bitmap bm) { BitmapData bmData = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadOnly, bm.PixelFormat); int bufferLen = (Marshal.SizeOf(typeof(BITMAPV5HEADER)) + bmData.Height * bmData.Stride); IntPtr hMem = Kernel32Func.GlobalAlloc(GlobalAllocFlags.GHND, bufferLen); IntPtr packedDIBV5 = Kernel32Func.GlobalLock(hMem); var bmi = (BITMAPV5HEADER)Marshal.PtrToStructure(packedDIBV5, typeof(BITMAPV5HEADER)); bmi.bV5Size = (uint)Marshal.SizeOf(typeof(BITMAPV5HEADER)); bmi.bV5Width = bmData.Width; bmi.bV5Height = -bmData.Height; // Top-down bitmap requires negative height bmi.bV5BitCount = 32; bmi.bV5Planes = 1; bmi.bV5Compression = (uint)BiCompression.BI_RGB; bmi.bV5XPelsPerMeter = (int)(bm.HorizontalResolution * (10000 / 254.0)); bmi.bV5YPelsPerMeter = (int)(bm.VerticalResolution * (10000 / 254.0)); bmi.bV5ClrUsed = 0; bmi.bV5ClrImportant = 0; bmi.bV5BlueMask = 0x000000FF; bmi.bV5GreenMask = 0x0000FF00; bmi.bV5RedMask = 0x00FF0000; bmi.bV5AlphaMask = 0xFF000000; bmi.bV5CSType = (uint)LcsCsType.LCS_WINDOWS_COLOR_SPACE; bmi.bV5GammaBlue = 0; bmi.bV5GammaGreen = 0; bmi.bV5GammaRed = 0; bmi.bV5ProfileData = 0; bmi.bV5ProfileSize = 0; bmi.bV5Reserved = 0; bmi.bV5Intent = (uint)LcsIntent.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); int offsetBits = (int)bmi.bV5Size; var bits = IntPtr.Add(packedDIBV5, offsetBits); Kernel32Func.CopyMemory(bits, bmData.Scan0, (uint)(bmData.Height * bmData.Stride)); bm.UnlockBits(bmData); Kernel32Func.GlobalUnlock(hMem); return(hMem); }
/// <summary> /// Converts an enhanced metafile to a windows metafile picture (CF_MFPICT). Please note that the provided enhanced metafile should neither contain /// transparancies nor splines. Thus it is best if the provided enhanced metafile contains only an embedded bitmap in 24bppRGB format. /// </summary> /// <param name="hEmf">The handle to the enhanced metafile.</param> /// <param name="docSizeX">The document size x in points.</param> /// <param name="docSizeY">The document size y in points.</param> /// <returns>Handle to a windows meta file picture (CF_MFPICT).</returns> public static IntPtr ConvertEnhancedMetafileToWindowsMetafilePict(IntPtr hEmf, double docSizeX, double docSizeY) { byte[] buffer = ConvertEnhancedMetafileToWindowsMetafileBytes(hEmf); // Get a handle to the converted metafile. IntPtr hmf = Gdi32Func.SetMetaFileBitsEx((uint)buffer.Length, buffer); // Convert the Metafile to a METAFILEPICT. IntPtr hMem = Kernel32Func.GlobalAlloc(GlobalAllocFlags.GHND, Marshal.SizeOf(typeof(METAFILEPICT))); var mfp = new METAFILEPICT() { mm = MappingMode.MM_ANISOTROPIC, xExt = PointToHimetric(docSizeX), yExt = PointToHimetric(docSizeY), hMF = hmf }; Marshal.StructureToPtr(mfp, Kernel32Func.GlobalLock(hMem), false); Kernel32Func.GlobalUnlock(hMem); return(hMem); }