IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

DirectBitmap à partir d'un fichier image


Sujet :

C#

  1. #1
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut 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 : 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
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  2. #2
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Bonjour,

    j'ai trouvé :

    Code VBNET : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        Public Sub New(File As String)
            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())
            Graphics.FromImage(Bitmap).DrawImage(bm, 0, 0) 'peindre le contenu de 'bm' dans 'Bitmap'
            bm.Dispose()
        End Sub

    A bientôt
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  3. #3
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Si vous n'avez pas besoin d'un objet 'color', il est possible d'augmenter la vitesse en utilisant un tableau de Byte

    Dans mon programme j'ai seulement besoin d'une valeur de gris pour faire un heightmap :

    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
    Imports System.Drawing.Imaging
    Imports System.Runtime.InteropServices
     
    Public Class DirectBitmapByte 'Inherits IDisposable
        Public Property Bitmap As Bitmap
        Public Property Bits As Byte()
        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)
            Dim bm As Bitmap
            bm = CType(Image.FromFile(File), Bitmap)
            Width = bm.Width
            Height = bm.Height
            Bits = New Byte(Width * Height * 4 - 1) {}
            BitsHandle = GCHandle.Alloc(Bits, GCHandleType.Pinned)
            Bitmap = New Bitmap(Width, Height, Width * 4, PixelFormat.Format32bppPArgb, BitsHandle.AddrOfPinnedObject())
            Graphics.FromImage(Bitmap).DrawImage(bm, 0, 0) '"peindre" le contenu de 'bm' dans 'Bitmap'
            bm.Dispose()
        End Sub
     
        Public Sub New(ByVal w As Integer, ByVal h As Integer)
            Width = w
            Height = h
            Bits = New Byte(Width * Height * 4 - 1) {}
            BitsHandle = GCHandle.Alloc(Bits, GCHandleType.Pinned)
            Bitmap = New Bitmap(Width, Height, Width * 4, PixelFormat.Format32bppPArgb, BitsHandle.AddrOfPinnedObject())
        End Sub
     
        Public Function GetGrayLevel(ByVal x As Integer, ByVal y As Integer) As Integer
            Dim index As Integer = 4 * (x + (y * Width))
            If STL_LithophanieInverserZ Then
                Return 255000 - 299 * Bits(index + 1) - 587 * Bits(index + 2) - 114 * Bits(index + 3)
                'Return 255000 - 333 * c.R - 334 * c.G - 333 * c.B
            Else
                Return 299 * Bits(index + 1) + 587 * Bits(index + 2) + 114 * Bits(index + 3)
                'Return 333 * c.R + 334 * c.G + 333 * c.B
            End If
        End Function
     
        Public Sub Dispose()
            If Disposed Then Return
            Disposed = True
            Bitmap.Dispose()
            BitsHandle.Free()
        End Sub
    End Class
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [VB.Net] Image à partir d'un fichier
    Par Fullmetal82 dans le forum Windows Forms
    Réponses: 6
    Dernier message: 18/02/2007, 00h52
  2. Récupération automatique d'images à partir d'un fichier vidéo
    Par osscour dans le forum Bibliothèques et frameworks
    Réponses: 8
    Dernier message: 15/05/2006, 09h11
  3. [Image] Comment créer une image à partir d'un fichier
    Par mereyj dans le forum Entrée/Sortie
    Réponses: 1
    Dernier message: 01/07/2005, 21h48
  4. [CR] Inserer une image à partir d'un fichier
    Par Gandalf24 dans le forum SAP Crystal Reports
    Réponses: 7
    Dernier message: 23/07/2003, 10h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo