DirectBitmap à partir d'un fichier image
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:
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:
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 :mouarf:
Il y a probablement une façon toute bête d'y parvenir mais je ne vois pas :mouarf:
Peut-être peut-on le faire via un objet "Graphics", en effet on peut faire ça avec cette classe DirectBitmap :
Code:
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