cs_Orohena
Messages postés577Date d'inscriptionvendredi 26 septembre 2008StatutMembreDernière intervention20 novembre 2010
-
8 janv. 2009 à 22:06
cs_Orohena
Messages postés577Date d'inscriptionvendredi 26 septembre 2008StatutMembreDernière intervention20 novembre 2010
-
14 janv. 2009 à 22:15
bonjour
Voila, je suis newbie en vb.NET 2008, et j'ai un souci pour écrire des fichiers structurés en binaire. D'après ce que j'ai vu sur le forum, le moins compliqué est d'utiliser les méthodes Marshal. J'ai donc voulu créer un fichier bitmap windows, mais ça ne donne pas les résultats espérés.
Voici le code ; pour l'alléger, j'ai tronqué le fichier à la structure bitmapFileHeader :
Option Strict On
Option Explicit
Imports System.Runtime.InteropServices
Public Class Form1
Public Structure bitmapFileHeader
<MarshalAs(UnmanagedType.ByValTstr, sizeconst:=2)> _
Dim bftype As String ' 2 bytes
Dim bfsize As Integer ' 4 bytes
Dim bfReserved1 As Short ' 2 bytes
Dim bfReserved2 As Short ' 2 bytes
Dim bfOffBits As Integer ' 4 bytes
End Structure
Private Sub Essai()
Dim entete As New bitmapFileHeader
Dim rep As String = My.Computer.FileSystem.CurrentDirectory & "\test.bmp"
Dim f As New IO.FileStream(rep, IO.FileMode.Create)
With entete
.bftype = "BM"
.bfsize = 10000
.bfReserved1 = 0
.bfReserved2 = 0
.bfOffBits = 1078
End With
Try
Dim Data(Marshal.SizeOf(entete)) As Byte
Dim Handle As GCHandle = GCHandle.Alloc(Data, GCHandleType.Pinned)
Dim Pointer As IntPtr = Handle.AddrOfPinnedObject()
Marshal.StructureToPtr(entete, Pointer, False)
Handle.Free()
f.Write(Data, 0, Data.Length)
Finally
f.Close()
End Try
End Sub
End Class
Après exécution, je m'attendais à trouver ça dans mon fichier :
Est-ce que quelqu'un peut m'éclairer, car pour le moment, je marche à l'ombre (Marshal.ombre )
Au passage, mes remerciements à picpic10, ebartsoft et us_30 sans lesquels je me serais déjà suicidé au gaz ou par tout autre moyen propice à abréger mes souffrances.
cs_Orohena
Messages postés577Date d'inscriptionvendredi 26 septembre 2008StatutMembreDernière intervention20 novembre 20104 9 janv. 2009 à 19:58
Bonjour NHenry et merci pour ta réponse
La donnée à structurer est entete, du type bmpFileHeader.
Je souhaite l'écrire dans un fichier, comme je l'aurais fait en VBA avec PUT numeroFichier, 0, entete.
NHenry
Messages postés15113Date d'inscriptionvendredi 14 mars 2003StatutModérateurDernière intervention22 avril 2024159 9 janv. 2009 à 20:41
Bonjour,
Question idiote (sans doute), si j'ai bien compris, tu veux enregistrer un fichier Bitmap avec ton application ? Dans ce cas, il existe une méthode intégrée au framwork .NET TonImage.SaveToFile (ou un truc du genre).
Sinon, tu peux aussi forcer la taille des données dans ta structure (jamais testé pour écrire un fichier). Ou alors tu enregistre tous tes champs "à la main".
cs_Orohena
Messages postés577Date d'inscriptionvendredi 26 septembre 2008StatutMembreDernière intervention20 novembre 20104 9 janv. 2009 à 21:26
Non, ta question est pertinente. En fait je souhaite pouvoir maîtriser l'écriture et la lecture d'un fichier binaire à la main, rien qu'à partir des spécifications de l'éditeur.
Je voudrais par exemple être en mesure de faire en .net ce que j'ai fait sous Excel (voir mon 2e source), c'est à dire visualiser les structures d'un fichier GIF en partant de rien (si ce n'est des spécifications de Compuserve).
Apparemment, en .net c'est un peu plus compliqué qu'un PUT ou qu'un GET, mais si c'est possible, c'est le principal.
Bien entendu, j'utiliserai les méthodes intégrées au framework .NET chaque fois qu'elles répondront à mes besoins ; je n'ai quand même pas envie de réinventer ce qui existe déjà .
cs_Orohena
Messages postés577Date d'inscriptionvendredi 26 septembre 2008StatutMembreDernière intervention20 novembre 20104 10 janv. 2009 à 01:43
Bonjour Nicolas
J'ai fait pas mal de tests, et je te donnes le résultat :
<hr />
Tests "2 bytes et Short"
J'ai fait les tests que tu m'as suggérés :1) en remplaçant le string par deux bytes, c'est nickel.
2) en remplaçant le string par un entier, c'est ok également (tout au moins en début de structure : voir ci-dessous)
Je suppose qu'il y a un souci dans le code au niveau du MarshalAs, mais comme je suis béotien en la matière, je n'ai pas encore pu déterminer lequel.
<hr />
Alignement des variables
Il semble que Marshal.StructureToPtr récupère les variables de la structure et les aligne selon leur longueur (en octets) avant de les charger dans la table : les variables Short sont en effet "alignées Short" (traduction plus ou moins heureuse de Short-boundary alignment) et les variables Integer sont "alignées Integer". Je suppose que c'est le cas de toutes les autres types de données, mais je ne l'ai pas vérifié.
En effet, j'ai constaté que quelque soit la combinaison de variables de la structure, le flux de caractères du fichier de sortie était arrangé de façon que les variables Short du fichier soient toujours à l'offset 1, 3, ou 5... du fichier, et les variables Long à offset 1, 5, 9..., par l'insertion de caractères nuls de "padding" ou remplissage.Par exemple, si la structure testée commençait par une variable Byte et une Short, le fichier généré commençait par le Byte, suivi d'un zero-byte, suivi du Short.
De même, si la structure commençait par une variable Byte suivi d'une Long, le fichier commençait par le Byte, suivi de trois zero-bytes, suivis du Long.
Ca explique en partie la tête bizarre des 4 premiers caractères de mon fichier bmp.
Je vais donc chercher le paramétrage de Marshal qui supprime l'alignement des variables.
<hr />Null-byte en fin de fichier
Dans tous mes tests, j'ai constaté la présence inexplicable d'un zero-byte en fin de fichier. Cela pourrait être dû à l'instruction Dim Data(Marshal.SizeOf(entete)) As Byte du code ; en effet, si la limite inférieure des indices de tableaux en .net est 0, cette instruction crée, à mon avis, un tableau trop grand d'un octet.
<hr />Bien entendu, je vais tâcher de régler ces différents problèmes, mais toute aide sera la bienvenue. Je suppose que des membres du forum ont déjà écrit un fichier formaté bmp, mdi, wav ou autre en .net à la main.
NHenry
Messages postés15113Date d'inscriptionvendredi 14 mars 2003StatutModérateurDernière intervention22 avril 2024159 10 janv. 2009 à 10:30
Bonjour,
En effet, concernant le tableau, l'erreur est facile à faire, quand tu le dimensionnes, tu donne la borne supérieure, donc, la ligne devrait être :
Dim Data(Marshal.SizeOf(entete)-1) As Byte
Concernant l'alignement, je n'ai pas d'idées, autre que de ne mettre que des Short et de séparer les données à la main, mais cela enlèverait tout intérêt à cette technique :/ .
cs_Orohena
Messages postés577Date d'inscriptionvendredi 26 septembre 2008StatutMembreDernière intervention20 novembre 20104 10 janv. 2009 à 14:46
Bonjour Nicolas
Entièrement d'accord avec toi, soit la structure permet de conserver le format d'origine, soit on passe à une autre technique. Mais je suis sûr que ça doit le faire en vb.net ; suffit de trouver la bonne technique.
cs_Orohena
Messages postés577Date d'inscriptionvendredi 26 septembre 2008StatutMembreDernière intervention20 novembre 20104 12 janv. 2009 à 20:21
Bonjour Nicolas et le forum
Les instructions FilePut / FileGet semblent donner les résultats recherchés et leur utilisation est assez semblable aux instructions Put / Get de vb, facilitant la migration d'applications écrites en vba.
Comme j'avais pris pour exemple la structure bitmapFileHeader, je vous soumets le programme de test d'écriture de fichier bitmap Windows afin que vous puissiez le critiquer, car je suis débutant en vb.net 2008 et je souhaite évidemment démarrer sur de bonnes bases.
Amicalement
<hr />
Public Class form1
' Ecriture d'une image noire 1024x100 pixels dans un fichier bitmap 256 couleurs
' dans le répertoire de l'application
Shared Sub Main()
Dim bfFileHeader As New bitmapFileHeader
Dim bfInfoHeader As New bitmapInfoHeader
Dim bfPalette As String
Dim numFic As Integer = FreeFile()
Dim hauteur As Integer = 100
Dim largeur As Integer = 1024
Dim trailer As Byte = CByte(IIf(largeur Mod 4 <> 0, 4 - largeur Mod 4, 0))
Dim lgBmpData As Integer = hauteur * (largeur + trailer)
Dim fichier As String = My.Computer.FileSystem.CurrentDirectory & "\test.bmp"
Dim bfData As String
Dim lgFic As Integer = 1078 + lgBmpData
Try
My.Computer.FileSystem.DeleteFile(fichier)
Catch filenotfound As System.IO.FileNotFoundException
End Try
FileOpen(numFic, fichier, OpenMode.Binary, _
OpenAccess.ReadWrite, OpenShare.Shared)
With bfFileHeader
.bftype = "BM"
.bfsize = lgFic
.bfReserved1 = 0
.bfReserved2 = 0
.bfOffBits = 1078
End With
' creation d'une palette 256 couleurs (monochrome N & B)
bfPalette = StrDup(1020, Chr(0)) & StrDup(3, Chr(255)) & Chr(0)
' creation d'un raster data (fond noir)
bfData = StrDup(lgBmpData, Chr(0))
' ecriture de la structure bitmapFileHeader (14 bytes)
FilePut(numFic, bfFileHeader)
' méthode alternative d'ecriture de la structure bitmapFileHeader
' FilePut(numFic, New bitmapFileHeader("BM", lgFic, 0, 0, 1078))
' ecriture de la structure bitmapInfoHeader (40 bytes)
FilePut(numFic, bfInfoHeader)
' ecriture de la palette et du bitmap data (Strings de longeurs variables)
FilePut(numFic, bfPalette & bfData)
FileClose(numFic)
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Main()
End Sub
Public Structure bitmapFileHeader
<VBFixedString(2)> Public bftype As String ' Type de fichier
Public bfsize As Integer ' Longueur du fichier
Public bfReserved1 As Short ' Reserve
Public bfReserved2 As Short ' Reserve
Public bfOffBits As Integer ' Offset du bitmap data depuis le debut du fichier
Public Sub New(ByVal new_bftype As String, ByVal new_bfsize As Integer, _
ByVal new_bfReserved1 As Short, ByVal new_bfReserved2 As Short, ByVal new_bfOffbits As Integer)
bftype = new_bftype
bfsize = new_bfsize
bfReserved1 = new_bfReserved1
bfReserved2 = new_bfReserved2
bfOffBits = new_bfOffbits
End Sub
End Structure
Public Structure bitmapInfoHeader
Public biSize As Integer ' Longueur de la structure de données bitmapInfoHeader
Public biWidth As Integer ' Largeur de l'image en pixels
Public biHeight As Integer ' Hauteur de l'image en pixels
Public biPlanes As Short ' Nombre de plans du target device
Public biBitCount As Short ' Nombre de bits par pixels = controle 'couleurs
Public biCompression As Integer ' Type de compression
Public bisizeimage As Integer ' Taille de l'image data
Public biXPelsPerMeter As Integer ' Pixels par metres du target device (horizontal)
Public biYPelsPerMeter As Integer ' Pixels par metres du target device (vertical)
Public biClrUsed As Integer ' Nombre de couleurs utilise dans le bitmap
Public biClrImportant As Integer ' Nombre de couleurs importantes
cs_Orohena
Messages postés577Date d'inscriptionvendredi 26 septembre 2008StatutMembreDernière intervention20 novembre 20104 14 janv. 2009 à 22:15
Bonjour Nicolas
Merci pour ton message !
En marge de cette discussion, si tu as des réserves ou suggestions sur mon choix de vb.net 2008, n'hésite pas à m'en faire part. Ca m'a paru assez logique comme choix puisque je codais principalement en vba. Mais comme ta fiche indique que tu maîtrises tous les langages de Visual Studio je suis preneur de tous tes conseils. Je maîtrise bien php et perl, assez proche du c.