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) 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) if (bitmap == null)
{ {
throw new ArgumentNullException(nameof(bitmap)); throw new ArgumentNullException(nameof(bitmap));
@ -62,6 +63,7 @@ public class GdiImage : IMemoryImage
{ {
imageFormat = ImageContext.GetFileFormatFromExtension(path); imageFormat = ImageContext.GetFileFormatFromExtension(path);
} }
ImageContext.CheckSupportsFormat(imageFormat);
if (imageFormat == ImageFileFormat.Jpeg && quality != -1) if (imageFormat == ImageFileFormat.Jpeg && quality != -1)
{ {
var (encoder, encoderParams) = GetJpegSaveArgs(quality); 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)); throw new ArgumentException("Format required to save to a stream", nameof(imageFormat));
} }
ImageContext.CheckSupportsFormat(imageFormat);
if (imageFormat == ImageFileFormat.Jpeg && quality != -1) if (imageFormat == ImageFileFormat.Jpeg && quality != -1)
{ {
var (encoder, encoderParams) = GetJpegSaveArgs(quality); var (encoder, encoderParams) = GetJpegSaveArgs(quality);

View File

@ -20,6 +20,8 @@ public class GdiImageContext : ImageContext
_imageTransformer = new GdiImageTransformer(this); _imageTransformer = new GdiImageTransformer(this);
} }
protected override bool SupportsTiff => true;
public override IMemoryImage PerformTransform(IMemoryImage image, Transform transform) public override IMemoryImage PerformTransform(IMemoryImage image, Transform transform)
{ {
var gdiImage = image as GdiImage ?? throw new ArgumentException("Expected GdiImage object"); 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) 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; Pixbuf = pixbuf;
LogicalPixelFormat = PixelFormat; LogicalPixelFormat = PixelFormat;
HorizontalResolution = float.TryParse(pixbuf.GetOption("x-dpi"), out var xDpi) ? xDpi : 0; HorizontalResolution = float.TryParse(pixbuf.GetOption("x-dpi"), out var xDpi) ? xDpi : 0;
@ -72,6 +73,7 @@ public class GtkImage : IMemoryImage
{ {
imageFormat = ImageContext.GetFileFormatFromExtension(path); imageFormat = ImageContext.GetFileFormatFromExtension(path);
} }
ImageContext.CheckSupportsFormat(imageFormat);
var type = GetType(imageFormat); var type = GetType(imageFormat);
var (keys, values) = GetSaveOptions(imageFormat, quality); var (keys, values) = GetSaveOptions(imageFormat, quality);
Pixbuf.Savev(path, type, keys, values); 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)); throw new ArgumentException("Format required to save to a stream", nameof(imageFormat));
} }
ImageContext.CheckSupportsFormat(imageFormat);
var type = GetType(imageFormat); var type = GetType(imageFormat);
var (keys, values) = GetSaveOptions(imageFormat, quality); var (keys, values) = GetSaveOptions(imageFormat, quality);
// TODO: Map to OutputStream directly? // TODO: Map to OutputStream directly?

View File

