Bonjour à tous,

J'ai créé un programme qui traite des images

J'ai trouvé ce code qui permet de lire efficacement la couleur des pixels (fonction GetPixel rapide) sans recourir à du code unsafe:

https://stackoverflow.com/questions/...-for-windows-f

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class DirectBitmap : IDisposable
{
    public Bitmap Bitmap { get; private set; }
    public Int32[] Bits { get; private set; }
    public bool Disposed { get; private set; }
    public int Height { get; private set; }
    public int Width { get; private set; }
 
    protected GCHandle BitsHandle { get; private set; }
 
    public DirectBitmap(int width, int height)
    {
        Width = width;
        Height = height;
        Bits = new Int32[width * height];
        BitsHandle = GCHandle.Alloc(Bits, GCHandleType.Pinned);
        Bitmap = new Bitmap(width, height, width * 4, PixelFormat.Format32bppPArgb, BitsHandle.AddrOfPinnedObject());
    }
 
    public void SetPixel(int x, int y, Color colour)
    {
        int index = x + (y * Width);
        int col = colour.ToArgb();
 
        Bits[index] = col;
    }
 
    public Color GetPixel(int x, int y)
    {
        int index = x + (y * Width);
        int col = Bits[index];
        Color result = Color.FromArgb(col);
 
        return result;
    }
 
    public void Dispose()
    {
        if (Disposed) return;
        Disposed = true;
        Bitmap.Dispose();
        BitsHandle.Free();
    }
}
Ce code marche mais il créé un bitmap "vierge"

Je ne sais pas comment faire pour créer un nouveau bitmap à partir d'une image existante.

Je l'ai adapté en VB.NET (mon logiciel a son interface et le gros du code en VB.NET, avec quelques DLL écrites en C# que j'ai modifié)
J'ai ajouté un deuxième constructeur permettant de créer le DirectBitmap à partir d'un fichier et c'est là que je ne sais pas comment faire.

Code VBNET : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
 
Public Class DirectBitmap  'Inherits IDisposable
    Public Property Bitmap As Bitmap
    Public Property Bits As Int32()
    Public Property Disposed As Boolean
    Public Property Height As Integer
    Public Property Width As Integer
    Protected Property BitsHandle As GCHandle
 
    Public Sub New(File As String)
        'Lecture du fichier (qui peut être une image de n'importe quel type)
        Dim bm As Bitmap
        bm = CType(Image.FromFile(File), Bitmap)
        Width = bm.Width
        Height = bm.Height
        Bits = New Int32(Width * Height - 1) {}
        BitsHandle = GCHandle.Alloc(Bits, GCHandleType.Pinned)
        Bitmap = New Bitmap(Width, Height, Width * 4, PixelFormat.Format32bppPArgb, BitsHandle.AddrOfPinnedObject())
 
        'Comment faire pour "peindre" le contenu de 'bm' dans 'Bitmap' ???
 
        bm.Dispose()
    End Sub
 
    Public Sub New(ByVal width As Integer, ByVal height As Integer)
        width = width
        height = height
        Bits = New Int32(width * height - 1) {}
        BitsHandle = GCHandle.Alloc(Bits, GCHandleType.Pinned)
        Bitmap = New Bitmap(width, height, width * 4, PixelFormat.Format32bppPArgb, BitsHandle.AddrOfPinnedObject())
    End Sub
 
    Public Sub SetPixel(ByVal x As Integer, ByVal y As Integer, ByVal colour As Color)
        Dim index As Integer = x + (y * Width)
        Dim col As Integer = colour.ToArgb()
        Bits(index) = col
    End Sub
 
    Public Function GetPixel(ByVal x As Integer, ByVal y As Integer) As Color
        Dim index As Integer = x + (y * Width)
        Dim col As Integer = Bits(index)
        Dim result As Color = Color.FromArgb(col)
        Return result
    End Function
 
    Public Sub Dispose()
        If Disposed Then Return
        Disposed = True
        Bitmap.Dispose()
        BitsHandle.Free()
    End Sub
End Class

Le constructeur new Bitmap() permet de nombreuses possibilités avec différents paramètres, mais aucun ne permet d'avoir à la fois comme paramètres:
- PixelFormat.Format32bppPArgb et BitsHandle.AddrOfPinnedObject
- File

Je précise qu'il faut que ce soit rapide... car faire des bm.GetPixel() classiques (donc lents) pour remplir DirectBitmap.Bitmap n'a aucun intérêt

Il y a probablement une façon toute bête d'y parvenir mais je ne vois pas

Peut-être peut-on le faire via un objet "Graphics", en effet on peut faire ça avec cette classe DirectBitmap :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
var dbm = new DirectBitmap(200, 200);
using (var g = Graphics.FromImage(dbm.Bitmap))
{
    g.DrawRectangle(Pens.Black, new Rectangle(50, 50, 100, 100));
}
A bientôt