[.Net] Récupérer, Modifier et Travailler avec les pixels et les bitmap

dotnet microsoft

Pour un de mes projets (dont je parlerai plus longuement dans quelques mois), j’ai eu besoin de faire des captures d’écran via une application Dotnet.

Une fois la capture réalisée, j’ai voulu lire et modifier les valeurs RGB de certains pixels.

Certains traitements tels que la mise à jour de nombreux pixels sont coûteux en ressource, c’est pourquoi j’ai fait une petite classe nommée SpeedBitmap. Cette classe permet ainsi d’optimiser certains traitements.

Voici les fonctionnalités de ma classe SpeedBitmap:

  • réaliser une capture d’écran
  • lire le code RGB d’un pixel
  • modifier le code RGB d’un pixel
  • bloquer et débloquer un bitmap afin d’optimiser les temps de traitement

Les fonctions de bloquage et débloquage du bitmap sont relativement pratiques si vous avez à effectuer de nombreux traitements sur le bitmap.

Voici ma classe pratique pour travailler avec des screenshots:

Private Class SpeedBitmap
#Region "Properties"
        Private pixelBytes() As Byte
        Private bmpData As BitmapData
        Private Depth As PixelFormat = PixelFormat.Format24bppRgb
        Private Width As Integer
#End Region
 
#Region "Mappage des fonctions Win32"
        <DllImport("gdi32.dll", EntryPoint:="DeleteDC")>
        Public Shared Function DeleteDC(ByVal hdc As IntPtr) As IntPtr
        End Function
 
        <DllImport("gdi32.dll", EntryPoint:="DeleteObject")>
        Public Shared Function DeleteObject(ByVal hObject As IntPtr) As IntPtr
        End Function
 
        <DllImport("gdi32.dll", EntryPoint:="BitBlt")>
        Public Shared Function BitBlt(ByVal hdcDest As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, _
                                   ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As Integer) As Boolean
        End Function
 
        <DllImport("gdi32.dll", EntryPoint:="CreateCompatibleBitmap")>
        Public Shared Function CreateCompatibleBitmap(ByVal hdc As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer) As IntPtr
        End Function
 
        <DllImport("gdi32.dll", EntryPoint:="CreateCompatibleDC")>
        Public Shared Function CreateCompatibleDC(ByVal hdc As IntPtr) As IntPtr
        End Function
 
        <DllImport("gdi32.dll", EntryPoint:="SelectObject")>
        Public Shared Function SelectObject(ByVal hdc As IntPtr, ByVal hgdiobjBmp As IntPtr) As IntPtr
        End Function
 
        <DllImport("user32.dll", EntryPoint:="GetDesktopWindow")>
        Public Shared Function GetDesktopWindow() As IntPtr
        End Function
 
        <DllImport("user32.dll", EntryPoint:="GetDC")>
        Public Shared Function GetDC(ByVal hWnd As IntPtr) As IntPtr
        End Function
 
        <DllImport("user32.dll", EntryPoint:="GetSystemMetrics")>
        Public Shared Function GetSystemMetrics(ByVal nIndex As Integer) As Integer
        End Function
 
        <DllImport("user32.dll", EntryPoint:="ReleaseDC")>
        Public Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As IntPtr
        End Function
#End Region
 
        'Fonction qui lock le bitmap
        Public Sub LockBitmap(ByVal bm As Bitmap)
            ' Lock the bitmap data.
            Width = bm.Width
            Dim bounds As Rectangle = New Rectangle(0, 0, bm.Width, bm.Height)
            bmpData = bm.LockBits(bounds, ImageLockMode.ReadWrite, Depth)
 
            ' Allocate room for the data.
            Dim total_size As Integer = bmpData.Stride * bmpData.Height
            ReDim pixelBytes(total_size)
 
            ' Copy the data into the g_PixBytes array.
            Marshal.Copy(bmpData.Scan0, pixelBytes, 0, total_size)
        End Sub
 
        'Fonction qui unlock le bitmap
        Public Sub UnlockBitmap(ByVal bm As Bitmap)
            ' Copy the data back into the bitmap.
            Dim total_size As Integer = bmpData.Stride * bmpData.Height
            Marshal.Copy(pixelBytes, 0, bmpData.Scan0, total_size)
 
            ' Unlock the bitmap.
            bm.UnlockBits(bmpData)
 
            ' Release resources.
            pixelBytes = Nothing
            bmpData = Nothing
        End Sub
 
        'Fonction qui recupere la couleur d'un pixel
        Public Function GetPixel(ByVal x As Integer, ByVal y As Integer) As Color
            Dim clr As Color = Color.Empty
 
            'Get color components count
            Dim cCount As Integer = 24 \ 8
 
            'Get start index of the specified pixel
            Dim i As Integer = ((y * Width) + x) * cCount
 
            If (i > pixelBytes.Length - cCount) Then
                Throw New IndexOutOfRangeException()
            End If
 
            Dim b As Byte = pixelBytes(i)
            Dim g As Byte = pixelBytes(i + 1)
            Dim r As Byte = pixelBytes(i + 2)
            clr = Color.FromArgb(r, g, b)
 
            Return clr
        End Function
 
        'Fonction qui met à jour la couleur pour un pixel
        Public Sub SetPixel(ByVal x As Integer, ByVal y As Integer, ByVal clr As Color)
            'Get color components count
            Dim cCount As Integer = Depth \ 8
 
            'Get start index of the specified pixel
            Dim i As Integer = ((y * Width) + x) * cCount
            pixelBytes(i) = clr.B
            pixelBytes(i + 1) = clr.G
            pixelBytes(i + 2) = clr.R
        End Sub
 
        'Fonction qui prend un screenshot de votre écran
        Public Function Capture() As Bitmap
            Dim screenX, screenY As Integer
            Dim hBmp As IntPtr
            Dim hdcScreen As IntPtr = GetDC(GetDesktopWindow())
            Dim hdcCompatible As IntPtr = CreateCompatibleDC(hdcScreen)
            screenX = GetSystemMetrics(0)
            screenY = GetSystemMetrics(1)
            hBmp = CreateCompatibleBitmap(hdcScreen, screenX, screenY)
 
            If (hBmp <> IntPtr.Zero) Then
                Dim hOldBmp As IntPtr = SelectObject(hdcCompatible, hBmp)
                BitBlt(hdcCompatible, 0, 0, screenX, screenY, hdcScreen, 0, 0, 13369376)
                SelectObject(hdcCompatible, hOldBmp)
                DeleteDC(hdcCompatible)
                ReleaseDC(GetDesktopWindow(), hdcScreen)
                Dim bmp As Bitmap = System.Drawing.Image.FromHbitmap(hBmp)
                DeleteObject(hBmp)
                GC.Collect()
                Return bmp
            End If
            Return Nothing
        End Function
    End Class

Leave a Reply

Your email address will not be published. Required fields are marked *