From c0990c1ba3347f2f2992efe81c443de4535a1348 Mon Sep 17 00:00:00 2001 From: Georgy Perevozchikov Date: Tue, 3 Apr 2018 01:29:03 +0300 Subject: [PATCH] add GUI-scan-print - Added a Graphic User Interphase. - Python script moved to \PythonModule\ - setup.py added file added to compile for Win32 - added print, load, save and scan functions. --- .gitattributes | 63 ++++ .gitignore | 332 +++++++++++++----- NoteShrink.sln | 25 ++ NoteShrink/App.config | 6 + NoteShrink/App.xaml | 9 + NoteShrink/App.xaml.cs | 17 + NoteShrink/MainWindow.xaml | 72 ++++ NoteShrink/MainWindow.xaml.cs | 57 +++ NoteShrink/Models/ConvertImageService.cs | 61 ++++ NoteShrink/Models/FileSystemService.cs | 57 +++ NoteShrink/Models/PrintService.cs | 35 ++ NoteShrink/Models/ScannerException.cs | 24 ++ NoteShrink/Models/ScannerImageConverter.cs | 78 ++++ NoteShrink/Models/ScannerNotFoundException.cs | 16 + NoteShrink/Models/ScannerService.cs | 45 +++ NoteShrink/NoteShrink.csproj | 120 +++++++ NoteShrink/Properties/AssemblyInfo.cs | 55 +++ NoteShrink/Properties/Resources.Designer.cs | 71 ++++ NoteShrink/Properties/Resources.resx | 117 ++++++ NoteShrink/Properties/Settings.Designer.cs | 30 ++ NoteShrink/Properties/Settings.settings | 7 + NoteShrink/ViewModels/MainViewModel.cs | 239 +++++++++++++ NoteShrink/ViewModels/Observable.cs | 20 ++ NoteShrink/ViewModels/RelayCommand.cs | 40 +++ noteshrink.py => PythonModule/noteshrink.py | 0 .../requirements.txt | 0 PythonModule/setup.py | 11 + 27 files changed, 1521 insertions(+), 86 deletions(-) create mode 100644 .gitattributes create mode 100644 NoteShrink.sln create mode 100644 NoteShrink/App.config create mode 100644 NoteShrink/App.xaml create mode 100644 NoteShrink/App.xaml.cs create mode 100644 NoteShrink/MainWindow.xaml create mode 100644 NoteShrink/MainWindow.xaml.cs create mode 100644 NoteShrink/Models/ConvertImageService.cs create mode 100644 NoteShrink/Models/FileSystemService.cs create mode 100644 NoteShrink/Models/PrintService.cs create mode 100644 NoteShrink/Models/ScannerException.cs create mode 100644 NoteShrink/Models/ScannerImageConverter.cs create mode 100644 NoteShrink/Models/ScannerNotFoundException.cs create mode 100644 NoteShrink/Models/ScannerService.cs create mode 100644 NoteShrink/NoteShrink.csproj create mode 100644 NoteShrink/Properties/AssemblyInfo.cs create mode 100644 NoteShrink/Properties/Resources.Designer.cs create mode 100644 NoteShrink/Properties/Resources.resx create mode 100644 NoteShrink/Properties/Settings.Designer.cs create mode 100644 NoteShrink/Properties/Settings.settings create mode 100644 NoteShrink/ViewModels/MainViewModel.cs create mode 100644 NoteShrink/ViewModels/Observable.cs create mode 100644 NoteShrink/ViewModels/RelayCommand.cs rename noteshrink.py => PythonModule/noteshrink.py (100%) rename requirements.txt => PythonModule/requirements.txt (100%) create mode 100644 PythonModule/setup.py diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore index 7bbc71c..3c4efe2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,101 +1,261 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -env/ -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -*.egg-info/ -.installed.cfg -*.egg - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -.hypothesis/ - -# Translations -*.mo -*.pot - -# Django stuff: +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj *.log -local_settings.py +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* -# Flask stuff: -instance/ -.webassets-cache +# DotCover is a Code Coverage Tool +*.dotCover -# Scrapy stuff: -.scrapy +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* -# Sphinx documentation -docs/_build/ +# MightyMoose +*.mm.* +AutoTest.Net/ -# PyBuilder -target/ +# Web workbench (sass) +.sass-cache/ -# Jupyter Notebook -.ipynb_checkpoints +# Installshield output folder +[Ee]xpress/ -# pyenv -.python-version +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html -# celery beat schedule file -celerybeat-schedule +# Click-Once directory +publish/ -# SageMath parsed files -*.sage.py +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj -# dotenv -.env +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ -# virtualenv -.venv -venv/ -ENV/ +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets -# Spyder project settings -.spyderproject -.spyproject +# Microsoft Azure Build Output +csx/ +*.build.csdef -# Rope project settings -.ropeproject +# Microsoft Azure Emulator +ecf/ +rcf/ -# mkdocs documentation -/site +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt -# mypy -.mypy_cache/ +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc \ No newline at end of file diff --git a/NoteShrink.sln b/NoteShrink.sln new file mode 100644 index 0000000..12963c9 --- /dev/null +++ b/NoteShrink.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2027 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NoteShrink", "NoteShrink\NoteShrink.csproj", "{C0942310-7D37-4BD0-B475-096C34B21E9C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C0942310-7D37-4BD0-B475-096C34B21E9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C0942310-7D37-4BD0-B475-096C34B21E9C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C0942310-7D37-4BD0-B475-096C34B21E9C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C0942310-7D37-4BD0-B475-096C34B21E9C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {492D0835-F99A-429E-897B-C7E2BE2CF784} + EndGlobalSection +EndGlobal diff --git a/NoteShrink/App.config b/NoteShrink/App.config new file mode 100644 index 0000000..8e15646 --- /dev/null +++ b/NoteShrink/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/NoteShrink/App.xaml b/NoteShrink/App.xaml new file mode 100644 index 0000000..04a10c1 --- /dev/null +++ b/NoteShrink/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/NoteShrink/App.xaml.cs b/NoteShrink/App.xaml.cs new file mode 100644 index 0000000..9c061ed --- /dev/null +++ b/NoteShrink/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace NoteShrink +{ + /// + /// Логика взаимодействия для App.xaml + /// + public partial class App : Application + { + } +} diff --git a/NoteShrink/MainWindow.xaml b/NoteShrink/MainWindow.xaml new file mode 100644 index 0000000..234cf25 --- /dev/null +++ b/NoteShrink/MainWindow.xaml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/NoteShrink/MainWindow.xaml.cs b/NoteShrink/MainWindow.xaml.cs new file mode 100644 index 0000000..ba6e2bd --- /dev/null +++ b/NoteShrink/MainWindow.xaml.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace NoteShrink +{ + /// + /// Логика взаимодействия для MainWindow.xaml + /// + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + } + + private void mDocumentIncrease_Click(object sender, RoutedEventArgs e) + { + ScannerImage.Width += ScannerImage.Width * 0.25; + ScannerImage.Height += ScannerImage.Height * 0.25; + } + + private void mDocumentShrink_Click(object sender, RoutedEventArgs e) + { + ScannerImage.Width -= ScannerImage.Width * 0.25; + ScannerImage.Height -= ScannerImage.Height * 0.25; + } + + private void W_Main_SizeChanged(object sender, SizeChangedEventArgs e) + { + ScannerImage.Width = W_Main.Width - 50; + ScannerImage.Height = W_Main.Height - 110; + } + + private void mFileExit_Click(object sender, RoutedEventArgs e) + { + W_Main.Close(); + } + + private void mHelpAbout_Click(object sender, RoutedEventArgs e) + { + string msg = "NoteShrink v0.5.0.\nCreated by Georgy Perevozchikov (gosha20777@live.ru).\n\nNoteShrink - улучшает ваши сканы и уменьшает их размер.\n\nИсходные коды проекта доступны по ссылке:\nhttps://github.com/gosha20777/NoteShrink"; + MessageBox.Show(msg, "NoteShrink", MessageBoxButton.OK, MessageBoxImage.Information); + } + } +} diff --git a/NoteShrink/Models/ConvertImageService.cs b/NoteShrink/Models/ConvertImageService.cs new file mode 100644 index 0000000..6924006 --- /dev/null +++ b/NoteShrink/Models/ConvertImageService.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; + +namespace NoteShrink.Models +{ + class ConvertImageService + { + private readonly string _inputName = @"conv\input.png"; + private readonly string _outputName = @"page0000.png"; + private readonly string _processName = @"conv\noteshrink.exe"; + + public async Task Convert(BitmapSource bitmapSource) + { + using (var fileStream = new FileStream(_inputName, FileMode.Create)) + { + BitmapEncoder encoder = new PngBitmapEncoder(); + encoder.Frames.Add(BitmapFrame.Create(bitmapSource)); + encoder.Save(fileStream); + } + + var t = await Task.Run(() => RunProcess()); + + File.Delete(_inputName); + BitmapFrame img; + // load the file to a WPF type + using (FileStream stream = File.OpenRead(_outputName)) + { + img = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); + stream.Close(); + } + File.Delete(_outputName); + return img; + } + + public bool RunProcess() + { + using (Process process = new Process()) + { + process.StartInfo = new ProcessStartInfo + { + FileName = _processName, + Arguments = _inputName, + CreateNoWindow = true, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardInput = true + }; + bool sucsess = process.Start(); + process.WaitForExit(); + + return sucsess; + } + } + } +} diff --git a/NoteShrink/Models/FileSystemService.cs b/NoteShrink/Models/FileSystemService.cs new file mode 100644 index 0000000..4b76ae3 --- /dev/null +++ b/NoteShrink/Models/FileSystemService.cs @@ -0,0 +1,57 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; + +namespace NoteShrink.Models +{ + class FileSystemService + { + public BitmapSource LoadFile() + { + OpenFileDialog openDig = new OpenFileDialog + { + Title = "Выбирете файл...", + Filter = "Картинки (*.png; *.jpg;)|*.png;*.jpg;", + Multiselect = false + }; + if (openDig.ShowDialog() == true && openDig.CheckFileExists) + { + BitmapFrame img; + // load the file to a WPF type + using (FileStream stream = File.OpenRead(openDig.FileName)) + { + img = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); + stream.Close(); + } + + return img; + } + else + return null; + } + + public void SaveFile(BitmapSource bitmapSource) + { + SaveFileDialog saveDig = new SaveFileDialog + { + FileName = "Output", + Title = "Сохранить...", + Filter = "Картинки (*.png)|*.png" + }; + if (saveDig.ShowDialog() == true && saveDig.CheckPathExists) + { + using (var fileStream = new FileStream(saveDig.FileName, FileMode.Create)) + { + BitmapEncoder encoder = new PngBitmapEncoder(); + encoder.Frames.Add(BitmapFrame.Create(bitmapSource)); + encoder.Save(fileStream); + } + } + } + } +} diff --git a/NoteShrink/Models/PrintService.cs b/NoteShrink/Models/PrintService.cs new file mode 100644 index 0000000..e8ca4f2 --- /dev/null +++ b/NoteShrink/Models/PrintService.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media.Imaging; + +namespace NoteShrink.Models +{ + class PrintService + { + public void Print(BitmapSource bitmapSource) + { + PrintDialog printDialog = new PrintDialog(); + if (printDialog.ShowDialog() == true) + { + var capability = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket); + var pageArea = capability.PageImageableArea; + Image img = new Image + { + Source = bitmapSource + }; + Size size = new Size { Width = pageArea.ExtentWidth, Height = pageArea.ExtentHeight }; + img.Measure(size); + img.Arrange(new Rect { Width = pageArea.ExtentWidth, Height = pageArea.ExtentHeight }); + + printDialog.PrintVisual(img, "Печать"); + } + } + + + } +} diff --git a/NoteShrink/Models/ScannerException.cs b/NoteShrink/Models/ScannerException.cs new file mode 100644 index 0000000..de6033a --- /dev/null +++ b/NoteShrink/Models/ScannerException.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NoteShrink.Models +{ + class ScannerException : ApplicationException + { + public ScannerException() + : base() + { } + + public ScannerException(string message) + : base(message) + { } + + public ScannerException(string message, Exception innerException) + : base(message, innerException) + { } + + } +} diff --git a/NoteShrink/Models/ScannerImageConverter.cs b/NoteShrink/Models/ScannerImageConverter.cs new file mode 100644 index 0000000..0b09581 --- /dev/null +++ b/NoteShrink/Models/ScannerImageConverter.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; +using WIA; + +namespace NoteShrink.Models +{ + public class ScannerImageConverter + { + // this could be in the ScannerService, but then that service + // takes a dependency on WPF, which I didn't want. Better to have + // the dependencies wrapped into this service instead. Requires + // FileIOPermission + public BitmapSource ConvertScannedImage(ImageFile imageFile) + { + if (imageFile == null) + return null; + + // save the image out to a temp file + string fileName = Path.GetTempFileName(); + + // this is pretty hokey, but since SaveFile won't overwrite, we + // need to do something to both guarantee a unique name and + // also allow SaveFile to write the file + File.Delete(fileName); + + // now save using the same filename + imageFile.SaveFile(fileName); + + BitmapFrame img; + + // load the file back in to a WPF type, this is just + // to get around size issues with large scans + using (FileStream stream = File.OpenRead(fileName)) + { + img = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); + + stream.Close(); + } + + // clean up + File.Delete(fileName); + + return img; + } + + + // this will choke on large images (like 1200dpi scans) + // for that reason, you may want to do the conversion by + // saving the ImageFile to a temp file and then loading it + // in to convert it, as we do in the revised method above + public BitmapSource InMemoryConvertScannedImage(ImageFile imageFile) + { + if (imageFile == null) + return null; + + Vector vector = imageFile.FileData; + + if (vector != null) + { + byte[] bytes = vector.get_BinaryData() as byte[]; + + if (bytes != null) + { + var ms = new MemoryStream(bytes); + return BitmapFrame.Create(ms); + } + } + + return null; + } + + } +} diff --git a/NoteShrink/Models/ScannerNotFoundException.cs b/NoteShrink/Models/ScannerNotFoundException.cs new file mode 100644 index 0000000..8085a6b --- /dev/null +++ b/NoteShrink/Models/ScannerNotFoundException.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NoteShrink.Models +{ + class ScannerNotFoundException : ScannerException + { + public ScannerNotFoundException() + : base("Ошибка получения списка сканеров! Проверьте, включен ли ваш сканер или многофункциональный принтер.") + { + } + } +} diff --git a/NoteShrink/Models/ScannerService.cs b/NoteShrink/Models/ScannerService.cs new file mode 100644 index 0000000..dae8615 --- /dev/null +++ b/NoteShrink/Models/ScannerService.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using WIA; + +namespace NoteShrink.Models +{ + class ScannerService + { + public ImageFile Scan() + { + ImageFile image; + + try + { + CommonDialog dialog = new CommonDialog(); + + image = dialog.ShowAcquireImage( + WiaDeviceType.ScannerDeviceType, + WiaImageIntent.ColorIntent, + WiaImageBias.MaximizeQuality, + "{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}", //FormatID.wiaFormatJPEG + false, + true, + false); + + return image; + } + catch (COMException ex) + { + if (ex.ErrorCode == -2145320939) + { + throw new ScannerNotFoundException(); + } + else + { + throw new ScannerException("COM Exception", ex); + } + } + } + } +} diff --git a/NoteShrink/NoteShrink.csproj b/NoteShrink/NoteShrink.csproj new file mode 100644 index 0000000..57a2dee --- /dev/null +++ b/NoteShrink/NoteShrink.csproj @@ -0,0 +1,120 @@ + + + + + Debug + AnyCPU + {C0942310-7D37-4BD0-B475-096C34B21E9C} + WinExe + NoteShrink + NoteShrink + v4.5 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + + + + + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + MainWindow.xaml + Code + + + + + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + {94A0E92D-43C0-494E-AC29-FD45948A5221} + 1 + 0 + 0 + tlbimp + False + True + + + + + \ No newline at end of file diff --git a/NoteShrink/Properties/AssemblyInfo.cs b/NoteShrink/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c87fb4b --- /dev/null +++ b/NoteShrink/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// Общие сведения об этой сборке предоставляются следующим набором +// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, +// связанные со сборкой. +[assembly: AssemblyTitle("NoteShrink")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("NoteShrink")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми +// для компонентов COM. Если необходимо обратиться к типу в этой сборке через +// COM, задайте атрибуту ComVisible значение TRUE для этого типа. +[assembly: ComVisible(false)] + +//Чтобы начать создание локализуемых приложений, задайте +//CultureYouAreCodingWith в файле .csproj +//внутри . Например, если используется английский США +//в своих исходных файлах установите в en-US. Затем отмените преобразование в комментарий +//атрибута NeutralResourceLanguage ниже. Обновите "en-US" в +//строка внизу для обеспечения соответствия настройки UICulture в файле проекта. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //где расположены словари ресурсов по конкретным тематикам + //(используется, если ресурс не найден на странице, + // или в словарях ресурсов приложения) + ResourceDictionaryLocation.SourceAssembly //где расположен словарь универсальных ресурсов + //(используется, если ресурс не найден на странице, + // в приложении или в каких-либо словарях ресурсов для конкретной темы) +)] + + +// Сведения о версии сборки состоят из следующих четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер сборки +// Редакция +// +// Можно задать все значения или принять номер сборки и номер редакции по умолчанию. +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/NoteShrink/Properties/Resources.Designer.cs b/NoteShrink/Properties/Resources.Designer.cs new file mode 100644 index 0000000..3049962 --- /dev/null +++ b/NoteShrink/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// Этот код создан программным средством. +// Версия среды выполнения: 4.0.30319.42000 +// +// Изменения в этом файле могут привести к неправильному поведению и будут утрачены, если +// код создан повторно. +// +//------------------------------------------------------------------------------ + +namespace NoteShrink.Properties +{ + + + /// + /// Класс ресурсов со строгим типом для поиска локализованных строк и пр. + /// + // Этот класс был автоматически создан при помощи StronglyTypedResourceBuilder + // класс с помощью таких средств, как ResGen или Visual Studio. + // Для добавления или удаления члена измените файл .ResX, а затем перезапустите ResGen + // с параметром /str или заново постройте свой VS-проект. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Возврат кэшированного экземпляра ResourceManager, используемого этим классом. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NoteShrink.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Переопределяет свойство CurrentUICulture текущего потока для всех + /// подстановки ресурсов с помощью этого класса ресурсов со строгим типом. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/NoteShrink/Properties/Resources.resx b/NoteShrink/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/NoteShrink/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/NoteShrink/Properties/Settings.Designer.cs b/NoteShrink/Properties/Settings.Designer.cs new file mode 100644 index 0000000..d59b3cc --- /dev/null +++ b/NoteShrink/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace NoteShrink.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/NoteShrink/Properties/Settings.settings b/NoteShrink/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/NoteShrink/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/NoteShrink/ViewModels/MainViewModel.cs b/NoteShrink/ViewModels/MainViewModel.cs new file mode 100644 index 0000000..8b57eb6 --- /dev/null +++ b/NoteShrink/ViewModels/MainViewModel.cs @@ -0,0 +1,239 @@ +using NoteShrink.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using WIA; + +namespace NoteShrink.ViewModels +{ + class MainViewModel : Observable + { + private BitmapSource _image; + private ImageBrush _imageBrush; + private double _width = 800; + private double _height = 600; + private string _statusText = "Готово."; + + public double Width + { + get { return _width; } + set { _width = value; NotifyPropertyChanged("Width"); } + } + public double Height + { + get { return _height; } + set { _height = value; NotifyPropertyChanged("Height"); } + } + public ImageBrush ImageBrush + { + get { return _imageBrush; } + set { _imageBrush = value; NotifyPropertyChanged("ImageBrush"); } + } + public string StatusText + { + get { return _statusText; } + set { _statusText = value; NotifyPropertyChanged("StatusText"); } + } + #region Scan + // Command for scanning + private RelayCommand _scanCommand; + public ICommand ScanCommand + { + get + { + + if (_scanCommand == null) + { + _scanCommand = new RelayCommand(param => this.Scan(), param => this.CanScan); + } + + return _scanCommand; + } + } + + // implemented for the command pattern completeness. We don't currently + // have any situations where we'd disable the ability to scan + public bool CanScan + { + get { return true; } + } + + // method to do the actual scanning + public void Scan() + { + StatusText = "Сканирование..."; + var scanner = new ScannerService(); + + try + { + ImageFile file = scanner.Scan(); + + if (file != null) + { + var converter = new ScannerImageConverter(); + + _image = converter.ConvertScannedImage(file); + } + else + { + _image = null; + } + ImageBrush = new ImageBrush(_image) { Stretch = Stretch.Uniform }; + } + catch (ScannerException ex) + { + // yeah, I know. Showing UI from the VM. Shoot me now. + MessageBox.Show(ex.Message, "Не удалось выполнить сканирование изображения", MessageBoxButton.OK, MessageBoxImage.Warning); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error); + } + StatusText = "Готово."; + } + #endregion + + #region LoadFile + private RelayCommand _openFieCommand; + public ICommand OpenFileCommand + { + get + { + if (_openFieCommand == null) + { + _openFieCommand = new RelayCommand(param => this.OpenFile(), param => true); + } + return _openFieCommand; + } + } + + private void OpenFile() + { + StatusText = "Загрузка файла..."; + var fileSystem = new FileSystemService(); + + try + { + _image = fileSystem.LoadFile(); + ImageBrush = new ImageBrush(_image) { Stretch = Stretch.Uniform }; + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error); + } + StatusText = "Готово."; + } + #endregion + + #region SaveFile + private RelayCommand _saveFieCommand; + public ICommand SaveFileCommand + { + get + { + if (_saveFieCommand == null) + { + _saveFieCommand = new RelayCommand(param => this.SaveFile(), param => this.CanSave); + } + + return _saveFieCommand; + } + } + + public bool CanSave { get { return _image != null; } } + + private void SaveFile() + { + StatusText = "Сохранение файла..."; + var fileSystem = new FileSystemService(); + + try + { + fileSystem.SaveFile(_image); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error); + } + StatusText = "Готово."; + } + #endregion + + #region ConvertImage + private RelayCommand _convertImageCommand; + public ICommand ConvertImageCommand + { + get + { + if (_convertImageCommand == null) + { + _convertImageCommand = new RelayCommand(param => this.ConvertAsync(), param => this.CanConvert); + } + + return _convertImageCommand; + } + } + + public bool CanConvert { get { return _image != null; } } + + private async void ConvertAsync() + { + StatusText = "Конвертация..."; + var convertImage = new ConvertImageService(); + + try + { + _image = await convertImage.Convert(_image); + ImageBrush = new ImageBrush(_image) { Stretch = Stretch.Uniform }; + + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error); + } + StatusText = "Готово."; + } + #endregion + + #region PrintFile + private RelayCommand _printCommand; + public ICommand PrintCommand + { + get + { + + if (_printCommand == null) + { + _printCommand = new RelayCommand(param => this.Print(), param => this.CanPrint); + } + + return _printCommand; + } + } + + public bool CanPrint { get { return _image != null; } } + + private void Print() + { + StatusText = "Печать..."; + var printService = new PrintService(); + + try + { + printService.Print(_image); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error); + } + StatusText = "Готово."; + } + #endregion + } +} diff --git a/NoteShrink/ViewModels/Observable.cs b/NoteShrink/ViewModels/Observable.cs new file mode 100644 index 0000000..9630c0f --- /dev/null +++ b/NoteShrink/ViewModels/Observable.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NoteShrink.ViewModels +{ + public abstract class Observable : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + protected void NotifyPropertyChanged(string propertyName) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + } +} diff --git a/NoteShrink/ViewModels/RelayCommand.cs b/NoteShrink/ViewModels/RelayCommand.cs new file mode 100644 index 0000000..9ab66c8 --- /dev/null +++ b/NoteShrink/ViewModels/RelayCommand.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace NoteShrink.ViewModels +{ + public class RelayCommand : ICommand + { + #region Fields + readonly Action _execute; + readonly Predicate _canExecute; + #endregion // Fields + #region Constructors + public RelayCommand(Action execute) : this(execute, null) { } + public RelayCommand(Action execute, Predicate canExecute) + { + if (execute == null) + throw new ArgumentNullException("execute"); + _execute = execute; _canExecute = canExecute; + } + #endregion // Constructors + #region ICommand Members + [DebuggerStepThrough] + public bool CanExecute(object parameter) + { + return _canExecute == null ? true : _canExecute(parameter); + } + public event EventHandler CanExecuteChanged + { + add { CommandManager.RequerySuggested += value; } + remove { CommandManager.RequerySuggested -= value; } + } + public void Execute(object parameter) { _execute(parameter); } + #endregion // ICommand Members + } +} diff --git a/noteshrink.py b/PythonModule/noteshrink.py similarity index 100% rename from noteshrink.py rename to PythonModule/noteshrink.py diff --git a/requirements.txt b/PythonModule/requirements.txt similarity index 100% rename from requirements.txt rename to PythonModule/requirements.txt diff --git a/PythonModule/setup.py b/PythonModule/setup.py new file mode 100644 index 0000000..b37a80e --- /dev/null +++ b/PythonModule/setup.py @@ -0,0 +1,11 @@ +from cx_Freeze import setup, Executable + +additional_mods = ['numpy.core._methods', 'numpy.lib.format', 'scipy.sparse.csgraph._validation', 'scipy.spatial.ckdtree'] + +setup( + name = "noteshrink", + version = "0.1", + description = "noteshrink", + options = {'build_exe': {'includes': additional_mods}}, + executables = [Executable("noteshrink.py")] +) \ No newline at end of file