Hallo Ich fand this Artikel über InPlaceBitmapMetadataWriter, wo der Typ sagte, dass TrySave() das Bild beschädigen könnte und deshalb riet er, TrySave() auf die Kopie der ursprünglichen Datei zu tun und wenn dies nicht funktioniert, fügen Sie Auffüllen zur Kopie der Originaldatei und als TrySave() erneut und wenn es funktioniert, löschen Sie das Original und benennen Sie die Kopie um.
Ich kratzte mich am Kopf und fragte mich, warum ich mich mit InPlaceBitmapMetadataWriter beschäftigen und 3x Originaldatei auf die Festplatte schreiben sollte, falls TrySave() nicht funktioniert, da ich nicht genügend Padding habe, Metadaten klonen kann sie und jpeg Datei sofort zusammenbauen.
Dann begann ich zu denken, dass ich dank InPlaceBitmapMetadataWriter Metadaten bearbeiten kann, ohne Qualität zu verlieren, aber es sieht so aus, als ob es "nur" hilft, Metadaten schneller zu schreiben, wenn genug Padding vorhanden ist.
Ich schrieb einen kleinen Test, wo ich eine Datei viele Male komprimiere, um die Qualitätsverschlechterung zu sehen, und Sie können es in der dritten bis vierten Kompression sehen, die sehr schlecht ist.
Aber zum Glück, wenn Sie immer die gleichen QualityLevel mit JpegBitmapEncoder verwenden, gibt es keine Verschlechterung.
In diesem Beispiel habe ich die Schlüsselwörter 100x in Metadaten umgeschrieben und die Qualität scheint sich nicht zu ändern.
private void LosslessJpegTest() {
var original = "d:\\!test\\TestInTest\\20150205_123011.jpg";
var copy = original;
const BitmapCreateOptions createOptions = BitmapCreateOptions.PreservePixelFormat | BitmapCreateOptions.IgnoreColorProfile;
for (int i = 0; i < 100; i++) {
using (Stream originalFileStream = File.Open(copy, FileMode.Open, FileAccess.Read)) {
BitmapDecoder decoder = BitmapDecoder.Create(originalFileStream, createOptions, BitmapCacheOption.None);
if (decoder.CodecInfo == null || !decoder.CodecInfo.FileExtensions.Contains("jpg") || decoder.Frames[0] == null)
continue;
BitmapMetadata metadata = decoder.Frames[0].Metadata == null
? new BitmapMetadata("jpg")
: decoder.Frames[0].Metadata.Clone() as BitmapMetadata;
if (metadata == null) continue;
var keywords = metadata.Keywords == null ? new List<string>() : new List<string>(metadata.Keywords);
keywords.Add($"Keyword {i:000}");
metadata.Keywords = new ReadOnlyCollection<string>(keywords);
JpegBitmapEncoder encoder = new JpegBitmapEncoder {QualityLevel = 80};
encoder.Frames.Add(BitmapFrame.Create(decoder.Frames[0], decoder.Frames[0].Thumbnail, metadata,
decoder.Frames[0].ColorContexts));
copy = original.Replace(".", $"_{i:000}.");
using (Stream newFileStream = File.Open(copy, FileMode.Create, FileAccess.ReadWrite)) {
encoder.Save(newFileStream);
}
}
}
}
TrySave() gibt _true_ zurück! Tut aber nichts. Es gibt also keine Möglichkeit herauszufinden, ob Metadaten geschrieben sind oder nicht. – mephisto123
Lazo, es gibt keine sichere Methode für den Encoder in .NET 4. – Roger