Je veux savoir quel est l'état intermédiaire du tampon où l'objet graphique dessine des trucs. Comment puis-je obtenir la maintien du bitmap ou de l'image qu'il contient? P>
7 Réponses :
Pas à 100% sûr de ce que vous voulez ici, mais si vous souhaitez utiliser la classe graphique pour dessiner, puis enregistrer dans le fichier, vous devez obtenir l'objet graphique dans un fichier bitmap, puis enregistrer le bitmap après que vous soyez terminé. Vous pouvez faire cela comme ceci:
Je ne suis pas vraiment sûr si je comprends ce que vous demandez, comme votre question est très peu claire.
Si vous voulez savoir comment enregistrer le contenu d'un objet code> graphique code> dans un bitmap, la réponse est qu'il n'y a pas d'approche directe pour le faire. Dessin sur un L'option meilleure est de créer un nouvel objet bitmap code>, obtenez un objet code> graphique code> pour ce bitmap et dessinez-le directement sur celui-ci. Le code suivant est un exemple de la façon dont vous pourriez faire cela: P> graphique code> est une opération à sens unique. P>
// Create a new bitmap object
using (Bitmap bmp = new Bitmap(200, 300))
{
// Obtain a Graphics object from that bitmap
using (Graphics g = Graphics.FromImage(bmp))
{
// Draw onto the bitmap here
// ....
g.DrawRectangle(Pens.Red, 10, 10, 50, 50);
}
// Save the bitmap to a file on disk, or do whatever else with it
// ...
bmp.Save("C:\\MyImage.bmp");
}
Ce code travaillant pour moi où je suis convertit Image >> Bitmap >> Byte >> Base64 String.
Je ne sais pas vraiment pourquoi vous avez converti l'image en une chaîne de base64? Je vais accorder que la question n'est pas particulièrement claire, mais je ne vois pas cela mentionné n'importe où i> dedans.
Oui, bien sûr, nous pouvons obtenir l'objet graphique à partir d'un bitmap à l'aide de la méthode graphique.fromImage (). Ce que je cherchais était une API qui me donnerait l'image du bitmap !!
Vous pouvez obtenir son HDC qui est un pointeur sur le tampon de surface et copier éventuellement copier son contenu à un autre HDC avec la fonction BitBlt. De cette façon, vous pouvez créer une copie de la surface de dessin sur un bitmap.
enum TernaryRasterOperations : uint { /// <summary>dest = source</summary> SRCCOPY = 0x00CC0020, /// <summary>dest = source OR dest</summary> SRCPAINT = 0x00EE0086, /// <summary>dest = source AND dest</summary> SRCAND = 0x008800C6, /// <summary>dest = source XOR dest</summary> SRCINVERT = 0x00660046, /// <summary>dest = source AND (NOT dest)</summary> SRCERASE = 0x00440328, /// <summary>dest = (NOT source)</summary> NOTSRCCOPY = 0x00330008, /// <summary>dest = (NOT src) AND (NOT dest)</summary> NOTSRCERASE = 0x001100A6, /// <summary>dest = (source AND pattern)</summary> MERGECOPY = 0x00C000CA, /// <summary>dest = (NOT source) OR dest</summary> MERGEPAINT = 0x00BB0226, /// <summary>dest = pattern</summary> PATCOPY = 0x00F00021, /// <summary>dest = DPSnoo</summary> PATPAINT = 0x00FB0A09, /// <summary>dest = pattern XOR dest</summary> PATINVERT = 0x005A0049, /// <summary>dest = (NOT dest)</summary> DSTINVERT = 0x00550009, /// <summary>dest = BLACK</summary> BLACKNESS = 0x00000042, /// <summary>dest = WHITE</summary> WHITENESS = 0x00FF0062, /// <summary> /// Capture window as seen on screen. This includes layered windows /// such as WPF windows with AllowsTransparency="true" /// </summary> CAPTUREBLT = 0x40000000 } [DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop); public static Bitmap CopyGraphicsContent(Graphics source, Rectangle rect) { Bitmap bmp = new Bitmap(rect.Width, rect.Height); using (Graphics dest = Graphics.FromImage(bmp)) { IntPtr hdcSource = source.GetHdc(); IntPtr hdcDest = dest.GetHdc(); BitBlt(hdcDest, 0, 0, rect.Width, rect.Height, hdcSource, rect.X, rect.Y, TernaryRasterOperations.SRCCOPY); source.ReleaseHdc(hdcSource); dest.ReleaseHdc(hdcDest); } return bmp; }
Puisque personne n'a répondu à la question réelle après 9 ans ... pour arriver aux bits de bitmap fort>, vous devez savoir quelque chose à propos de GDI Bitmaps d'abord . Il y a soi-disant em> bitmaps dépendant du périphérique em> (DDB ou souvent simplement simplement "bitmap" dans l'API) et bitmaps indépendants de l'appareil em> (DIB). Une explication complète de la différence serait hors de portée de cette réponse. P> si vous utilisez Si vous souhaitez manipuler des données de pixels en mémoire, vous devez connaître le format de pixel exact du DIB afin de le manipuler correctement. . Il existe de nombreuses possibilités sur ce que le format de pixel peut être (nombre de bits par pixel 1/4/16/24/32, RVB VS BGR, Palesettes, etc.). C'est beaucoup de travail si vous voulez vraiment tout soutenir em>. p> Pour ce faire, sachez que lorsque vous avez donné un this.settyle (contrôletyle.optimizeddoublebuffer, true); code>, alors l'objet graphique dans < Code> Onpaint Code> utilisera un DIB, sinon il utilisera un DDB. P>
HBITMAP code> est un
ddb code> < / Strong>, vous ne pouvez pas lire / écrire les données de pixels directement (même s'il est techniquement possible, Windows n'expose aucun moyen de le faire). Vous devez utiliser
getdibits code> pour les copier sur un tampon indépendant de périphérique, à l'aide d'un format particulier, puis
setdibits code> pour les copier. P>
HBITMAP code> est un
dib code> strud>, vous pouvez obtenir les bits de pixels réels (comme un pointeur) et lisez / écrivez-les directement en mémoire en utilisant < a href = "https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-getobjecte" rel = "nofollow noreferrer">
getObject code> a > (Ne pas être confondu avec
getcurrentObject code>): p>
bitmap.bmbits code> sera
null Code> S'il s'agissait d'un DDB, et ce sera une adresse mémoire valide si elle est une DIB. Si vous souhaitez simplement copier ces données, vous pouvez utiliser directement
bmbits code>; La longueur totale est
bmheight * bmwidthbyltes code>. p>
HBITMAP code>, le
, le
GetObject code> la fonction acceptera un
bitmap code> struct (comme indiqué dans l'exemple de code ci-dessus) ou un
DIBSECTION CODE>
STRIT. Notez que dibsection code> commence par un
bitmap code>, cela rend les deux structures compatibles. Iff le
HBITMAP code> est un dib, puis
getObject code> remplira un indice valide (non null)
BMBits code> Pointeur, et il remplira également la
dibsection code> 's
bitmapinfoheader code>
struct, que vous pouvez ensuite utiliser pour inspecter le format de pixel du DIB. examiner le bitmapinfoheader code> sera douloureux. em> p> p>
@Dialer a la meilleure réponse dans ce fil jusqu'à présent. À titre d'exemple supplémentaire, voici comment obtenir des bits de graphiques ou de tout HWND dans EMGU.CV MAT en C #.
struct BITMAP { public Int32 bmType; public Int32 bmWidth; public Int32 bmHeight; public Int32 bmWidthBytes; public Int16 bmPlanes; public Int16 bmBitsPixel; public IntPtr bmBits; } [StructLayout(LayoutKind.Sequential, Pack = 4)] struct BITMAPINFOHEADER { public int biSize; public int biWidth; public int biHeight; public Int16 biPlanes; public Int16 biBitCount; public int biCompression; public int biSizeImage; public int biXPelsPerMeter; public int biYPelsPerMeter; public int biClrUsed; public int bitClrImportant; } [DllImport("user32.dll", SetLastError=true)] static extern IntPtr GetDC(IntPtr hWnd); // System.Windows.Forms.Internal.IntUnsafeNativeMethods [DllImport("gdi32.dll", CharSet = CharSet.Auto, EntryPoint = "GetCurrentObject", ExactSpelling = true, SetLastError = true)] static extern IntPtr IntGetCurrentObject(HandleRef hDC, int uObjectType); [DllImport("gdi32.dll", CharSet = CharSet.Auto, EntryPoint = "GetObject")] static extern int GetObjectBitmap(IntPtr hObject, int nCount, ref BITMAP lpObject); [DllImport("gdi32.dll", EntryPoint = "GetDIBits")] static extern int GetDIBits(IntPtr hdc, IntPtr hbmp, int uStartScan, int cScanLines, IntPtr lpvBits, ref BITMAPINFOHEADER lpbi, int uUsage); /// <summary>Gets GDI HDC as an Emgu.CV.Mat image as BGRA</summary> /// <param name="hdc">GDI HDC</param> /// <param name="destination">Destination Mat which will receive the window contents image</param> /// <param name="verticalFlip">If TRUE, pixel will be flipped vertically</param> /// <returns>TRUE if image was copied successfully</returns> public static bool GetHdcAsMat(IntPtr hdc, ref Mat destination, bool verticalFlip) { try { // This is a HBITMAP, which is the actual buffer that is being drawn to by hdc. IntPtr hbitmap = IntGetCurrentObject(new HandleRef(null, hdc), 7 /*OBJ_BITMAP*/); // Get width, height and the address of the pixel data for the native HBitmap BITMAP info = new BITMAP(); if (0 == GetObjectBitmap(hbitmap, Marshal.SizeOf(info), ref info)) return false; // if the image is a DIB, we can copy the bits directly from bmBits if (info.bmBits != IntPtr.Zero) { // data view of the DIB bits, no allocations Mat view = new Mat(info.bmHeight, info.bmWidth, DepthType.Cv8U, 4, info.bmBits, info.bmWidth * 4); if (verticalFlip) // copy flipped: CvInvoke.Flip(view, destination, FlipType.Vertical); else // copy directly: view.CopyTo(destination); // automatically resize destination return true; } // otherwise, use GetDIBits to get the bitmap from the GPU // a copy is always needed to get the data from GPU to system memory if (destination.Width != info.bmWidth || destination.Height != info.bmHeight) { destination.Dispose(); destination = new Mat(info.bmHeight, info.bmWidth, DepthType.Cv8U, 4); } var desired = new BITMAPINFOHEADER(); desired.biSize = Marshal.SizeOf(desired); desired.biWidth = info.bmWidth; desired.biHeight = verticalFlip ? -info.bmHeight : info.bmHeight; desired.biPlanes = 1; desired.biBitCount = info.bmBitsPixel; // Copy bits into destination IntPtr dest = destination.DataPointer; return 0 != GetDIBits(hdc, hbitmap, 0, destination.Height, dest, ref desired, 0); } catch { return false; } } /// <summary>Gets window contents as an Emgu.CV.Mat image as BGRA</summary> /// <param name="hwnd">Handle to desired window</param> /// <param name="destination">Destination Mat which will receive the window contents image</param> /// <param name="verticalFlip">If TRUE, pixel will be flipped vertically</param> /// <returns>TRUE if image was copied successfully</returns> public static bool GetWindowAsMat(IntPtr hwnd, ref Mat destination, bool verticalFlip) { IntPtr hdc = GetDC(hwnd); // private DC does not need to be released return GetHdcAsMat(hdc, ref destination, verticalFlip); } /// <summary>Gets GDI Graphics contents as an Emgu.CV.Mat image as BGRA</summary> /// <param name="graphics">.NET GDI Graphics instance</param> /// <param name="destination">Destination Mat which will receive the window contents image</param> /// <param name="verticalFlip">If TRUE, pixel will be flipped vertically</param> /// <returns>TRUE if image was copied successfully</returns> public static bool GetGraphicsAsMat(Graphics graphics, ref Mat destination, bool verticalFlip) { IntPtr hdc = graphics.GetHdc(); try { return GetHdcAsMat(hdc, ref destination, verticalFlip); } finally { // NOTE: You cannot use the graphics object before ReleaseHdc is called. graphics.ReleaseHdc(hdc); } }
n'oubliez pas de le marquer comme accepté si cela fonctionne pour vous ..........
@Pranayrana: Aucune des réponses ne donne à l'astucher ce qu'ils veulent; Plutôt, tout le contraire.