@ -14,6 +14,8 @@ public class GtkImageContext : ImageContext
_tiffIo = new LibTiffIo(this); _tiffIo = new LibTiffIo(this);
} }
protected override bool SupportsTiff => true;
public override IMemoryImage PerformTransform(IMemoryImage image, Transform transform) public override IMemoryImage PerformTransform(IMemoryImage image, Transform transform)
{ {
var gdiImage = image as GtkImage ?? throw new ArgumentException("Expected GtkImage object"); 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) 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)); NsImage = image ?? throw new ArgumentNullException(nameof(image));
var reps = NsImage.Representations(); var reps = NsImage.Representations();
if (reps.Length != 1) if (reps.Length != 1)
@ -124,6 +125,7 @@ public class MacImage : IMemoryImage
{ {
imageFormat = ImageContext.GetFileFormatFromExtension(path); imageFormat = ImageContext.GetFileFormatFromExtension(path);
} }
ImageContext.CheckSupportsFormat(imageFormat);
var rep = GetRepForSaving(imageFormat, quality); var rep = GetRepForSaving(imageFormat, quality);
if (!rep.Save(path, false, out var error)) 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)); throw new ArgumentException("Format required to save to a stream", nameof(imageFormat));
} }
ImageContext.CheckSupportsFormat(imageFormat);
var rep = GetRepForSaving(imageFormat, quality); var rep = GetRepForSaving(imageFormat, quality);
rep.AsStream().CopyTo(stream); rep.AsStream().CopyTo(stream);
} }
@ -145,7 +148,7 @@ public class MacImage : IMemoryImage
{ {
lock (MacImageContext.ConstructorLock) 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), ? NSDictionary.FromObjectAndKey(NSNumber.FromDouble(quality / 100.0),
NSBitmapImageRep.CompressionFactor) NSBitmapImageRep.CompressionFactor)
: null; : null;
@ -155,6 +158,7 @@ public class MacImage : IMemoryImage
ImageFileFormat.Png => NSBitmapImageFileType.Png, ImageFileFormat.Png => NSBitmapImageFileType.Png,
ImageFileFormat.Bmp => NSBitmapImageFileType.Bmp, ImageFileFormat.Bmp => NSBitmapImageFileType.Bmp,
ImageFileFormat.Tiff => NSBitmapImageFileType.Tiff, ImageFileFormat.Tiff => NSBitmapImageFileType.Tiff,
ImageFileFormat.Jpeg2000 => NSBitmapImageFileType.Jpeg2000,
_ => throw new InvalidOperationException("Unsupported image format") _ => throw new InvalidOperationException("Unsupported image format")
}; };
var targetFormat = LogicalPixelFormat; var targetFormat = LogicalPixelFormat;

View File

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

View File

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

View File

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

View File

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

View File

