On some .JPG files (EPS previews, generated by Adobe Illustrator) in Windows 7 InPlaceBitmapMetadataWriter.TrySave() returns true after some SetQuery() calls, but does nothi
Hi I found this article about InPlaceBitmapMetadataWriter where the guy said that TrySave() might corrupt the image and that's why he advised to do TrySave() on the copy of the original file and if this doesn't work, add padding to the copy of original file and than TrySave() again and if it works, delete the original and rename the copy.
I scratched my head and asked myself why I should bother with InPlaceBitmapMetadataWriter and writing 3x original file to the disk in case TrySave() doesn't work because there is not enough padding, if I can clone metadata, write whatever into them and assemble jpeg file right away.
Then I started to think that maybe thanks to InPlaceBitmapMetadataWriter I can edit metadata without losing quality, but it looks like it "just" helps you to write metadata more quickly if there is enough padding.
I wrote a small test where I compress one file many times to see the quality degradation and you can see it in the third-fourth compression, which is very bad.
But luckily, if you always use same QualityLevel with JpegBitmapEncoder there is no degradation.
In this example I rewrite keywords 100x in metadata and the quality seems not to change.
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() : new List(metadata.Keywords);
keywords.Add($"Keyword {i:000}");
metadata.Keywords = new ReadOnlyCollection(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);
}
}
}
}