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

VB.NET Discussion :

Import d'une image PNG par pixel


Sujet :

VB.NET

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2011
    Messages : 5
    Points : 5
    Points
    5
    Par défaut Import d'une image PNG par pixel
    Bonjour à tous !

    J'ai besoin de vos lumières pour réaliser une fonction qui importe le contenu d'un fichier image 1024*1024 format .PNG (16 bits, 1 seul channel grayscale) dans une matrice 1024*1024. La valeur de chaque pixel de l'image se mettant dans la cellule correspondante de la matrice.
    exemple: MatriceFinale(x,y) = ValeureImagePixelPosition(x,y)

    Je vois comment extraire une couleur avec GetPixel d'un fichier RGB 8 bits par channel avec le code suivant:

    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
    Public Function ExtractR(ByVal CurrentColor As Long) As Byte
       ExtractR = CurrentColor And 255
    End Function
     
    Public Function ExtractG(ByVal CurrentColor As Long) As Byte
       ExtractG = (CurrentColor \ 256) And 255
    End Function
     
    Public Function ExtractB(ByVal CurrentColor As Long) As Byte
       ExtractB = (CurrentColor \ 65536) And 255
    End Function
     
     
    Private Declare Function GetPixel Lib "GDI32" (ByVal hDC As Long, ByVal x As Long, ByVal y As Long) As Long
     
    Dim R as Byte, G as Byte, B as Byte
    Dim Color as Long
     
    Color = GetPixel(Picture1.hDC, 35, 42)
     
    R = ExtractR(Color)
    G = ExtractG(Color)
    B = ExtractB(Color)
    J'ai aussi recupéré le debut de la declaration pour stocker un png 16 bits grayscale:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Dim MyBitmap as Bitmap = New Bitmap (1024, 1024, Imaging.PixelFormat.Format16bppGrayScale)
    Comment realiser ma fonction ?
    Merci beaucoup pour vos conseils je ne parviens pas à mettre la main sur un tutorial ou un post de forum qui m'eclaire !

  2. #2
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 493
    Points
    5 493
    Par défaut
    Bonsoir.

    Le plus simple ici n'est pas de passer par GetPixel (ce qui serait d'ailleurs assez lent) mais de récupérer directement un IntPtr vers le tableau des pixels (via Bitmap.LockBits). A partir de là on peut soit le caster en ushort* si on veut travailler en unsafe ou le copier vers un tableau de ushort[] représentant les pixels (via Marshal.Copy).

    PS : GetPixel est déjà exposé par System.Drawing.Bitmap, pas besoin de l'importer soi-même.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2011
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    Merci DonQuiche pour ta réponse.
    Je t'avouerai que je ne connais aucune des methodes dont tu parles. Tu aurais un lien vers un tuto ou un depart de code ? Je suis sur que c'est une fonction qui prend moins de 10 lignes mais je ne voit pas comment faire
    Merci !

  4. #4
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 493
    Points
    5 493
    Par défaut
    Il suffit d'aller voir la référence de LockBits.

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2011
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    J'ai trouvé cette source en C#, penses tu que l'on puisse partir de la ?

    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
    public static void getRGB(this Bitmap image, int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)
        {
            const int PixelWidth = 3;
            const PixelFormat PixelFormat = PixelFormat.Format24bppRgb;
     
            // En garde!
            if (image == null) throw new ArgumentNullException("image");
            if (rgbArray == null) throw new ArgumentNullException("rgbArray");
            if (startX < 0 || startX + w > image.Width) throw new ArgumentOutOfRangeException("startX");
            if (startY < 0 || startY + h > image.Height) throw new ArgumentOutOfRangeException("startY");
            if (w < 0 || w > scansize || w > image.Width) throw new ArgumentOutOfRangeException("w");
            if (h < 0 || (rgbArray.Length < offset + h * scansize) || h > image.Height) throw new ArgumentOutOfRangeException("h");
     
            BitmapData data = image.LockBits(new Rectangle(startX, startY, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat);
            try
            {
                byte[] pixelData = new Byte[data.Stride];
                for (int scanline = 0; scanline < data.Height; scanline++)
                {
                    Marshal.Copy(data.Scan0 + (scanline * data.Stride), pixelData, 0, data.Stride);
                    for (int pixeloffset = 0; pixeloffset < data.Width; pixeloffset++)
                    {
                        // PixelFormat.Format32bppRgb means the data is stored
                        // in memory as BGR. We want RGB, so we must do some 
                        // bit-shuffling.
                        rgbArray[offset + (scanline * scansize) + pixeloffset] = 
                            (pixelData[pixeloffset * PixelWidth + 2] << 16) +   // R 
                            (pixelData[pixeloffset * PixelWidth + 1] << 8) +    // G
                            pixelData[pixeloffset * PixelWidth];                // B
                    }
                }
            }
            finally
            {
                image.UnlockBits(data);
            }
        }

  6. #6
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 493
    Points
    5 493
    Par défaut
    Certainement, oui. Il suffit de remplacer le tableau de byte par un tableau de ushort et de changer la ligne au coeur de la boucle.

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2011
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    Hello !

    J'ai reussi a importer le contenu d'un PNG 16 bits grayscale dans des variables à l'aide de la fonction FileOpen(iFileNum, path, OpenMode.Binary) et en decomposant le fichier grace a la structure du PNG trouvé sur google (standard PNG).

    Voici le code en question adapté en VBA (Excel) car je ne suis pas chez moi donc je test sur Excel (voir ci-dessous).

    J'importe bien ma signature mes differents chunks ainsi que le IHDR avec longeur, largeur, bitdepth, compression etc.

    Par contre je rencontre un probleme lors de l'import du chunk IDAT qui comporte les données. Mon image PNG fait 5 pixel / 5 pixel et est en 16bits (donc 2 bytes / pixel) grayscale, non compressé, sans filtre.

    Si je compare les valeurs en hexadecimal que je recupere du fichier (qui sont coherentes avec les valeurs que je peut voir si j'ouvre le PNG de test avec un editeur hexadecimal), je ne parviens pas a reconstituer les couleurs que je peut voir dans photoshop par exemple.

    Bien sur je test en faisant [valeur Hexa du fichier sur 2 bytes converti en decimal] * 255 / 65536

    Y a t-il des bytes de fin de ligne ? les données sont elles "eclatées" dans le fichiers, du genre dans le cas de mon image:
    25 pixels (5x5) d'affilé des bytes les plus lourdes + 25 pixels (5x5) d'affilé des bytes les plus legers ?

    Ou y a t-il une autre astuce?
    Merci beaucoup !! Je suis a 2 doigts d'atteindre mon but !!



    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    Option Explicit
     
    Private Type PNGHeader
        pngType(7) As Byte
    End Type
     
    Private Type PNGChunkHeader
        Length(3) As Byte
        CType(3) As Byte
    End Type
     
    Private Type PNGChunkData
        value As Byte
    End Type
     
    Private Type PNGImageData
        PixelData As Byte
    End Type
     
    Private Type PNGImageHDData
        WidthP(3) As Byte
        HeightP(3) As Byte
        BitDepthP As Byte
        ColorP As Byte
        CompressionP As Byte
        FilterP As Byte
        InterlaceP As Byte
    End Type
     
    Private Type PNGChunkCRC
        value(3) As Byte
    End Type
     
     
        Private Sub Form_Load()
     
            Dim x As Long, y As Long, index As Long
            Dim iFileNum As Integer
     
            Dim path As String
            Dim n As Integer
     
            iFileNum = FreeFile()
            path = "C:\Users\bla.png"
     
            Open path For Binary As iFileNum
            'FileOpen(iFileNum, path, OpenMode.Binary) in VB.net
     
            Dim dataFlag As Boolean
            dataFlag = False
            Dim DataLength As Integer
     
            Dim PixelList() As Single
     
            Dim pngHd As PNGHeader
            Dim pngChHd As PNGChunkHeader
            Dim pngChData() As PNGChunkData
            Dim pngChCRC As PNGChunkCRC
            Dim pngIHDRData As PNGImageHDData
            Dim pngIDATData() As PNGImageData
            Dim ChunkSize As Integer
            Dim ChunkType As String
            Dim ImageWidth As Integer
            Dim ImageHeight As Integer
     
            Get #iFileNum, , pngHd
     
            While dataFlag = False
     
                Get #iFileNum, , pngChHd
                ChunkSize = Val(Hex(pngChHd.Length(0)) * 2 ^ (8 * 3)) + Val(Hex(pngChHd.Length(1)) * 2 ^ (8 * 2)) + Val(Hex(pngChHd.Length(2)) * 2 ^ (8 * 1)) + pngChHd.Length(3)
                ChunkType = hex2ascii(Hex(pngChHd.CType(0))) & hex2ascii(Hex(pngChHd.CType(1))) & hex2ascii(Hex(pngChHd.CType(2))) & hex2ascii(Hex(pngChHd.CType(3)))
     
     
                Select Case ChunkType
                    Case "IHDR"
                        ReDim pngChData(ChunkSize - 1)
                        Get #iFileNum, , pngIHDRData
                        Get #iFileNum, , pngChCRC
                        ImageWidth = Val(Hex(pngIHDRData.WidthP(0)) * 2 ^ (8 * 3)) + Val(Hex(pngIHDRData.WidthP(1)) * 2 ^ (8 * 2)) + Val(Hex(pngIHDRData.WidthP(2)) * 2 ^ (8 * 1)) + pngIHDRData.WidthP(3)
                        ImageHeight = Val(Hex(pngIHDRData.HeightP(0)) * 2 ^ (8 * 3)) + Val(Hex(pngIHDRData.HeightP(1)) * 2 ^ (8 * 2)) + Val(Hex(pngIHDRData.HeightP(2)) * 2 ^ (8 * 1)) + pngIHDRData.HeightP(3)
     
                    Case "IDAT"
                        ReDim pngIDATData(ChunkSize - 1)
                        Get #iFileNum, , pngIDATData
                        Get #iFileNum, , pngChCRC
                        DataLength = ChunkSize
                        dataFlag = True
     
                    Case Else
                        ReDim pngChData(ChunkSize - 1)
                        Get #iFileNum, , pngChData
                        Get #iFileNum, , pngChCRC
     
                End Select
     
            Wend
     
            ReDim PixelList(ImageWidth * ImageHeight - 1)
            index = 0
     
            For n = 0 To ImageWidth * ImageHeight - 1
                PixelList(n) = pngIDATData(index).PixelData * 2 ^ 8 + pngIDATData(index + 1).PixelData
                index = index + 2
            Next n
     
            index = 0
            For x = 1 To 5
                For y = 1 To 5
                Sheets("Sheet1").Cells(x, y) = PixelList(index)
                index = index + 1
                Next y
            Next x
     
            Close iFileNum
     
     
        End Sub
     
    Public Function hex2ascii(ByVal hextext As String) As String
     
        Dim y As Integer
        Dim value As String
     
    For y = 1 To Len(hextext)
        value = value & Chr(Val("&h" & Mid(hextext, y, 2)))
        y = y + 1
    Next y
     
    hex2ascii = value
    End Function

  8. #8
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 493
    Points
    5 493
    Par défaut
    Malheureusement, en ce qui me concerne j'ignore tout des détails du format png.
    Cela dit, les données IDAT ne sont pas supposées être compressées ? Je ne vois aucun code de décompression.

Discussions similaires

  1. Réponses: 4
    Dernier message: 09/02/2006, 18h44
  2. [ImageMagick] Affichage d'une image png
    Par JavaAcro dans le forum Bibliothèques et frameworks
    Réponses: 15
    Dernier message: 06/02/2006, 10h13
  3. [Image] Décomposer une image png.
    Par Quintoff dans le forum 2D
    Réponses: 3
    Dernier message: 06/01/2006, 21h22
  4. [GD] pb affichage d'une image créée par GD depuis ma base MySQL
    Par freddy92110 dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 30/12/2005, 16h50
  5. [Cross-Browser] Couleur d'une image PNG
    Par [BkM-) dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 17/11/2005, 22h00

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