Skip to content

Commit 845ecd9

Browse files
committed
Minor refactoring of image saving code.
1 parent d7c3e61 commit 845ecd9

File tree

1 file changed

+61
-54
lines changed

1 file changed

+61
-54
lines changed

PhotoTagger.Imaging/ImageLoadManager.cs

Lines changed: 61 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ private static void makeFullImage(Photo.Metadata metadata, BitmapImage img) {
259259
img.Freeze();
260260
}
261261

262+
private class ImageLoadException : Exception {
263+
public ImageLoadException(string message) : base(message) { }
264+
}
265+
262266
/// <summary>
263267
/// Saves the given <see cref="Photo"/> to the disk.
264268
/// </summary>
@@ -268,61 +272,19 @@ private static void makeFullImage(Photo.Metadata metadata, BitmapImage img) {
268272
/// </param>
269273
/// <returns></returns>
270274
public static async Task Commit(Photo photo, string destination = null) {
271-
var tempFile = photo.FileName + DateTime.Now.Ticks.ToString() + ".tmp";
272-
if (destination != null) {
273-
tempFile = destination;
274-
}
275+
var tempFile = destination ?? photo.FileName + DateTime.Now.Ticks.ToString() + ".tmp";
275276
Photo.Metadata newSource;
276-
using (var mmap = MemoryMappedFile.OpenExisting(
277-
mmapName(photo.FileName),
278-
MemoryMappedFileRights.Read)) {
279-
using (var stream = new UnsafeMemoryMapStream(
280-
mmap.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read),
281-
FileAccess.Read)) {
282-
BitmapFrame sourceFrame;
283-
Guid format;
284-
int width, height;
285-
{
286-
var decoder = BitmapDecoder.Create(stream.Stream,
287-
BitmapCreateOptions.PreservePixelFormat,
288-
BitmapCacheOption.None);
289-
var frames = decoder.Frames;
290-
if (frames.Count < 1) {
291-
await photo.Dispatcher.InvokeAsync(() => {
292-
MessageBox.Show("Invalid image data",
293-
string.Format("Image {0} did not contain any frames.",
294-
photo.FileName),
295-
MessageBoxButton.OK,
296-
MessageBoxImage.Error);
297-
});
298-
return;
299-
}
300-
sourceFrame = frames[0];
301-
format = decoder.CodecInfo.ContainerFormat;
302-
width = sourceFrame.PixelWidth;
303-
height = sourceFrame.PixelHeight;
304-
}
305-
var md = sourceFrame.Metadata.Clone() as BitmapMetadata;
306-
newSource = await Exif.SetMetadata(photo, md);
307-
newSource.Width = width;
308-
newSource.Height = height;
309-
BitmapEncoder encoder;
310-
if (destination != null) {
311-
encoder = new JpegBitmapEncoder();
312-
} else {
313-
encoder = BitmapEncoder.Create(format);
314-
}
315-
encoder.Frames.Add(
316-
BitmapFrame.Create(
317-
sourceFrame.Clone() as BitmapFrame,
318-
sourceFrame.Thumbnail,
319-
md,
320-
sourceFrame.ColorContexts));
321-
sourceFrame = null;
322-
using (var outFile = new FileStream(tempFile, FileMode.CreateNew)) {
323-
encoder.Save(outFile);
324-
}
325-
}
277+
try {
278+
newSource = await reloadAndSave(photo, destination != null, tempFile);
279+
} catch (ImageLoadException ex) {
280+
await photo.Dispatcher.InvokeAsync(() => {
281+
MessageBox.Show("Invalid image data",
282+
string.Format($"Image {photo.FileName} {ex.Message}.",
283+
photo.FileName),
284+
MessageBoxButton.OK,
285+
MessageBoxImage.Error);
286+
});
287+
return;
326288
}
327289
if (destination == null) {
328290
var oldFile = tempFile + "2";
@@ -354,6 +316,51 @@ await photo.Dispatcher.InvokeAsync(() => {
354316
}
355317
}
356318

319+
private static async Task<Photo.Metadata> reloadAndSave(
320+
Photo photo, bool forceJpeg, string destFile) {
321+
using (var mmap = MemoryMappedFile.OpenExisting(
322+
mmapName(photo.FileName),
323+
MemoryMappedFileRights.Read)) {
324+
using (var stream = new UnsafeMemoryMapStream(
325+
mmap.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read),
326+
FileAccess.Read)) {
327+
BitmapFrame sourceFrame;
328+
Guid format;
329+
(sourceFrame, format) = loadFrame(stream.Stream);
330+
var md = sourceFrame.Metadata.Clone() as BitmapMetadata;
331+
Photo.Metadata newMetadata = await Exif.SetMetadata(photo, md);
332+
newMetadata.Width = sourceFrame.PixelWidth;
333+
newMetadata.Height = sourceFrame.PixelHeight;
334+
BitmapEncoder encoder = forceJpeg ?
335+
new JpegBitmapEncoder() :
336+
BitmapEncoder.Create(format);
337+
encoder.Frames.Add(
338+
BitmapFrame.Create(
339+
sourceFrame.Clone() as BitmapFrame,
340+
sourceFrame.Thumbnail,
341+
md,
342+
sourceFrame.ColorContexts));
343+
sourceFrame = null;
344+
using (var outFile = new FileStream(destFile, FileMode.CreateNew)) {
345+
encoder.Save(outFile);
346+
}
347+
return newMetadata;
348+
}
349+
}
350+
}
351+
352+
private static ValueTuple<BitmapFrame, Guid> loadFrame(Stream stream) {
353+
var decoder = BitmapDecoder.Create(stream,
354+
BitmapCreateOptions.PreservePixelFormat,
355+
BitmapCacheOption.None);
356+
var frames = decoder.Frames;
357+
if (frames.Count < 1) {
358+
throw new ImageLoadException("did not contain any frames");
359+
}
360+
var sourceFrame = frames[0];
361+
return (sourceFrame, decoder.CodecInfo.ContainerFormat);
362+
}
363+
357364
/// <summary>
358365
/// Remove <paramref name="oldFile"/> after closing any handles
359366
/// <paramref name="photo"/> might have open for it and replacing them

0 commit comments

Comments
 (0)