rational64u

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von Bartosz.

    Hallo zusammen,

    laut dieser Seite bekomme ich die Metadaten für die Exposure Time. An Stelle 0x829a (oder in Dezimal 33434). Hier steckt
    laut der Seite ein "rational64u" in den Daten. Mein Visual Studio sagt, an der Stelle ist ein Byte-Array mit 8 Stellen. Wie muss ich die Zahlen zusammenrechnen? Mein Testfoto hat eine Belichtungszeit von 1/3128 Sek. Das müsste rauskommen.

    VB.NET-Quellcode

    1. Using Bild As New Bitmap(Bildpfade1(i))
    2. Dim propItems As PropertyItem() = Bild.PropertyItems
    3. Dim propItem As PropertyItem
    4. For Each propItem In propItems
    5. 'If propItem.Id = 33434 Then 'Exposure Time
    6. ' Debug.WriteLine(" ")
    7. 'End If
    8. Next 'propItems
    9. End Using
    Bilder
    • Vollbildaufzeichnung 08.11.2020 020209 - Kopie.jpg

      46,04 kB, 775×258, 99 mal angesehen
    Könntest du mir sagen, wie die Formel ist? Ich blick das nicht
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    @Bartosz Da stehen 8 Byte.
    Lies die als 4 Byte und noch mal 4 Byte. Lies die mit nem BinaryReader als zwei Mal Integer oder UInteger und führe eine Double-Division durch (/, nicht aber \).
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    ? Du musst nur zwei Integer einlesen. Der erste ist der Zähler, der zweite der Nenner. Ein int besteht aus 4 Bytes. Der BitConverter kann dir beim Zusammensetzen helfen. Einzig die Endianess, also Reihenfolge der Bytes, ist wichtig. Nix durch 16 teilen
    Let me see if I got this straight:

    nehmen wir als Beispiel die letzten 4 Bytes (56, 12, 0, 0).
    Jedes Element ist ein Byte und kann daher von 0 – 255 gehen. Es kann also nicht gelten.
    Ein Integer hat vier Bytes. Diese 4 Bytes stellen den Nenner des Ergebnisses dar. 8 bit: Daher 1111 1111 = 255. Wird deshalb als Byte dargestellt. Davon wiederum habe ich 4!

    Warum die 56 als verstehen? Und dann?

    Ich habe 56/16, sind 3 Ganze und Rest 8 . Nun kann ich die Potenz inkrementieren . Ich muss nur unterscheiden, ob die Zahl > oder < 16 ist, weil wenn ja, habe ich noch eine Potenz mehr zu verbrauchen (die Hoch 2 in wäre nicht nötig gewesen, wenn die erste Zahl (56) kleiner als 16 gewesen wäre). Dann weiter mit der nächsten Stelle im Byte-Array.

    So habe ich das verstanden. Dies soll nicht patzig sein, helft mir bitte, wenn ich Müll erzähl.

    VB.NET-Quellcode

    1. If propItem.Id = 33434 Then ' 0x829a Exposure Time [rational64u]
    2. '1
    3. '0
    4. '0
    5. '0
    6. '56
    7. '12
    8. '0
    9. '0
    10. 'Man muss rechnen 56÷16 = 3,5. Das führt zu 8*16^0 + 3*16^1 + 12*16^2
    11. Dim myByteArr(7) As Byte 'TEST = {1, 0, 0, 0, 18, 7, 0, 0}
    12. For q As Integer = 0 To propItem.Len - 1 Step 1
    13. myByteArr(q) = propItem.Value(q)
    14. Next
    15. Dim Zwischenergebnis As Long = 0
    16. Dim has_been_more_than_16 As Boolean = False
    17. Dim cnt As Integer = 0
    18. For w As Integer = 4 To 7 Step 1
    19. If myByteArr(w) > 16 Then
    20. Dim Rest As Long = myByteArr(w) Mod 16 '56÷16 -> Rest 8
    21. Dim ganze_Div As Long = myByteArr(w) \ 16 'Integer-Division -> 56÷16 = 3
    22. Zwischenergebnis += CLng(Rest * Math.Pow(16, cnt) + ganze_Div * Math.Pow(16, cnt + 1))
    23. has_been_more_than_16 = True
    24. cnt += 1
    25. Else
    26. Dim Rest As Long = myByteArr(w) Mod 16 'alles, was kleiner als 16 ist, bleibt dabei
    27. Dim ganze_Div As Long = myByteArr(w) \ 16 'wird 0 werden
    28. If has_been_more_than_16 Then
    29. Zwischenergebnis += CLng(Rest * Math.Pow(16, cnt + 1))
    30. Else
    31. Zwischenergebnis += CLng(Rest * Math.Pow(16, cnt))
    32. End If
    33. has_been_more_than_16 = False
    34. cnt += 1
    35. End If
    36. Next
    37. Debug.WriteLine("1/" & $"{Zwischenergebnis}")
    38. End If

    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.

    Bartosz schrieb:

    Jedes Element ist ein Byte und kann daher von 0 – 255 gehen. Es kann also nicht gelten.

    Genau, du hast die Basis 256 statt 2.
    Für Little Endian (was du da hast) gilt also:

    Die Methode BinaryFormatter.ReadUInt32 erledigt das für dich sogar automatisch.
    Mit freundlichen Grüßen,
    Thunderbolt
    @Thunderbolt Danke. Oh man, das habe ich nicht gesehen.
    Erledigt
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.