@ -82,9 +82,9 @@ public partial class FAutoSaveSettings : FormBase
private void btnChooseFolder_Click(object sender, EventArgs e) 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) 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) 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) 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); string subPath = placeholders.Substitute(settings.FilePath, true, i);
if (settings.PromptForFilePath) 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") // 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 // TODO: Cross-platform TIFF
public class SaveImagesOperation : OperationBase public class SaveImagesOperation : OperationBase
@ -47,9 +45,9 @@ public class SaveImagesOperation : OperationBase
fileName = Path.Combine(subFileName, "$(n).jpg"); fileName = Path.Combine(subFileName, "$(n).jpg");
subFileName = placeholders.Substitute(fileName, batch); 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)) if (File.Exists(subFileName))
{ {
@ -151,60 +149,22 @@ public class SaveImagesOperation : OperationBase
return true; 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); FileSystemHelper.EnsureParentDirExists(path);
if (Equals(format, ImageFormat.Tiff)) if (format == ImageFileFormat.Tiff)
{ {
using var renderedImage = image.Render(); using var renderedImage = image.Render();
_imageContext.TiffWriter.SaveTiff(new[] { renderedImage }, path, _imageContext.TiffWriter.SaveTiff(new[] { renderedImage }, path,
imageSettings.TiffCompression.ToTiffCompressionType(), CancelToken); 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 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(); using var bitmap = image.Render();
var fileFormat = format switch bitmap.Save(path, format, quality);
{
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;
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@ -33,6 +33,7 @@ public class DesktopController
private readonly ImageClipboard _imageClipboard; private readonly ImageClipboard _imageClipboard;
private readonly ImageListActions _imageListActions; private readonly ImageListActions _imageListActions;
private readonly IWinFormsExportHelper _exportHelper; private readonly IWinFormsExportHelper _exportHelper;
private readonly DialogHelper _dialogHelper;
private readonly DesktopImagesController _desktopImagesController; private readonly DesktopImagesController _desktopImagesController;
private readonly IDesktopScanController _desktopScanController; private readonly IDesktopScanController _desktopScanController;
private readonly DesktopFormProvider _desktopFormProvider; private readonly DesktopFormProvider _desktopFormProvider;
@ -46,6 +47,7 @@ public class DesktopController
StillImage stillImage, StillImage stillImage,
IUpdateChecker updateChecker, INotificationManager notify, ImageTransfer imageTransfer, IUpdateChecker updateChecker, INotificationManager notify, ImageTransfer imageTransfer,
ImageClipboard imageClipboard, ImageListActions imageListActions, IWinFormsExportHelper exportHelper, ImageClipboard imageClipboard, ImageListActions imageListActions, IWinFormsExportHelper exportHelper,
DialogHelper dialogHelper,
DesktopImagesController desktopImagesController, IDesktopScanController desktopScanController, DesktopImagesController desktopImagesController, IDesktopScanController desktopScanController,
DesktopFormProvider desktopFormProvider, IScannedImagePrinter scannedImagePrinter) DesktopFormProvider desktopFormProvider, IScannedImagePrinter scannedImagePrinter)
{ {
@ -63,6 +65,7 @@ public class DesktopController
_imageClipboard = imageClipboard; _imageClipboard = imageClipboard;
_imageListActions = imageListActions; _imageListActions = imageListActions;
_exportHelper = exportHelper; _exportHelper = exportHelper;
_dialogHelper = dialogHelper;
_desktopImagesController = desktopImagesController; _desktopImagesController = desktopImagesController;
_desktopScanController = desktopScanController; _desktopScanController = desktopScanController;
_desktopFormProvider = desktopFormProvider; _desktopFormProvider = desktopFormProvider;
@ -490,35 +493,9 @@ public class DesktopController
public void Import() public void Import()
{ {
// TODO: Merge this into exporthelper/dialoghelper? if (_dialogHelper.PromptToImport(out var fileNames))
var ofd = new OpenFileDialog
{ {
MultiSelect = true, ImportFiles(fileNames!);
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);
} }
} }
} }

View File

@ -2,9 +2,11 @@
public abstract class DialogHelper 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 class StubDialogHelper : DialogHelper
{ {
public override bool PromptToSavePdfOrImage(string defaultPath, out string savePath) public override bool PromptToSavePdfOrImage(string? defaultPath, out string? savePath)
{ {
savePath = null; savePath = null;
return false; return false;
} }
public override bool PromptToSavePdf(string defaultPath, out string savePath) public override bool PromptToSavePdf(string? defaultPath, out string? savePath)
{ {
savePath = null; savePath = null;
return false; return false;
} }
public override bool PromptToSaveImage(string defaultPath, out string savePath) public override bool PromptToSaveImage(string? defaultPath, out string? savePath)
{ {
savePath = null; savePath = null;
return false; return false;
} }
public override bool PromptToImport(out string[]? filePaths)
{
filePaths = null;
return false;
}
} }

View File

@ -1,37 +1,29 @@
using Eto.Forms; using Eto.Forms;
using NAPS2.EtoForms;
namespace NAPS2.WinForms; namespace NAPS2.WinForms;
public class WinFormsDialogHelper : DialogHelper public class WinFormsDialogHelper : DialogHelper
{ {
private readonly Naps2Config _config; private readonly Naps2Config _config;
private readonly FileFilters _fileFilters;
public WinFormsDialogHelper(Naps2Config config) public WinFormsDialogHelper(Naps2Config config, FileFilters fileFilters)
{ {
_config = config; _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 var sd = new SaveFileDialog
{ {
CheckFileExists = false, CheckFileExists = false,
// TODO // TODO
// AddExtension = true, // 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) FileName = Path.GetFileName(defaultPath)
}; };
_fileFilters.Set(sd, FileFilterGroup.Pdf | FileFilterGroup.Image);
SetDir(sd, defaultPath); SetDir(sd, defaultPath);
if (sd.ShowDialog(null) == DialogResult.Ok) if (sd.ShowDialog(null) == DialogResult.Ok)
{ {
@ -42,18 +34,15 @@ public class WinFormsDialogHelper : DialogHelper
return false; return false;
} }
public override bool PromptToSavePdf(string? defaultPath, out string savePath) public override bool PromptToSavePdf(string? defaultPath, out string? savePath)
{ {
var sd = new SaveFileDialog var sd = new SaveFileDialog
{ {
CheckFileExists = false, CheckFileExists = false,
// AddExtension = true, // AddExtension = true,
Filters =
{
new FileFilter(MiscResources.FileTypePdf, ".pdf"),
},
FileName = Path.GetFileName(defaultPath) FileName = Path.GetFileName(defaultPath)
}; };
_fileFilters.Set(sd, FileFilterGroup.Pdf);
SetDir(sd, defaultPath); SetDir(sd, defaultPath);
if (sd.ShowDialog(null) == DialogResult.Ok) if (sd.ShowDialog(null) == DialogResult.Ok)
{ {
@ -64,51 +53,17 @@ public class WinFormsDialogHelper : DialogHelper
return false; return false;
} }
public override bool PromptToSaveImage(string? defaultPath, out string savePath) public override bool PromptToSaveImage(string? defaultPath, out string? savePath)
{ {
var sd = new SaveFileDialog var sd = new SaveFileDialog
{ {
CheckFileExists = false, CheckFileExists = false,
// AddExtension = true, // 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) FileName = Path.GetFileName(defaultPath)
}; };
var lastExt = _config.Get(c => c.LastImageExt)?.ToLowerInvariant();
_fileFilters.Set(sd, FileFilterGroup.Image, lastExt ?? "jpg");
SetDir(sd, defaultPath); 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) if (sd.ShowDialog(null) == DialogResult.Ok)
{ {
savePath = sd.FileName; savePath = sd.FileName;
@ -138,4 +93,27 @@ public class WinFormsDialogHelper : DialogHelper
dialog.Directory = new Uri(Path.GetFullPath(path)); 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 else
{ {
if (!_dialogHelper.PromptToSavePdf(defaultFileName, out savePath)) if (!_dialogHelper.PromptToSavePdf(defaultFileName, out savePath!))
{ {
return false; return false;
} }
@ -79,7 +79,7 @@ public class WinFormsExportHelper : IWinFormsExportHelper
} }
else 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; return false;
} }

View File

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

View File

@ -11,46 +11,32 @@ namespace NAPS2.Sdk.Tests {
using System; using System;
/// <summary> [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
/// A strongly-typed resource class, for looking up localized strings, etc. [System.Diagnostics.DebuggerNonUserCodeAttribute()]
/// </summary> [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
// 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()]
internal class ImageResources { 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() { internal ImageResources() {
} }
/// <summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
/// Returns the cached ResourceManager instance used by this class. internal static System.Resources.ResourceManager ResourceManager {
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (object.Equals(null, resourceMan)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NAPS2.Sdk.Tests.ImageResources", typeof(ImageResources).Assembly); System.Resources.ResourceManager temp = new System.Resources.ResourceManager("NAPS2.Sdk.Tests.ImageResources", typeof(ImageResources).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;
} }
} }
/// <summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
/// Overrides the current thread's CurrentUICulture property for all internal static System.Globalization.CultureInfo Culture {
/// 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 {
get { get {
return resourceCulture; 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 { internal static byte[] dog {
get { get {
object obj = ResourceManager.GetObject("dog", resourceCulture); 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 { internal static byte[] dog_bw {
get { get {
object obj = ResourceManager.GetObject("dog_bw", resourceCulture); 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 { internal static byte[] dog_bw_24bit {
get { get {
object obj = ResourceManager.GetObject("dog_bw_24bit", resourceCulture); 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 { internal static byte[] dog_bw_jpg {
get { get {
object obj = ResourceManager.GetObject("dog_bw_jpg", resourceCulture); object obj = ResourceManager.GetObject("dog_bw_jpg", resourceCulture);
@ -199,19 +73,13 @@ namespace NAPS2.Sdk.Tests {
} }
} }
/// <summary> internal static byte[] dog_bw_bmp {
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_bw_p300 {
get { get {
object obj = ResourceManager.GetObject("dog_bw_p300", resourceCulture); object obj = ResourceManager.GetObject("dog_bw_bmp", resourceCulture);
return ((byte[])(obj)); return ((byte[])(obj));
} }
} }
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_bw_tiff { internal static byte[] dog_bw_tiff {
get { get {
object obj = ResourceManager.GetObject("dog_bw_tiff", resourceCulture); object obj = ResourceManager.GetObject("dog_bw_tiff", resourceCulture);
@ -219,9 +87,34 @@ namespace NAPS2.Sdk.Tests {
} }
} }
/// <summary> internal static byte[] dog_bw_p300 {
/// Looks up a localized resource of type System.Byte[]. get {
/// </summary> 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 { internal static byte[] dog_c_5_10_15_20 {
get { get {
object obj = ResourceManager.GetObject("dog_c_5_10_15_20", resourceCulture); 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 { internal static byte[] dog_c_n300 {
get { get {
object obj = ResourceManager.GetObject("dog_c_n300", resourceCulture); 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 { internal static byte[] dog_c_p300 {
get { get {
object obj = ResourceManager.GetObject("dog_c_p300", resourceCulture); 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 { internal static byte[] dog_h_n300 {
get { get {
object obj = ResourceManager.GetObject("dog_h_n300", resourceCulture); 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 { internal static byte[] dog_h_p300 {
get { get {
object obj = ResourceManager.GetObject("dog_h_p300", resourceCulture); 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 { internal static byte[] dog_r_180 {
get { get {
object obj = ResourceManager.GetObject("dog_r_180", resourceCulture); 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 { internal static byte[] dog_r_n45 {
get { get {
object obj = ResourceManager.GetObject("dog_r_n45", resourceCulture); 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 { internal static byte[] dog_r_p46 {
get { get {
object obj = ResourceManager.GetObject("dog_r_p46", resourceCulture); 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 { internal static byte[] dog_r_p90 {
get { get {
object obj = ResourceManager.GetObject("dog_r_p90", resourceCulture); 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 { internal static byte[] dog_sc_50pct {
get { get {
object obj = ResourceManager.GetObject("dog_sc_50pct", resourceCulture); 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 { internal static byte[] dog_sh_n1000 {
get { get {
object obj = ResourceManager.GetObject("dog_sh_n1000", resourceCulture); 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 { internal static byte[] dog_sh_p1000 {
get { get {
object obj = ResourceManager.GetObject("dog_sh_p1000", resourceCulture); object obj = ResourceManager.GetObject("dog_sh_p1000", resourceCulture);
@ -469,9 +199,20 @@ namespace NAPS2.Sdk.Tests {
} }
} }
/// <summary> internal static byte[] dog_s_n300 {
/// Looks up a localized resource of type System.Byte[]. get {
/// </summary> 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 { internal static byte[] dog_thumb_256 {
get { get {
object obj = ResourceManager.GetObject("dog_thumb_256", resourceCulture); object obj = ResourceManager.GetObject("dog_thumb_256", resourceCulture);
@ -479,49 +220,13 @@ namespace NAPS2.Sdk.Tests {
} }
} }
/// <summary> internal static byte[] deskewed {
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] dog_tiff {
get { get {
object obj = ResourceManager.GetObject("dog_tiff", resourceCulture); object obj = ResourceManager.GetObject("deskewed", resourceCulture);
return ((byte[])(obj)); 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 { internal static byte[] skewed {
get { get {
object obj = ResourceManager.GetObject("skewed", resourceCulture); 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 { internal static byte[] skewed_bw {
get { get {
object obj = ResourceManager.GetObject("skewed_bw", resourceCulture); 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 { internal static byte[] stock_cat {
get { get {
object obj = ResourceManager.GetObject("stock_cat", resourceCulture); object obj = ResourceManager.GetObject("stock_cat", resourceCulture);
return ((byte[])(obj)); 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"> <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> <value>Resources\dog_mask.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data> </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"> <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> <value>Resources\dog.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data> </data>

View File

@ -172,6 +172,11 @@ public class LoadSaveTests : ContextualTests
new[] { "dog_bw" }, new[] { ImagePixelFormat.Gray8 }, false new[] { "dog_bw" }, new[] { ImagePixelFormat.Gray8 }, false
}, },
new object[] new object[]
{
ImageFileFormat.Jpeg2000, ".jp2", "dog_jp2",
new[] { "dog" }, new[] { ImagePixelFormat.RGB24 }, false
},
new object[]
{ {
ImageFileFormat.Bmp, ".bmp", "dog_bmp", ImageFileFormat.Bmp, ".bmp", "dog_bmp",
new[] { "dog" }, new[] { ImagePixelFormat.RGB24 }, true 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; } public ImageContext ImageContext { get; }
// TODO: Consider having two copies of the image on disk - one before transforms, one after.
public IImageStorage Storage { get; } public IImageStorage Storage { get; }
public ImageMetadata Metadata { get; } public ImageMetadata Metadata { get; }