Dateimetadaten Kommentar ändern

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

Es gibt 29 Antworten in diesem Thema. Der letzte Beitrag () ist von Westerwälder.

    Hallo, hatte leider zwei Tage keine Zeit und dann finde ich folgendes im Forum

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub MetaDataEditor()
    2. If Me.Halt Then Exit Sub
    3. If IO.File.Exists(Me.TempDatei) Then IO.File.Delete(Me.TempDatei)
    4. Me.Quelldatei = Me.QuellPfad & Me.DGV_Quelldaten.CurrentRow.Cells("Dateiname").Value.ToString
    5. Dim createOptions As BitmapCreateOptions = BitmapCreateOptions.PreservePixelFormat Or BitmapCreateOptions.IgnoreColorProfile
    6. Dim paddingAmount As UInteger = 2048
    7. ' 2Kb padding for this example, but really this can be any value.
    8. ' Our recommendation is to keep this between 1Kb and 5Kb as most metadata updates are not large.
    9. ' High level overview:
    10. ' 1. Perform a lossles transcode on the JPEG
    11. ' 2. Add appropriate padding
    12. ' 3. Optionally add whatever metadata we need to add initially
    13. ' 4. Save the file
    14. ' 5. For sanity, we verify that we really did a lossless transcode
    15. ' 6. Open the new file and add metadata in-place
    16. Using originalFile As Stream = File.Open(Me.Quelldatei, FileMode.Open, FileAccess.Read)
    17. ' Notice the BitmapCreateOptions and BitmapCacheOption. Using these options in the manner here
    18. ' will inform the JPEG decoder and encoder that we're doing a lossless transcode operation. If the
    19. ' encoder is anything but a JPEG encoder, then this no longer is a lossless operation.
    20. ' ( Details: Basically BitmapCreateOptions.PreservePixelFormat | BitmapCreateOptions.IgnoreColorProfile
    21. ' tell the decoder to use the original image bits and BitmapCacheOption.None tells the decoder to wait
    22. ' with decoding. So, at the time of encoding the JPEG encoder understands that the input was a JPEG
    23. ' and just copies over the image bits without decompressing and recompressing them. Hence, this is a
    24. ' lossless operation. )
    25. Dim original As BitmapDecoder = BitmapDecoder.Create(originalFile, createOptions, BitmapCacheOption.None)
    26. If Not original.CodecInfo.FileExtensions.Contains("jpg") Then
    27. MsgBox("The file you passed in is not a JPEG.")
    28. 'Return
    29. End If
    30. Dim output As New JpegBitmapEncoder()
    31. ' If you're just interested in doing a lossless transcode without adding metadata, just do this:
    32. 'output.Frames = original.Frames;
    33. ' If you want to add metadata to the image using the InPlaceBitmapMetadataWriter, first add padding:
    34. If original.Frames(0) IsNot Nothing AndAlso original.Frames(0).Metadata IsNot Nothing Then
    35. ' Your gut feel may want you to do something like:
    36. ' output.Frames = original.Frames;
    37. ' BitmapMetadata metadata = output.Frames[0].Metadata as BitmapMetadata;
    38. ' if (metadata != null)
    39. ' {
    40. ' metadata.SetQuery("/app1/ifd/PaddingSchema:Padding", paddingAmount);
    41. ' }
    42. ' However, the BitmapMetadata object is frozen. So, you need to clone the BitmapMetadata and then
    43. ' set the padding on it. Lastly, you need to create a "new" frame with the updated metadata.
    44. Dim metadata As BitmapMetadata = TryCast(original.Frames(0).Metadata.Clone(), BitmapMetadata)
    45. ' Of the metadata handlers that we ship in WIC, padding can only exist in IFD, EXIF, and XMP.
    46. ' Third parties implementing their own metadata handler may wish to support IWICFastMetadataEncoder
    47. ' and hence support padding as well.
    48. metadata.SetQuery("/app1/ifd/PaddingSchema:Padding", paddingAmount)
    49. metadata.SetQuery("/app1/ifd/exif/PaddingSchema:Padding", paddingAmount)
    50. metadata.SetQuery("/xmp/PaddingSchema:Padding", paddingAmount)
    51. metadata.Title = "Das ist der Titel"
    52. metadata.SetQuery("System.Keywords", "Das ist eine Markierung")
    53. metadata.SetQuery("System.Author", "Ich bin der Autor von diesem Foto")
    54. metadata.Copyright = "Das ist das Copyrigh von dem Foto"
    55. metadata.Comment = "Der Kommentar"
    56. metadata.Rating = CInt("5")
    57. ' Create a new frame identical to the one from the original image, except the metadata will have padding.
    58. ' Essentially we want to keep this as close as possible to:
    59. ' output.Frames = original.Frames;
    60. output.Frames.Add(BitmapFrame.Create(original.Frames(0), original.Frames(0).Thumbnail, metadata, original.Frames(0).ColorContexts))
    61. End If
    62. Using outputFile As Stream = File.Open(Me.TempDatei, FileMode.Create, FileAccess.ReadWrite)
    63. output.Save(outputFile)
    64. End Using
    65. End Using
    66. ' For sanity, let's verify that the original and the output contain image bits that are the same.
    67. Using originalFile As Stream = File.Open(Me.Quelldatei, FileMode.Open, FileAccess.Read)
    68. Dim original As BitmapDecoder = BitmapDecoder.Create(originalFile, createOptions, BitmapCacheOption.None)
    69. Using savedFile As Stream = File.Open(Me.TempDatei, FileMode.Open, FileAccess.Read)
    70. Dim output As BitmapDecoder = BitmapDecoder.Create(savedFile, createOptions, BitmapCacheOption.None)
    71. End Using
    72. End Using
    73. IO.File.Delete(Me.Quelldatei)
    74. Rename(Me.TempDatei, Me.Quelldatei)
    75. End Sub




    Funktioniert im Testlauf. Denke ich werde es ein wenig anpassen und dann in mein Projekt so übernehmen.
    Gruß Markus

    Westerwälder schrieb:

    dann finde ich folgendes im Forum
    Gib mal die Quelle dazu an.
    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!
    Habe mir mal meine Dateien angeschaut, welche ich gerne ändern würde.
    Ausgenommen von PDF-Dateien haben alle (Excel, Word, MP3) die Tags
    Titel und Kommentar.
    Da ich nur diese beiden Tags ändern möchte (alle andere Einträge interessieren micht nicht), kann man dies nicht standardisieren?
    Eine Script- oder Batchlösung wäre mir auch recht.
    Gruß Markus
    Hallo und Frohe Pfingsten

    Bin nun bei Worddokumenten angekommen.

    VB.NET-Quellcode

    1. Public Sub Setzen(ByVal WordPfad As String, ByVal WordDatei As String,
    2. ByVal MetaTitel As String, ByVal MetaKommentar As String)
    3. If Not WordPfad.EndsWith("\") Then WordPfad = WordPfad & "\"
    4. Me.QuellDatei = WordPfad & WordDatei
    5. If Not IO.File.Exists(Me.QuellDatei) Then
    6. MessageBox.Show("Die Worddatei " & Me.QuellDatei & " existiert nicht.", Me.MessTitel, MessageBoxButtons.OK, MessageBoxIcon.Hand)
    7. Exit Sub
    8. End If
    9. Dim Worddokument As Package = Package.Open(Me.QuellDatei, FileMode.Open, FileAccess.ReadWrite)
    10. With Worddokument.PackageProperties
    11. .Title = MetaTitel
    12. .Subject = MetaKommentar
    13. End With
    14. ' Speichern der geänderten Eigenschaften in der Datei
    15. End Sub

    Leider gibt es keinen Package.Save oder ähnliches.
    Gruß Markus
    Für Office Word habe ich nun eine Lösung:

    VB.NET-Quellcode

    1. Public Sub Setzen(ByVal WordPfad As String, ByVal WordDatei As String,
    2. ByVal MetaTitel As String, ByVal MetaKommentar As String)
    3. If Not WordPfad.EndsWith("\") Then WordPfad = WordPfad & "\"
    4. Me.QuellDatei = WordPfad & WordDatei
    5. If Not IO.File.Exists(Me.QuellDatei) Then
    6. MessageBox.Show("Die Worddatei " & Me.QuellDatei & " existiert nicht.", Me.MessTitel, MessageBoxButtons.OK, MessageBoxIcon.Hand)
    7. Exit Sub
    8. End If
    9. Dim WordApp As New Word.Application
    10. Dim WordDokument As New Word.Document
    11. WordDokument = WordApp.Documents.Open(Me.QuellDatei.ToString)
    12. With WordDokument
    13. .BuiltInDocumentProperties("Title").value = MetaTitel
    14. .BuiltInDocumentProperties("Subject").value = MetaKommentar
    15. .BuiltInDocumentProperties("Comments").value = MetaKommentar
    16. .BuiltInDocumentProperties("Company").value = Programm.Copyright_Kurz
    17. End With
    18. WordDokument.Save()
    19. WordApp.ActiveDocument.Close()
    20. WordApp.Quit()
    21. WordDokument = Nothing
    22. End Sub

    Hier musste ich Option Strict Off setzen.
    Gruß Markus
    Word und Excel ist nun erledigt.
    Nun hänge ich an PDF fest. Für die Bearbeitung der Metadaten habe ich die itextsharp.dll importiert.

    Die Auslesung der Metadaten funktioniert auch:

    VB.NET-Quellcode

    1. Try
    2. Dim PDF_Reader As New iTextSharp.text.pdf.PdfReader(Me.QuellDatei)
    3. Dim HSTable As Hashtable = New Hashtable(PDF_Reader.Info)
    4. MessageBox.Show(HSTable("Author"))
    5. HSTable("Author") = "Markus"
    6. PDF_Reader.SafeFile '????
    7. Catch ex As Exception
    8. If Not Autokorr Then MessageBox.Show("Fehler Metadaten-Bearbeitung PDF-Dateien: " & vbNewLine &
    9. ex.Message, Me.MessTitel, MessageBoxButtons.OK, MessageBoxIcon.Hand)
    10. Fehlermeldung.Schreiben("Metadaten PDF Fehler: " & ex.Message)
    11. End Try

    Wie schreibe ich nun die geänderten Daten in die Datei auf der Festplatte zurück?
    Gruß Markus
    Hallo,
    habe für die PDF-Metadaten Änderung itextsharp 5.5.10 importiert.

    Nachstehend zwei Versuche die Daten zu ändern, was beides nicht fruchtet:

    VB.NET-Quellcode

    1. Public Sub Setzen(ByVal PDFPfad As String, ByVal PDFDatei As String,
    2. ByVal MetaTitel As String, ByVal MetaKommentar As String, ByVal MetaAkte As String,
    3. Optional Autokorr As Boolean = False)
    4. If Not PDFPfad.EndsWith("\") Then PDFPfad = PDFPfad & "\"
    5. Me.QuellDatei = PDFPfad & PDFDatei
    6. If Not IO.File.Exists(Me.QuellDatei) Then
    7. If Not Autokorr Then MessageBox.Show("Die PDF-Datei " & Me.QuellDatei & " existiert nicht.", Me.MessTitel, MessageBoxButtons.OK, MessageBoxIcon.Hand)
    8. Fehlermeldung.Schreiben("Metadaten: Datei " & Me.QuellDatei & " nicht im Verzeichnis vorhanden.")
    9. Exit Sub
    10. End If
    11. If IO.File.Exists(Me.TempDatei) Then IO.File.Delete(Me.TempDatei)
    12. Try
    13. 'Variante A) Dokument lesen und Änderungen in eine Tempdatei schreiben
    14. Dim PDF_Reader As New PdfReader(Me.QuellDatei)
    15. Dim PDF_Stamper = New PdfStamper(PDF_Reader, New IO.FileStream(Me.TempDatei, FileMode.Create))
    16. Dim Dic_Metadaten As New SortedDictionary(Of String, String)
    17. With Dic_Metadaten
    18. .Add("Author", Anwender.Name)
    19. .Add("Title", MetaTitel)
    20. .Add("Subject", MetaKommentar)
    21. .Add("Comments", MetaAkte)
    22. .Add("Company", Programm.Copyright_Kurz)
    23. End With
    24. With PDF_Stamper
    25. .MoreInfo = Dic_Metadaten
    26. .Close()
    27. End With
    28. PDF_Reader.Close()
    29. Threading.Thread.Sleep(1000)
    30. IO.File.Delete(Me.QuellDatei)
    31. Rename(Me.TempDatei, Me.QuellDatei)
    32. ' Ergebnis Variante A: Es erfolgte keine Änderung der Metadaten
    33. Exit Sub
    34. 'Variante B) Änderungen in Originaldatei vornehmen
    35. Dim PDF_Dokument As New iTextSharp.text.Document
    36. Dim FStream As New IO.FileStream(Me.QuellDatei, FileMode.Open)
    37. PdfWriter.GetInstance(PDF_Dokument, FStream)
    38. With PDF_Dokument
    39. .AddAuthor(Anwender.Name)
    40. .AddTitle(MetaTitel)
    41. .AddSubject(MetaKommentar)
    42. .AddKeywords("Comments, Texteintrag")
    43. .Open()
    44. .Close()
    45. End With
    46. FStream.Close()
    47. 'Fehler Variante B: Dokument hat keine Seiten
    48. Catch ex As Exception
    49. If Not Autokorr Then MessageBox.Show("Fehler Metadaten-Bearbeitung PDF-Dateien: " & vbNewLine &
    50. ex.Message, Me.MessTitel, MessageBoxButtons.OK, MessageBoxIcon.Hand)
    51. Fehlermeldung.Schreiben("Metadaten PDF Fehler: " & ex.Message)
    52. End Try
    53. End Sub

    Wie bereits im Code kommentiert, wird bei der Variante A die Tempdatei zwar erstellt, hat aber keine geänderte Metadaten und bei Variante B bekomme ich den Fehler: Dokument hat keine Seiten.
    Gruß Markus
    Danke Dir für den Hinweis.
    Mit dem DSOFile habe ich angefangen, die Daten zuändern.
    Hat nicht richtig funktioniert.
    Bis auf die PDF-Dateien ist alles erledigt.

    Habe mich bei ItextSharp an die Vorgaben gehalten.
    Keine Ahnung warum es nicht geht.
    Gruß Markus