Shurikn Posted June 9, 2005 Posted June 9, 2005 i got 2 diferent problems, depending on what date im reading, when im reading a short my problem is that the bytes are inversed, the first 2 bytes in the file are FFD8 and when read the give me D8FF, since i read it in a short it gives me 55551 when it should give me 65496... i know this is probably stupid and everyone knew that byte were inversed or something... but how can I compare shorts if there dont have the value they are suposed to.... my second problem is when i read a string... all my strings i read from the file are missing le last char my string is suposed to give me "JFIF\0" and instead i get "JFIF", then I tough it was maybe just because of the null char so I checked elsewere in my code where Im suposed to get the value "RIFF" and get "RIF" instead... anyone can help? Quote
IngisKahn Posted June 9, 2005 Posted June 9, 2005 First off the bytes FF D8 equal the number 0xD8FF so I'm not shore what your problem there is. How are you reading the four CC in? Remeber that in .NET, Strings are unicode strings not a null terminated array of bytes like in C. Quote "Who is John Galt?"
Shurikn Posted June 9, 2005 Author Posted June 9, 2005 I read the header that way: [structLayout(LayoutKind.Sequential)] public struct EnTeteJPG { public ushort SOI; public ushort JFIFMarker; public ushort length; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=5)] public string identifier; [MarshalAs(UnmanagedType.ByValArray, SizeConst=2)] public byte[] version; public byte units; public short Xdensity; public short Ydensity; public byte Xthumbnail;// 0 = no thumbnail public byte Ythumbnail;// 0 = no thumbnail } public bool LireFichier(string nomFichier) { byte[] data=new byte[Marshal.SizeOf(entete)]; GCHandle handle; IntPtr ptr; System.IO.FileStream stream= new System.IO.FileStream(nomFichier,FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.None); stream.Read(data,0,data.Length); stream.Close(); handle=GCHandle.Alloc(data,GCHandleType.Pinned); ptr=handle.AddrOfPinnedObject(); entete=(EnTeteJPG)Marshal.PtrToStructure(ptr,typeof(EnTeteJPG)); handle.Free(); this.nomFichier=nomFichier; if(entete.SOI!=0xD8FF) { return false; } if(entete.JFIFMarker!=0xE0FF) { return false; } if(entete.identifier!="JFIF\0") { return false; } return true; } Quote
IngisKahn Posted June 9, 2005 Posted June 9, 2005 (edited) Try using LPStr instead of ByValTStr or you can set the CharSet of the StuctLayoutAttribute to Ansi. Edited June 9, 2005 by IngisKahn Quote "Who is John Galt?"
Shurikn Posted June 9, 2005 Author Posted June 9, 2005 using LPStr instead of ByValTStr cause the program to an An unhandled exception of type 'System.NullReferenceException' occurred in mscorlib.dll Additional information: Object reference not set to an instance of an object. when the code reach entete=(EnteteAvi)Marshal.PtrToStructure(ptr,typeof(EnteteAvi)); and the StructLayoutAttribute CharSet=CharSet.Ansi didnt change anythig, I still get 4 chars array instead of 5... Now I could probably change the [MarshalAs(UnmanagedType.ByValTStr, SizeConst=5)] and put SizeConst=6 and i'd probably get my 5 chars, but then I would probably lose a byte, that is probably pretty usefull to the struct structure.... Quote
IngisKahn Posted June 9, 2005 Posted June 9, 2005 There are only 4 characters in the string, the null just marks the end. Quote "Who is John Galt?"
Shurikn Posted June 9, 2005 Author Posted June 9, 2005 i'll give you another code part to show you what i mean [structLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)] public struct EnteteAvi { [MarshalAs(UnmanagedType.LPStr, SizeConst=4)] public string chunkId; public Int32 fileSize; [MarshalAs(UnmanagedType.LPStr, SizeConst=4)] public string fileType; [MarshalAs(UnmanagedType.LPStr, SizeConst=4)] public string subChunk1ID; public Int32 subChunk1Size; [MarshalAs(UnmanagedType.LPStr, SizeConst=4)] public string subChunk1Type; public Int32 cb; public Int32 MicroSecPerFrame; public Int32 MaxBytePerSec; public Int32 PaddingGranularity; public Int32 Flags; public Int32 TotalFrames; public Int32 InitialFrames; public Int32 Streams; public Int32 SuggestedBufferSize; public Int32 Width; public Int32 Height; [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)] public Int32[] Reserved; } public bool LireFichier(string nomFichier) { byte[] data=new byte[Marshal.SizeOf(entete)]; GCHandle handle; IntPtr ptr; System.IO.FileStream stream= new System.IO.FileStream(nomFichier,FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.None); stream.Read(data,0,data.Length); stream.Close(); handle=GCHandle.Alloc(data,GCHandleType.Pinned); ptr=handle.AddrOfPinnedObject(); entete=(EnteteAvi)Marshal.PtrToStructure(ptr,typeof(EnteteAvi)); handle.Free(); this.nomFichier=nomFichier; if(entete.chunkId!="RIFF") { return false; } if(entete.fileType!="AVI ") { return false; } if(entete.subChunk1ID!="avih") { return false; } return true; } as you see in there, im asking for 4 char in my struct, and I compare with RIFF entete.chunkId is returning "RIF" wich is lacking 1 char! Quote
IngisKahn Posted June 9, 2005 Posted June 9, 2005 You have to use ByValTStr on fixed length strings that are not null terminated. Quote "Who is John Galt?"
Shurikn Posted June 10, 2005 Author Posted June 10, 2005 You have to use ByValTStr on fixed length strings that are not null terminated. sure but it was byvaltstr from the begining, i only tryed with that when you said that... but still I'm missing a char. Quote
Shurikn Posted June 10, 2005 Author Posted June 10, 2005 ok, after searching like crazy I fond a way to do it... even if it may not be the best way it's working! first i had to change back my struct to make it use only byte array: [structLayout(LayoutKind.Sequential,Pack=1,CharSet=CharSet.Ansi)] public struct EnteteAvi { [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)] public byte[] chunkId; public Int32 fileSize; [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)] public byte[] fileType; [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)] public byte[] subChunk1ID; public Int32 subChunk1Size; [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)] public byte[] subChunk1Type; public Int32 cb; public Int32 MicroSecPerFrame; public Int32 MaxBytePerSec; public Int32 PaddingGranularity; public Int32 Flags; public Int32 TotalFrames; public Int32 InitialFrames; public Int32 Streams; public Int32 SuggestedBufferSize; public Int32 Width; public Int32 Height; [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)] public Int32[] Reserved; } the writing in the strunct still goes well, the only other change is when I compare to what I need, I need to use: if(System.Text.Encoding.ASCII.GetString(entete.chunkId,0,4)!="RIFF") { return false; } and it'S now working, it see my 4 char instead of magically losing the last one Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.