WIP: JPEG200 support, just on Mac for now

This commit is contained in:
Ben Olden-Cooligan 2022-10-10 18:25:59 -07:00
parent 808113797e
commit c1f946df5f
31 changed files with 1027 additions and 1523 deletions

View File

@ -14,7 +14,8 @@ public class GdiImage : IMemoryImage
{
public GdiImage(ImageContext imageContext, Bitmap bitmap)
{
ImageContext = imageContext ?? throw new ArgumentNullException(nameof(imageContext));
if (imageContext is not GdiImageContext) throw new ArgumentException();
ImageContext = imageContext;
if (bitmap == null)
{
throw new ArgumentNullException(nameof(bitmap));
@ -62,6 +63,7 @@ public class GdiImage : IMemoryImage
{
imageFormat = ImageContext.GetFileFormatFromExtension(path);
}
ImageContext.CheckSupportsFormat(imageFormat);
if (imageFormat == ImageFileFormat.Jpeg && quality != -1)
{
var (encoder, encoderParams) = GetJpegSaveArgs(quality);
@ -79,6 +81,7 @@ public class GdiImage : IMemoryImage
{
throw new ArgumentException("Format required to save to a stream", nameof(imageFormat));
}
ImageContext.CheckSupportsFormat(imageFormat);
if (imageFormat == ImageFileFormat.Jpeg && quality != -1)
{
var (encoder, encoderParams) = GetJpegSaveArgs(quality);

View File

@ -20,6 +20,8 @@ public class GdiImageContext : ImageContext
_imageTransformer = new GdiImageTransformer(this);
}
protected override bool SupportsTiff => true;
public override IMemoryImage PerformTransform(IMemoryImage image, Transform transform)
{
var gdiImage = image as GdiImage ?? throw new ArgumentException("Expected GdiImage object");

View File

@ -8,7 +8,8 @@ public class GtkImage : IMemoryImage
{
public GtkImage(ImageContext imageContext, Pixbuf pixbuf)
{
ImageContext = imageContext ?? throw new ArgumentNullException(nameof(imageContext));
if (imageContext is not GtkImageContext) throw new ArgumentException();
ImageContext = imageContext;
Pixbuf = pixbuf;
LogicalPixelFormat = PixelFormat;
HorizontalResolution = float.TryParse(pixbuf.GetOption("x-dpi"), out var xDpi) ? xDpi : 0;
@ -72,6 +73,7 @@ public class GtkImage : IMemoryImage
{
imageFormat = ImageContext.GetFileFormatFromExtension(path);
}
ImageContext.CheckSupportsFormat(imageFormat);
var type = GetType(imageFormat);
var (keys, values) = GetSaveOptions(imageFormat, quality);
Pixbuf.Savev(path, type, keys, values);
@ -83,6 +85,7 @@ public class GtkImage : IMemoryImage
{
throw new ArgumentException("Format required to save to a stream", nameof(imageFormat));
}
ImageContext.CheckSupportsFormat(imageFormat);
var type = GetType(imageFormat);
var (keys, values) = GetSaveOptions(imageFormat, quality);
// TODO: Map to OutputStream directly?

View File

@ -14,6 +14,8 @@ public class GtkImageContext : ImageContext
_tiffIo = new LibTiffIo(this);
}
protected override bool SupportsTiff => true;
public override IMemoryImage PerformTransform(IMemoryImage image, Transform transform)
{
var gdiImage = image as GtkImage ?? throw new ArgumentException("Expected GtkImage object");

View File

@ -7,7 +7,8 @@ public class MacImage : IMemoryImage
{
public MacImage(ImageContext imageContext, NSImage image)
{
ImageContext = imageContext ?? throw new ArgumentNullException(nameof(imageContext));
if (imageContext is not MacImageContext) throw new ArgumentException();
ImageContext = imageContext;
NsImage = image ?? throw new ArgumentNullException(nameof(image));
var reps = NsImage.Representations();
if (reps.Length != 1)
@ -124,6 +125,7 @@ public class MacImage : IMemoryImage
{
imageFormat = ImageContext.GetFileFormatFromExtension(path);
}
ImageContext.CheckSupportsFormat(imageFormat);
var rep = GetRepForSaving(imageFormat, quality);
if (!rep.Save(path, false, out var error))
{
@ -137,6 +139,7 @@ public class MacImage : IMemoryImage
{
throw new ArgumentException("Format required to save to a stream", nameof(imageFormat));
}
ImageContext.CheckSupportsFormat(imageFormat);
var rep = GetRepForSaving(imageFormat, quality);
rep.AsStream().CopyTo(stream);
}
@ -145,7 +148,7 @@ public class MacImage : IMemoryImage
{
lock (MacImageContext.ConstructorLock)
{
var props = quality != -1 && imageFormat == ImageFileFormat.Jpeg
var props = quality != -1 && imageFormat is ImageFileFormat.Jpeg or ImageFileFormat.Jpeg2000
? NSDictionary.FromObjectAndKey(NSNumber.FromDouble(quality / 100.0),
NSBitmapImageRep.CompressionFactor)
: null;
@ -155,6 +158,7 @@ public class MacImage : IMemoryImage
ImageFileFormat.Png => NSBitmapImageFileType.Png,
ImageFileFormat.Bmp => NSBitmapImageFileType.Bmp,
ImageFileFormat.Tiff => NSBitmapImageFileType.Tiff,
ImageFileFormat.Jpeg2000 => NSBitmapImageFileType.Jpeg2000,
_ => throw new InvalidOperationException("Unsupported image format")
};
var targetFormat = LogicalPixelFormat;

View File

@ -16,6 +16,9 @@ public class MacImageContext : ImageContext
_imageTransformer = new MacImageTransformer(this);
}
protected override bool SupportsTiff => true;
protected override bool SupportsJpeg2000 => true;
public override IMemoryImage PerformTransform(IMemoryImage image, Transform transform)
{
var macImage = image as MacImage ?? throw new ArgumentException("Expected MacImage object");

View File

@ -5,6 +5,7 @@ public enum ImageFileFormat
Unspecified,
Bmp,
Jpeg,
Jpeg2000,
Png,
Tiff
}

View File

@ -16,6 +16,7 @@ public abstract class ImageContext
".bmp" => ImageFileFormat.Bmp,
".jpg" or ".jpeg" => ImageFileFormat.Jpeg,
".tif" or ".tiff" => ImageFileFormat.Tiff,
".jp2" or ".jpx" => ImageFileFormat.Jpeg2000,
_ => throw new ArgumentException($"Could not infer file format from extension: {path}")
};
}
@ -26,9 +27,9 @@ public abstract class ImageContext
{
return ImageFileFormat.Unspecified;
}
var firstBytes = new byte[4];
var firstBytes = new byte[8];
stream.Seek(0, SeekOrigin.Begin);
stream.Read(firstBytes, 0, 4);
stream.Read(firstBytes, 0, 8);
stream.Seek(0, SeekOrigin.Begin);
if (firstBytes[0] == 0x89 && firstBytes[1] == 0x50 && firstBytes[2] == 0x4E && firstBytes[3] == 0x47)
{
@ -50,6 +51,10 @@ public abstract class ImageContext
{
return ImageFileFormat.Tiff;
}
if (firstBytes[4] == 0x6A && firstBytes[5] == 0x50 && firstBytes[6] == 0x20 && firstBytes[7] == 0x20)
{
return ImageFileFormat.Jpeg2000;
}
return ImageFileFormat.Unspecified;
}
@ -122,6 +127,13 @@ public abstract class ImageContext
public Type ImageType { get; }
public bool SupportsFormat(ImageFileFormat format) =>
format is ImageFileFormat.Bmp or ImageFileFormat.Jpeg or ImageFileFormat.Png ||
format == ImageFileFormat.Tiff && SupportsTiff || format == ImageFileFormat.Jpeg2000 && SupportsJpeg2000;
protected virtual bool SupportsTiff => false;
protected virtual bool SupportsJpeg2000 => false;
// TODO: Implement these 4 load methods here, calling protected abstract internal methods.
// TODO: That will let us implement common behavior (reading file formats, setting originalfileformat/logicalpixelformat) consistently.
/// <summary>
@ -143,6 +155,7 @@ public abstract class ImageContext
public IMemoryImage Load(Stream stream)
{
var format = GetFileFormatFromFirstBytes(stream);
CheckSupportsFormat(format);
var image = LoadCore(stream, format);
if (image.OriginalFileFormat == ImageFileFormat.Unspecified)
{
@ -189,6 +202,15 @@ public abstract class ImageContext
private IAsyncEnumerable<IMemoryImage> DoLoadFrames(Stream stream, ImageFileFormat format, ProgressHandler progress,
bool disposeStream)
{
try
{
CheckSupportsFormat(format);
}
catch (Exception)
{
if (disposeStream) stream.Dispose();
throw;
}
return AsyncProducers.RunProducer<IMemoryImage>(produceImage =>
{
try
@ -222,7 +244,15 @@ public abstract class ImageContext
}
}
public abstract ITiffWriter TiffWriter { get; }
public void CheckSupportsFormat(ImageFileFormat format)
{
if (!SupportsFormat(format))
{
throw new NotSupportedException($"Unsupported file format: {format}");
}
}
public virtual ITiffWriter TiffWriter => throw new NotSupportedException();
public IMemoryImage Render(IRenderableImage image)
{

View File

@ -29,6 +29,7 @@ public class DesktopControllerTests : ContextualTests
private readonly ImageTransfer _imageTransfer;
private readonly ImageClipboard _imageClipboard;
private readonly Mock<IWinFormsExportHelper> _exportHelper;
private readonly Mock<DialogHelper> _dialogHelper;
private readonly DesktopImagesController _desktopImagesController;
private readonly Mock<IDesktopScanController> _desktopScanController;
private readonly DesktopFormProvider _desktopFormProvider;
@ -51,6 +52,7 @@ public class DesktopControllerTests : ContextualTests
_imageTransfer = new ImageTransfer();
_imageClipboard = new ImageClipboard();
_exportHelper = new Mock<IWinFormsExportHelper>();
_dialogHelper = new Mock<DialogHelper>();
_desktopImagesController = new DesktopImagesController(_imageList);
_desktopScanController = new Mock<IDesktopScanController>();
_desktopFormProvider = new DesktopFormProvider();
@ -72,6 +74,7 @@ public class DesktopControllerTests : ContextualTests
new ImageListActions(_imageList, _operationFactory.Object, _operationProgress.Object,
_config, _thumbnailController),
_exportHelper.Object,
_dialogHelper.Object,
_desktopImagesController,
_desktopScanController.Object,
_desktopFormProvider,

View File

@ -82,9 +82,9 @@ public partial class FAutoSaveSettings : FormBase
private void btnChooseFolder_Click(object sender, EventArgs e)
{
if (_dialogHelper.PromptToSavePdfOrImage(null, out string savePath))
if (_dialogHelper.PromptToSavePdfOrImage(null, out string? savePath))
{
txtFilePath.Text = savePath;
txtFilePath.Text = savePath!;
}
}

View File

@ -183,9 +183,9 @@ public partial class FBatchScan : FormBase
private void btnChooseFolder_Click(object sender, EventArgs e)
{
if (_dialogHelper.PromptToSavePdfOrImage(null, out string savePath))
if (_dialogHelper.PromptToSavePdfOrImage(null, out string? savePath))
{
txtFilePath.Text = savePath;
txtFilePath.Text = savePath!;
}
}

View File

@ -121,9 +121,9 @@ public partial class FImageSettings : FormBase
private void btnChooseFolder_Click(object sender, EventArgs e)
{
if (_dialogHelper.PromptToSaveImage(txtDefaultFilePath.Text, out string savePath))
if (_dialogHelper.PromptToSaveImage(txtDefaultFilePath.Text, out string? savePath))
{
txtDefaultFilePath.Text = savePath;
txtDefaultFilePath.Text = savePath!;
}
}
}

View File

@ -165,9 +165,9 @@ public partial class FPdfSettings : FormBase
private void btnChooseFolder_Click(object sender, EventArgs e)
{
if (_dialogHelper.PromptToSavePdf(txtDefaultFilePath.Text, out string savePath))
if (_dialogHelper.PromptToSavePdf(txtDefaultFilePath.Text, out string? savePath))
{
txtDefaultFilePath.Text = savePath;
txtDefaultFilePath.Text = savePath!;
}
}
}

View File

@ -0,0 +1,10 @@
namespace NAPS2.EtoForms;
[Flags]
public enum FileFilterGroup
{
Pdf = 1,
Image = 2,
AllFiles = 4,
AllImages = 8
}

View File

@ -0,0 +1,56 @@
using Eto.Forms;
namespace NAPS2.EtoForms;
public class FileFilters
{
private readonly ImageContext _imageContext;
public FileFilters(ImageContext imageContext)
{
_imageContext = imageContext;
}
public void Set(FileDialog fileDialog, FileFilterGroup groups, string? selectedExt = null)
{
var filters = fileDialog.Filters;
if (groups.HasFlag(FileFilterGroup.AllFiles))
{
filters.Add(new FileFilter(MiscResources.FileTypeAllFiles, ".*"));
}
if (groups.HasFlag(FileFilterGroup.Pdf))
{
filters.Add(new FileFilter(MiscResources.FileTypePdf, ".pdf"));
}
if (groups.HasFlag(FileFilterGroup.AllImages))
{
filters.Add(new FileFilter(MiscResources.FileTypeImageFiles,
".bmp", ".emf", ".exif", ".gif", "jpg", ".jpeg", ".png", ".tiff", ".tif"));
}
if (groups.HasFlag(FileFilterGroup.Image))
{
filters.Add(new FileFilter(MiscResources.FileTypeBmp, ".bmp"));
filters.Add(new FileFilter(MiscResources.FileTypeEmf, ".emf"));
filters.Add(new FileFilter(MiscResources.FileTypeExif, ".exif"));
filters.Add(new FileFilter(MiscResources.FileTypeGif, ".gif"));
filters.Add(new FileFilter(MiscResources.FileTypeJpeg, ".jpg", ".jpeg"));
if (_imageContext.SupportsFormat(ImageFileFormat.Jpeg2000))
{
filters.Add(new FileFilter(MiscResources.FileTypeJp2, ".jp2", ".jpx"));
}
filters.Add(new FileFilter(MiscResources.FileTypePng, ".png"));
filters.Add(new FileFilter(MiscResources.FileTypeTiff, ".tiff", ".tif"));
}
if (selectedExt != null)
{
selectedExt = selectedExt.Replace(".", "");
foreach (var filter in filters)
{
if (filter.Extensions.Any(x => x.Replace(".", "") == selectedExt))
{
fileDialog.CurrentFilter = filter;
}
}
}
}
}

View File

@ -111,9 +111,9 @@ public class AutoSaver
string subPath = placeholders.Substitute(settings.FilePath, true, i);
if (settings.PromptForFilePath)
{
if (_dialogHelper.PromptToSavePdfOrImage(subPath, out string newPath))
if (_dialogHelper.PromptToSavePdfOrImage(subPath, out string? newPath))
{
subPath = placeholders.Substitute(newPath, true, i);
subPath = placeholders.Substitute(newPath!, true, i);
}
}
// TODO: This placeholder handling is complex and wrong in some cases (e.g. FilePerScan with ext = "jpg")

View File

@ -1,6 +1,4 @@
using Eto.Drawing;
namespace NAPS2.ImportExport.Images;
namespace NAPS2.ImportExport.Images;
// TODO: Cross-platform TIFF
public class SaveImagesOperation : OperationBase
@ -47,9 +45,9 @@ public class SaveImagesOperation : OperationBase
fileName = Path.Combine(subFileName, "$(n).jpg");
subFileName = placeholders.Substitute(fileName, batch);
}
ImageFormat format = GetImageFormat(subFileName);
var format = ImageContext.GetFileFormatFromExtension(subFileName);
if (Equals(format, ImageFormat.Tiff) && !imageSettings.SinglePageTiff)
if (format == ImageFileFormat.Tiff && !imageSettings.SinglePageTiff)
{
if (File.Exists(subFileName))
{
@ -151,60 +149,22 @@ public class SaveImagesOperation : OperationBase
return true;
}
private void DoSaveImage(ProcessedImage image, string path, ImageFormat format, ImageSettings imageSettings)
private void DoSaveImage(ProcessedImage image, string path, ImageFileFormat format, ImageSettings imageSettings)
{
FileSystemHelper.EnsureParentDirExists(path);
if (Equals(format, ImageFormat.Tiff))
if (format == ImageFileFormat.Tiff)
{
using var renderedImage = image.Render();
_imageContext.TiffWriter.SaveTiff(new[] { renderedImage }, path,
imageSettings.TiffCompression.ToTiffCompressionType(), CancelToken);
}
else if (Equals(format, ImageFormat.Jpeg))
{
var quality = imageSettings.JpegQuality.Clamp(0, 100);
using var bitmap = image.Render();
bitmap.Save(path, ImageFileFormat.Jpeg, quality);
}
else
{
// Quality will be ignored when not needed
// TODO: Scale quality differently for jpeg2000?
var quality = imageSettings.JpegQuality.Clamp(0, 100);
using var bitmap = image.Render();
var fileFormat = format switch
{
ImageFormat.Bitmap => ImageFileFormat.Bmp,
ImageFormat.Jpeg => ImageFileFormat.Jpeg,
ImageFormat.Png => ImageFileFormat.Png
};
bitmap.Save(path, fileFormat);
}
}
private static ImageFormat GetImageFormat(string fileName)
{
string extension = Path.GetExtension(fileName);
switch (extension.ToLower())
{
// TODO: Get rid of unsupported file types
case ".bmp":
return ImageFormat.Bitmap;
// case ".emf":
// return ImageFormat.Emf;
case ".gif":
return ImageFormat.Gif;
// case ".ico":
// return ImageFormat.Icon;
case ".jpg":
case ".jpeg":
return ImageFormat.Jpeg;
case ".png":
return ImageFormat.Png;
case ".tif":
case ".tiff":
return ImageFormat.Tiff;
// case ".wmf":
// return ImageFormat.Wmf;
default:
return ImageFormat.Jpeg;
bitmap.Save(path, format, quality);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -177,6 +177,9 @@
<data name="FileTypeTiff" xml:space="preserve">
<value>TIFF File (*.tiff, *.tif)</value>
</data>
<data name="FileTypeJp2" xml:space="preserve">
<value>JPEG2000 File (*.jp2, *.jpx)</value>
</data>
<data name="NameMissing" xml:space="preserve">
<value>Name missing.</value>
</data>

View File

@ -13,6 +13,7 @@ public static class Paths
#if STANDALONE
AppDataPath = Path.Combine(ExecutablePath, "..", "Data");
#else
// TODO: Make lowercase for non-windows
AppDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "NAPS2");
#endif
var dataPathFromEnv = Environment.GetEnvironmentVariable("NAPS2_TEST_DATA");

View File

@ -33,6 +33,7 @@ public class DesktopController
private readonly ImageClipboard _imageClipboard;
private readonly ImageListActions _imageListActions;
private readonly IWinFormsExportHelper _exportHelper;
private readonly DialogHelper _dialogHelper;
private readonly DesktopImagesController _desktopImagesController;
private readonly IDesktopScanController _desktopScanController;
private readonly DesktopFormProvider _desktopFormProvider;
@ -46,6 +47,7 @@ public class DesktopController
StillImage stillImage,
IUpdateChecker updateChecker, INotificationManager notify, ImageTransfer imageTransfer,
ImageClipboard imageClipboard, ImageListActions imageListActions, IWinFormsExportHelper exportHelper,
DialogHelper dialogHelper,
DesktopImagesController desktopImagesController, IDesktopScanController desktopScanController,
DesktopFormProvider desktopFormProvider, IScannedImagePrinter scannedImagePrinter)
{
@ -63,6 +65,7 @@ public class DesktopController
_imageClipboard = imageClipboard;
_imageListActions = imageListActions;
_exportHelper = exportHelper;
_dialogHelper = dialogHelper;
_desktopImagesController = desktopImagesController;
_desktopScanController = desktopScanController;
_desktopFormProvider = desktopFormProvider;
@ -490,35 +493,9 @@ public class DesktopController
public void Import()
{
// TODO: Merge this into exporthelper/dialoghelper?
var ofd = new OpenFileDialog
if (_dialogHelper.PromptToImport(out var fileNames))
{
MultiSelect = true,
CheckFileExists = true,
Filters =
{
// TODO: Move filter logic somewhere common
new FileFilter(MiscResources.FileTypeAllFiles, ".*"),
new FileFilter(MiscResources.FileTypePdf, ".pdf"),
new FileFilter(MiscResources.FileTypeImageFiles,
".bmp", ".emf", ".exif", ".gif", "jpg", ".jpeg", ".png", ".tiff", ".tif"),
new FileFilter(MiscResources.FileTypeBmp, ".bmp"),
new FileFilter(MiscResources.FileTypeEmf, ".emf"),
new FileFilter(MiscResources.FileTypeExif, ".exif"),
new FileFilter(MiscResources.FileTypeGif, ".gif"),
new FileFilter(MiscResources.FileTypeJpeg, ".jpg", ".jpeg"),
new FileFilter(MiscResources.FileTypePng, ".png"),
new FileFilter(MiscResources.FileTypeTiff, ".tiff", ".tif"),
}
};
if (Paths.IsTestAppDataPath)
{
// For UI test automation we choose the appdata folder to find the prepared files to import
ofd.Directory = new Uri(Path.GetFullPath(Paths.AppData));
}
if (ofd.ShowDialog(_desktopFormProvider.DesktopForm) == DialogResult.Ok)
{
ImportFiles(ofd.Filenames);
ImportFiles(fileNames!);
}
}
}

View File

@ -2,9 +2,11 @@
public abstract class DialogHelper
{
public abstract bool PromptToSavePdfOrImage(string? defaultPath, out string savePath);
public abstract bool PromptToSavePdfOrImage(string? defaultPath, out string? savePath);
public abstract bool PromptToSavePdf(string? defaultPath, out string savePath);
public abstract bool PromptToSavePdf(string? defaultPath, out string? savePath);
public abstract bool PromptToSaveImage(string? defaultPath, out string savePath);
public abstract bool PromptToSaveImage(string? defaultPath, out string? savePath);
public abstract bool PromptToImport(out string[]? filePaths);
}

View File

@ -2,21 +2,27 @@
public class StubDialogHelper : DialogHelper
{
public override bool PromptToSavePdfOrImage(string defaultPath, out string savePath)
public override bool PromptToSavePdfOrImage(string? defaultPath, out string? savePath)
{
savePath = null;
return false;
}
public override bool PromptToSavePdf(string defaultPath, out string savePath)
public override bool PromptToSavePdf(string? defaultPath, out string? savePath)
{
savePath = null;
return false;
}
public override bool PromptToSaveImage(string defaultPath, out string savePath)
public override bool PromptToSaveImage(string? defaultPath, out string? savePath)
{
savePath = null;
return false;
}
public override bool PromptToImport(out string[]? filePaths)
{
filePaths = null;
return false;
}
}

View File

@ -1,37 +1,29 @@
using Eto.Forms;
using NAPS2.EtoForms;
namespace NAPS2.WinForms;
public class WinFormsDialogHelper : DialogHelper
{
private readonly Naps2Config _config;
private readonly FileFilters _fileFilters;
public WinFormsDialogHelper(Naps2Config config)
public WinFormsDialogHelper(Naps2Config config, FileFilters fileFilters)
{
_config = config;
_fileFilters = fileFilters;
}
public override bool PromptToSavePdfOrImage(string? defaultPath, out string savePath)
public override bool PromptToSavePdfOrImage(string? defaultPath, out string? savePath)
{
var sd = new SaveFileDialog
{
CheckFileExists = false,
// TODO
// AddExtension = true,
// TODO: Move filter logic somewhere common
Filters =
{
new FileFilter(MiscResources.FileTypePdf, ".pdf"),
new FileFilter(MiscResources.FileTypeBmp, ".bmp"),
new FileFilter(MiscResources.FileTypeEmf, ".emf"),
new FileFilter(MiscResources.FileTypeExif, ".exif"),
new FileFilter(MiscResources.FileTypeGif, ".gif"),
new FileFilter(MiscResources.FileTypeJpeg, ".jpg", ".jpeg"),
new FileFilter(MiscResources.FileTypePng, ".png"),
new FileFilter(MiscResources.FileTypeTiff, ".tiff", ".tif"),
},
FileName = Path.GetFileName(defaultPath)
};
_fileFilters.Set(sd, FileFilterGroup.Pdf | FileFilterGroup.Image);
SetDir(sd, defaultPath);
if (sd.ShowDialog(null) == DialogResult.Ok)
{
@ -42,18 +34,15 @@ public class WinFormsDialogHelper : DialogHelper
return false;
}
public override bool PromptToSavePdf(string? defaultPath, out string savePath)
public override bool PromptToSavePdf(string? defaultPath, out string? savePath)
{
var sd = new SaveFileDialog
{
CheckFileExists = false,
// AddExtension = true,
Filters =
{
new FileFilter(MiscResources.FileTypePdf, ".pdf"),
},
FileName = Path.GetFileName(defaultPath)
};
_fileFilters.Set(sd, FileFilterGroup.Pdf);
SetDir(sd, defaultPath);
if (sd.ShowDialog(null) == DialogResult.Ok)
{
@ -64,51 +53,17 @@ public class WinFormsDialogHelper : DialogHelper
return false;
}
public override bool PromptToSaveImage(string? defaultPath, out string savePath)
public override bool PromptToSaveImage(string? defaultPath, out string? savePath)
{
var sd = new SaveFileDialog
{
CheckFileExists = false,
// AddExtension = true,
// TODO: Move filter logic somewhere common
Filters =
{
new FileFilter(MiscResources.FileTypeBmp, ".bmp"),
new FileFilter(MiscResources.FileTypeEmf, ".emf"),
new FileFilter(MiscResources.FileTypeExif, ".exif"),
new FileFilter(MiscResources.FileTypeGif, ".gif"),
new FileFilter(MiscResources.FileTypeJpeg, ".jpg", ".jpeg"),
new FileFilter(MiscResources.FileTypePng, ".png"),
new FileFilter(MiscResources.FileTypeTiff, ".tiff", ".tif"),
},
FileName = Path.GetFileName(defaultPath)
};
var lastExt = _config.Get(c => c.LastImageExt)?.ToLowerInvariant();
_fileFilters.Set(sd, FileFilterGroup.Image, lastExt ?? "jpg");
SetDir(sd, defaultPath);
switch (_config.Get(c => c.LastImageExt)?.ToLowerInvariant())
{
case "bmp":
sd.CurrentFilterIndex = 0;
break;
case "emf":
sd.CurrentFilterIndex = 1;
break;
case "exif":
sd.CurrentFilterIndex = 2;
break;
case "gif":
sd.CurrentFilterIndex = 3;
break;
case "png":
sd.CurrentFilterIndex = 5;
break;
case "tif":
case "tiff":
sd.CurrentFilterIndex = 6;
break;
default: // Jpeg
sd.CurrentFilterIndex = 4;
break;
}
if (sd.ShowDialog(null) == DialogResult.Ok)
{
savePath = sd.FileName;
@ -138,4 +93,27 @@ public class WinFormsDialogHelper : DialogHelper
dialog.Directory = new Uri(Path.GetFullPath(path));
}
}
public override bool PromptToImport(out string[]? filePaths)
{
var ofd = new OpenFileDialog
{
MultiSelect = true,
CheckFileExists = true
};
_fileFilters.Set(ofd,
FileFilterGroup.AllFiles | FileFilterGroup.Pdf | FileFilterGroup.AllImages | FileFilterGroup.Image);
if (Paths.IsTestAppDataPath)
{
// For UI test automation we choose the appdata folder to find the prepared files to import
ofd.Directory = new Uri(Path.GetFullPath(Paths.AppData));
}
if (ofd.ShowDialog(null) == DialogResult.Ok)
{
filePaths = ofd.Filenames.ToArray();
return true;
}
filePaths = null;
return false;
}
}

View File

@ -38,7 +38,7 @@ public class WinFormsExportHelper : IWinFormsExportHelper
}
else
{
if (!_dialogHelper.PromptToSavePdf(defaultFileName, out savePath))
if (!_dialogHelper.PromptToSavePdf(defaultFileName, out savePath!))
{
return false;
}
@ -79,7 +79,7 @@ public class WinFormsExportHelper : IWinFormsExportHelper
}
else
{
if (!_dialogHelper.PromptToSaveImage(_config.Get(c => c.ImageSettings.DefaultFileName), out savePath))
if (!_dialogHelper.PromptToSaveImage(_config.Get(c => c.ImageSettings.DefaultFileName), out savePath!))
{
return false;
}

View File

@ -7,8 +7,9 @@ public class WinFormsOverwritePrompt : IOverwritePrompt
public OverwriteResponse ConfirmOverwrite(string path)
{
string fileName = Path.GetFileName(path);
var dialogResult = MessageBox.Show(string.Format(MiscResources.ConfirmOverwriteFile, fileName),
MiscResources.OverwriteFile, MessageBoxButtons.YesNoCancel, MessageBoxType.Warning);
var dialogResult = Invoker.Current.InvokeGet(() =>
MessageBox.Show(string.Format(MiscResources.ConfirmOverwriteFile, fileName),
MiscResources.OverwriteFile, MessageBoxButtons.YesNoCancel, MessageBoxType.Warning));
return dialogResult switch
{
DialogResult.Yes => OverwriteResponse.Yes,

View File

@ -11,46 +11,32 @@ namespace NAPS2.Sdk.Tests {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class ImageResources {
private static global::System.Resources.ResourceManager resourceMan;
private static System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
private static System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal ImageResources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
internal static System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NAPS2.Sdk.Tests.ImageResources", typeof(ImageResources).Assembly);
if (object.Equals(null, resourceMan)) {
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("NAPS2.Sdk.Tests.ImageResources", typeof(ImageResources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
internal static System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
@ -59,29 +45,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] animals_tiff {
get {
object obj = ResourceManager.GetObject("animals_tiff", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] deskewed {
get {
object obj = ResourceManager.GetObject("deskewed", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog {
get {
object obj = ResourceManager.GetObject("dog", resourceCulture);
@ -89,69 +52,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_alpha {
get {
object obj = ResourceManager.GetObject("dog_alpha", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_alpha_tiff {
get {
object obj = ResourceManager.GetObject("dog_alpha_tiff", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_b_n300 {
get {
object obj = ResourceManager.GetObject("dog_b_n300", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_b_p300 {
get {
object obj = ResourceManager.GetObject("dog_b_p300", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_b_p300_thumb_256 {
get {
object obj = ResourceManager.GetObject("dog_b_p300_thumb_256", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_bmp {
get {
object obj = ResourceManager.GetObject("dog_bmp", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_bw {
get {
object obj = ResourceManager.GetObject("dog_bw", resourceCulture);
@ -159,9 +59,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_bw_24bit {
get {
object obj = ResourceManager.GetObject("dog_bw_24bit", resourceCulture);
@ -169,29 +66,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_bw_bmp {
get {
object obj = ResourceManager.GetObject("dog_bw_bmp", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_bw_invertpal {
get {
object obj = ResourceManager.GetObject("dog_bw_invertpal", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_bw_jpg {
get {
object obj = ResourceManager.GetObject("dog_bw_jpg", resourceCulture);
@ -199,19 +73,13 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_bw_p300 {
internal static byte[] dog_bw_bmp {
get {
object obj = ResourceManager.GetObject("dog_bw_p300", resourceCulture);
object obj = ResourceManager.GetObject("dog_bw_bmp", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_bw_tiff {
get {
object obj = ResourceManager.GetObject("dog_bw_tiff", resourceCulture);
@ -219,9 +87,34 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_bw_p300 {
get {
object obj = ResourceManager.GetObject("dog_bw_p300", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_bw_invertpal {
get {
object obj = ResourceManager.GetObject("dog_bw_invertpal", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_b_n300 {
get {
object obj = ResourceManager.GetObject("dog_b_n300", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_b_p300 {
get {
object obj = ResourceManager.GetObject("dog_b_p300", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_c_5_10_15_20 {
get {
object obj = ResourceManager.GetObject("dog_c_5_10_15_20", resourceCulture);
@ -229,9 +122,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_c_n300 {
get {
object obj = ResourceManager.GetObject("dog_c_n300", resourceCulture);
@ -239,9 +129,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_c_p300 {
get {
object obj = ResourceManager.GetObject("dog_c_p300", resourceCulture);
@ -249,69 +136,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_gray {
get {
object obj = ResourceManager.GetObject("dog_gray", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_gray_24bit_png {
get {
object obj = ResourceManager.GetObject("dog_gray_24bit_png", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_gray_24bit_tiff {
get {
object obj = ResourceManager.GetObject("dog_gray_24bit_tiff", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_gray_bmp {
get {
object obj = ResourceManager.GetObject("dog_gray_bmp", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_gray_png {
get {
object obj = ResourceManager.GetObject("dog_gray_png", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_gray_tiff {
get {
object obj = ResourceManager.GetObject("dog_gray_tiff", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_h_n300 {
get {
object obj = ResourceManager.GetObject("dog_h_n300", resourceCulture);
@ -319,9 +143,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_h_p300 {
get {
object obj = ResourceManager.GetObject("dog_h_p300", resourceCulture);
@ -329,59 +150,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_huge {
get {
object obj = ResourceManager.GetObject("dog_huge", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_huge_png {
get {
object obj = ResourceManager.GetObject("dog_huge_png", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_low_quality {
get {
object obj = ResourceManager.GetObject("dog_low_quality", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_mask {
get {
object obj = ResourceManager.GetObject("dog_mask", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_png {
get {
object obj = ResourceManager.GetObject("dog_png", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_r_180 {
get {
object obj = ResourceManager.GetObject("dog_r_180", resourceCulture);
@ -389,9 +157,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_r_n45 {
get {
object obj = ResourceManager.GetObject("dog_r_n45", resourceCulture);
@ -399,9 +164,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_r_p46 {
get {
object obj = ResourceManager.GetObject("dog_r_p46", resourceCulture);
@ -409,9 +171,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_r_p90 {
get {
object obj = ResourceManager.GetObject("dog_r_p90", resourceCulture);
@ -419,29 +178,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_s_n300 {
get {
object obj = ResourceManager.GetObject("dog_s_n300", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_s_p300 {
get {
object obj = ResourceManager.GetObject("dog_s_p300", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_sc_50pct {
get {
object obj = ResourceManager.GetObject("dog_sc_50pct", resourceCulture);
@ -449,9 +185,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_sh_n1000 {
get {
object obj = ResourceManager.GetObject("dog_sh_n1000", resourceCulture);
@ -459,9 +192,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_sh_p1000 {
get {
object obj = ResourceManager.GetObject("dog_sh_p1000", resourceCulture);
@ -469,9 +199,20 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_s_n300 {
get {
object obj = ResourceManager.GetObject("dog_s_n300", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_s_p300 {
get {
object obj = ResourceManager.GetObject("dog_s_p300", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_thumb_256 {
get {
object obj = ResourceManager.GetObject("dog_thumb_256", resourceCulture);
@ -479,49 +220,13 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_tiff {
internal static byte[] deskewed {
get {
object obj = ResourceManager.GetObject("dog_tiff", resourceCulture);
object obj = ResourceManager.GetObject("deskewed", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] image_upc_barcode {
get {
object obj = ResourceManager.GetObject("image_upc_barcode", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] ocr_test {
get {
object obj = ResourceManager.GetObject("ocr_test", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] patcht {
get {
object obj = ResourceManager.GetObject("patcht", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] skewed {
get {
object obj = ResourceManager.GetObject("skewed", resourceCulture);
@ -529,9 +234,6 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] skewed_bw {
get {
object obj = ResourceManager.GetObject("skewed_bw", resourceCulture);
@ -539,14 +241,158 @@ namespace NAPS2.Sdk.Tests {
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] stock_cat {
get {
object obj = ResourceManager.GetObject("stock_cat", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_b_p300_thumb_256 {
get {
object obj = ResourceManager.GetObject("dog_b_p300_thumb_256", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] patcht {
get {
object obj = ResourceManager.GetObject("patcht", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] ocr_test {
get {
object obj = ResourceManager.GetObject("ocr_test", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] image_upc_barcode {
get {
object obj = ResourceManager.GetObject("image_upc_barcode", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_low_quality {
get {
object obj = ResourceManager.GetObject("dog_low_quality", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_alpha {
get {
object obj = ResourceManager.GetObject("dog_alpha", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_alpha_tiff {
get {
object obj = ResourceManager.GetObject("dog_alpha_tiff", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_mask {
get {
object obj = ResourceManager.GetObject("dog_mask", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_jp2 {
get {
object obj = ResourceManager.GetObject("dog_jp2", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_png {
get {
object obj = ResourceManager.GetObject("dog_png", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_bmp {
get {
object obj = ResourceManager.GetObject("dog_bmp", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_tiff {
get {
object obj = ResourceManager.GetObject("dog_tiff", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_huge {
get {
object obj = ResourceManager.GetObject("dog_huge", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_huge_png {
get {
object obj = ResourceManager.GetObject("dog_huge_png", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] animals_tiff {
get {
object obj = ResourceManager.GetObject("animals_tiff", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_gray {
get {
object obj = ResourceManager.GetObject("dog_gray", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_gray_png {
get {
object obj = ResourceManager.GetObject("dog_gray_png", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_gray_24bit_png {
get {
object obj = ResourceManager.GetObject("dog_gray_24bit_png", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_gray_bmp {
get {
object obj = ResourceManager.GetObject("dog_gray_bmp", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_gray_tiff {
get {
object obj = ResourceManager.GetObject("dog_gray_tiff", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] dog_gray_24bit_tiff {
get {
object obj = ResourceManager.GetObject("dog_gray_24bit_tiff", resourceCulture);
return ((byte[])(obj));
}
}
}
}

View File

@ -229,6 +229,9 @@
<data name="dog_mask" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\dog_mask.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="dog_jp2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\dog.jp2;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="dog_png" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\dog.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>

View File

@ -172,6 +172,11 @@ public class LoadSaveTests : ContextualTests
new[] { "dog_bw" }, new[] { ImagePixelFormat.Gray8 }, false
},
new object[]
{
ImageFileFormat.Jpeg2000, ".jp2", "dog_jp2",
new[] { "dog" }, new[] { ImagePixelFormat.RGB24 }, false
},
new object[]
{
ImageFileFormat.Bmp, ".bmp", "dog_bmp",
new[] { "dog" }, new[] { ImagePixelFormat.RGB24 }, true

Binary file not shown.

View File

@ -40,6 +40,7 @@ public class ProcessedImage : IRenderableImage, IDisposable, IEquatable<Processe
public ImageContext ImageContext { get; }
// TODO: Consider having two copies of the image on disk - one before transforms, one after.
public IImageStorage Storage { get; }
public ImageMetadata Metadata { get; }