Merge ImageResizer into master (#1469)

* Import Image Resizer for Windows

* getting code analysis and stylecop hooked in

* upgrading to 4.7.2

* adding copyright

* getting stuff to work

headers and trailing commas

adding braces

updated encoder

* Revert "getting stuff to work"

This reverts commit 5310866120.

* update to .net 4.7.2

* access modifier

* zero errors

* Fixed unit tests not running issue

* Fixed ImageResizer.Test stylecop warning

* Formatted ShellExtensions project with clang-format

* Fixed annotation warnings

* Suppressed 6031 and 26812 warnings for specific lines

* Shifting ImageResizer projects to PowerToys solution (#1054)

* Shifted ImageResizer projects to PowerToys solution: Builds, all tests pass, ImageResizer C# project works independently

* Deleted extra files

* Deleted nuget config file and fixed code analysis paths

* Convert ImageResizer to a PowerToy (#1073)

* Updated vcxproj file with common project references and cpp version flags

* Added module template code to dllmain and updated headers for successful build

* Removed unnecessary include

* Added dll to runner and add fixes to show up in PT Settings

* Added settings file

* Added support for enabling/disabling based on PowerRename codebase

* Fixed missing braces

* Fixed call_custom_action

* Add ImageResizer to msi installer (dev/imageResizer) (#1094)

* Updated vcxproj file with common project references and cpp version flags

* Added module template code to dllmain and updated headers for successful build

* Removed unnecessary include

* Added dll to runner and add fixes to show up in PT Settings

* Added settings file

* Added support for enabling/disabling based on PowerRename codebase

* Fixed solution file configurations

* Removed Any CPU from ImageResizer csprojs

* Renamed registry writing and removed build time registry addition

* Added ImageResizer installation details to msi

* Fixed comment on conditions to close explorer.exe

* Sync dev/imageResizer with master (#1105)

* tweaking language

* adjusting elevated permission verbiage to match Windows

* npm audit fix to update stuff

* slight bump for fabric ui

* Remove unwanted files (#1037)

Add temp build files to gitignore

* Ensure previous search and replace texts are evaluated and updated in the UI at startup (#1043)

Ensure stored settings get evaluated after initial enumeration

There was a bug where the list view was not getting updated with the results of the search and replace on launch when we are using a stored search or replace text from a previous session.

* adding fancy zone opacity setting, enhancement #631 (#1008)

* adding fancy zone opacity setting, enhancement #631

* applying zone opacity setting to all zones during zone selection

* changing opacity setting to percentage

* runner: show message box when restarting with different elevation fails (#1061)

Also make the message box appear on top of the settings window.

* Fix misaligned display of zones in layout priview and grid editor (#1010)

Fix misaligned display of zones in layout preview and grid editor

* MSIX: Extract MSIX building functionality from msix_reinstall.ps1 to a separate script (#1068)

* MSIX: label PowerToys as Preview (#1090)

* MSIX: Code sign msixbundle (#1093)

* Update to MSIX README.md (#1095)

* Update README.md

few adjustments

* Update README.md

* Update README.md

* adding in privacy statement, removing About in dialog (#1087)

* adding in privacy statement, removing About in dialog

* added Preview

* Revert "Fix misaligned display of zones in layout priview and grid editor (#1010)" (#1097)

This reverts commit d03690cffd.

* Fix reversed order of zones in layout (#1071)

* Shifted three functions to common (#1101)

Co-authored-by: Clint Rutkas <clint@rutkas.com>
Co-authored-by: Enrico Giordani <enricogior@users.noreply.github.com>
Co-authored-by: Chris Davis <chrisdavis@outlook.com>
Co-authored-by: Yosef Durr <yodurr@microsoft.com>
Co-authored-by: Bartosz Sosnowski <bzoz@users.noreply.github.com>
Co-authored-by: vldmr11080 <57061786+vldmr11080@users.noreply.github.com>
Co-authored-by: yuyoyuppe <yuyoyuppe@users.noreply.github.com>

* Revert "Sync dev/imageResizer with master (#1105)"

This reverts commit db7f15541f.

* Added icon to Resize pictures context menu entry (dev/imageResizer) (#1113)

* Updated vcxproj file with common project references and cpp version flags

* Added module template code to dllmain and updated headers for successful build

* Removed unnecessary include

* Added dll to runner and add fixes to show up in PT Settings

* Added settings file

* Added support for enabling/disabling based on PowerRename codebase

* Fixed solution file configurations

* Removed Any CPU from ImageResizer csprojs

* Renamed registry writing and removed build time registry addition

* Added ImageResizer installation details to msi

* Shifted to MII, TODO: Fix position

* Incorporated ImageResizer Icon in context menu entry

* Fixed typo

* Merged with dev/imageResizer

* Renamed Advanced Options to Settings and removed About tab (dev/imageResizer) (#1123)

* Removed about tab, renamed advanced opt to settings, changed assembly info

* Restored Resource designer file

* Reverted changes on AssemblyInfo

* MSI: Fix ImageResizer menu item position (dev/imageResizer) (#1114)

* Updated vcxproj file with common project references and cpp version flags

* Added module template code to dllmain and updated headers for successful build

* Removed unnecessary include

* Added dll to runner and add fixes to show up in PT Settings

* Added settings file

* Added support for enabling/disabling based on PowerRename codebase

* Fixed solution file configurations

* Removed Any CPU from ImageResizer csprojs

* Renamed registry writing and removed build time registry addition

* Added ImageResizer installation details to msi

* Shifted to MII, TODO: Fix position

* Incorporated ImageResizer Icon in context menu entry

* Changed registry entries to SystemFileAssociations and added index changes in InsertMenuItem

* Fixed extra newline

* Fixed merge conflict

* Refactor ImageResizer code base naming to match PowerRename (#1121)

* Created empty README file

* Renamed dll project

* Removed ShellExtensions references in src

* Fixed ImageResizerUI assembly name and added changes to MSI

* added the helper functions

* localized dllmain powerrename

* localized powerRenameExt

* localized the settings file

* built the proj

* Modified resourceIDs for strings in the table

* added common as a reference project

* Removed get_res_string_wchar and used the get_resource_string() function instead which returns a wstring typecast into wchar*

* Added new lines to the end of the file

* Removed string resources from the settings.cpp file

* rebuilt project PowerRename

* moved app name to constructor to init only once

* updated formatting of common.cpp

* reverting formatting of files

* Removed some IDs from resource file. Changed SHIFT to Shift

* Localizing C# Project of FancyZones (FancyZonesEditor) (#199) (#1122)

* removed hardcoded strings from CanvasEditorWindow.xaml

* removed hardcoded strings from GridEditorWindow.xaml

* loc

* Localized MainWindow

* reverting MainWindow.xaml as it is not rendering the window as expected

* Changed the resource settings from internal to public

* the culture is set based on the culture of the system UI set in the system settings

* Removed the french resource files used for testing

* Localized canvasWindow and mainwindow

* Removed setting the UI culture explicitly as it would be implicitly set to the culture of system UI

* Removed redundant header file

* Localize the Shortcut guide PowerToy (#199) (#1126)

* Localized shortcut_guide.cpp

* localized overlay_window.cpp

* formatting changes

* Localize overlay window

* removed the README link from the set of localized resources

* Typo: changed upper to lower

* Localize C++ Projects of FancyZones (#1130)

* localized dllmain.cpp  of fancyzones project

* localized FancyZones.cpp

* format fancyzones.rc file

* Moved SuperFancyZones back to being a string instead of having it in the resource file as it is the window class name

* reverted changes for window name

* Formatted fancyzones rc file

* Align zone dimensions from layout preview with those from grid editor (#1115)

* MSIX: add a dedicated .rc for UWPUI which joins both UI and DLL .rc's (#1139)

* Runner: fix restarting with same elevation (#1133)

* MSIX: reinstall script uses bundle instead of .msi to be able to reinstall in all cases

* Telemetry: add WebView init failure errors

* Settings: initialize COM security to allow communication between elevated Settings and WebView

* Common: implement on_scope_exit helper and typed_storage

* Changes for #1140 and #569 (#1152)

* MSIX build instructions adjustmnet (#1170)

* MSIX: hide the "Run at Startup" option if running as packaged

* MSIX: update identity name and publisher (#1176)

* Runner: fix startup task state setting for MSIX (#1181)

* Add ImageResizer to MSIX installer and make the code MSIX-compatible (#1219)

* Removed ImageResizer.exe location registry key

* Added working resize pictures to MSIX context menu without icon

* Fixed missing icon on MSIX build

* Added comments

* Changed to single context handler entry

* Made changes as per PR comments

* Localize ImageResizer (#1261)

* Removed hardcoded strings

* Added resource dlls to MSIX installer

* Save ImageResizer settings in JSON format (#1258)

* Combined settings files

* Added JSON settings functionality in PowerToys format with thread safety

* Reverting changes to csproj file

* Removed settings.settings and designer file and added target sdk tools to fix warning

* Added NewtonSoft Json package

* Added 3 tests

* Added propertychanged test

* Removed unused libraries

* Removed additional allocation statements in test

* Added comments on test

* Added one-time setup code

* Added Newtonsoft.Json.dll to MSI and MSIX installer

* Fixed copyright header

* Fixed folder location in MSIX

* Renamed jsonMutex to _jsonMutex

* Fixed line endings

* Created private setup functions and added Arrange, Act, Assert comments

* Created private setup functions and added Arrange, Act, Assert comments

* Suppressed copyright warning on AppFixture and enabled treat warnings as errors

* Added comments on Reload/AppFixture and added constructor andispose

* Added telemetry to ImageResizer Shell Extension code (dev/imageResizer) (#1272)

* Added telemetry to C++ ImageResizerExt

* Added Register and unregister calls

* Changed default enable setting

* Set startup location to center of the screen (ImageResizer) (#1452)

* Added ImageResizer resources.dlls to the MSI installer (#1448)

* Implemented fix for foreground issue for ImageResizer (#1434)

* Fixed conflict in installer README.md file

* Fixed conflict in bundle.js

* Auto-generate AssemblyInfo in ImageResizer (#1467)

* Updated assembly info

* Added auto-generation of AssemblyInfo.cs

* Fixed minor issues

* Remove the  License file since Notice.md have been added

* Fix errors due to resolving merge conflicts

Co-authored-by: Brice Lambson <brice@bricelam.net>
Co-authored-by: Clint Rutkas <clint@rutkas.com>
Co-authored-by: Arjun Balgovind <arbalgov@microsoft.com>
Co-authored-by: Enrico Giordani <enricogior@users.noreply.github.com>
Co-authored-by: Chris Davis <chrisdavis@outlook.com>
Co-authored-by: Yosef Durr <yodurr@microsoft.com>
Co-authored-by: Bartosz Sosnowski <bzoz@users.noreply.github.com>
Co-authored-by: vldmr11080 <57061786+vldmr11080@users.noreply.github.com>
Co-authored-by: yuyoyuppe <yuyoyuppe@users.noreply.github.com>
Co-authored-by: Alekhya Kommuru <alkommur@microsoft.com>
Co-authored-by: Alekhya <reddykalekhya@gmail.com>
Co-authored-by: yuyoyuppe <a.yuyoyuppe@gmail.com>
Co-authored-by: Udit Singh <udsing@microsoft.com>
This commit is contained in:
Arjun Balgovind
2020-03-12 12:02:34 -04:00
committed by GitHub
parent 7f12288b2c
commit d84cc370c9
114 changed files with 13436 additions and 10 deletions

View File

@@ -0,0 +1,31 @@
// Copyright (c) Brice Lambson
// The Brice Lambson licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. Code forked from Brice Lambson's https://github.com/bricelam/ImageResizer/
using ImageResizer.Properties;
using Newtonsoft.Json;
namespace ImageResizer.Models
{
public class CustomSize : ResizeSize
{
[JsonIgnore]
public override string Name
{
get => Resources.Input_Custom;
set { /* no-op */ }
}
public CustomSize(ResizeFit fit, double width, double height, ResizeUnit unit)
{
Fit = fit;
Width = width;
Height = height;
Unit = unit;
}
public CustomSize()
{
}
}
}

View File

@@ -0,0 +1,85 @@
// Copyright (c) Brice Lambson
// The Brice Lambson licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. Code forked from Brice Lambson's https://github.com/bricelam/ImageResizer/
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using ImageResizer.Properties;
namespace ImageResizer.Models
{
public class ResizeBatch
{
public string DestinationDirectory { get; set; }
public ICollection<string> Files { get; } = new List<string>();
public static ResizeBatch FromCommandLine(TextReader standardInput, string[] args)
{
var batch = new ResizeBatch();
// NB: We read these from stdin since there are limits on the number of args you can have
string file;
while ((file = standardInput.ReadLine()) != null)
{
batch.Files.Add(file);
}
for (var i = 0; i < args.Length; i++)
{
if (args[i] == "/d")
{
batch.DestinationDirectory = args[++i];
continue;
}
batch.Files.Add(args[i]);
}
return batch;
}
public IEnumerable<ResizeError> Process(
CancellationToken cancellationToken,
Action<int, double> reportProgress)
{
double total = Files.Count;
var completed = 0;
var errors = new ConcurrentBag<ResizeError>();
// TODO: If we ever switch to Windows.Graphics.Imaging, we can get a lot more throughput by using the async
// APIs and a custom SynchronizationContext
Parallel.ForEach(
Files,
new ParallelOptions
{
CancellationToken = cancellationToken,
MaxDegreeOfParallelism = Environment.ProcessorCount,
},
(file, state, i) =>
{
try
{
Execute(file);
}
catch (Exception ex)
{
errors.Add(new ResizeError { File = Path.GetFileName(file), Error = ex.Message });
}
Interlocked.Increment(ref completed);
reportProgress(completed, total);
});
return errors;
}
protected virtual void Execute(string file)
=> new ResizeOperation(file, DestinationDirectory, Settings.Default).Execute();
}
}

View File

@@ -0,0 +1,13 @@
// Copyright (c) Brice Lambson
// The Brice Lambson licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. Code forked from Brice Lambson's https://github.com/bricelam/ImageResizer/
namespace ImageResizer.Models
{
public class ResizeError
{
public string File { get; set; }
public string Error { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
// Copyright (c) Brice Lambson
// The Brice Lambson licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. Code forked from Brice Lambson's https://github.com/bricelam/ImageResizer/
namespace ImageResizer.Models
{
public enum ResizeFit
{
Fill,
Fit,
Stretch,
}
}

View File

@@ -0,0 +1,211 @@
// Copyright (c) Brice Lambson
// The Brice Lambson licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. Code forked from Brice Lambson's https://github.com/bricelam/ImageResizer/
using System;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using ImageResizer.Properties;
using ImageResizer.Utilities;
using Microsoft.VisualBasic.FileIO;
namespace ImageResizer.Models
{
internal class ResizeOperation
{
private readonly string _file;
private readonly string _destinationDirectory;
private readonly Settings _settings;
public ResizeOperation(string file, string destinationDirectory, Settings settings)
{
_file = file;
_destinationDirectory = destinationDirectory;
_settings = settings;
}
public void Execute()
{
string path;
using (var inputStream = File.OpenRead(_file))
{
var decoder = BitmapDecoder.Create(
inputStream,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.None);
var encoder = BitmapEncoder.Create(decoder.CodecInfo.ContainerFormat);
if (!encoder.CanEncode())
{
encoder = BitmapEncoder.Create(_settings.FallbackEncoder);
}
ConfigureEncoder(encoder);
if (decoder.Metadata != null)
{
try
{
encoder.Metadata = decoder.Metadata;
}
catch (InvalidOperationException)
{
}
}
if (decoder.Palette != null)
{
encoder.Palette = decoder.Palette;
}
foreach (var originalFrame in decoder.Frames)
{
encoder.Frames.Add(
BitmapFrame.Create(
Transform(originalFrame),
thumbnail: null,
(BitmapMetadata)originalFrame.Metadata, // TODO: Add an option to strip any metadata that doesn't affect rendering (issue #3)
colorContexts: null));
}
path = GetDestinationPath(encoder);
Directory.CreateDirectory(Path.GetDirectoryName(path));
using (var outputStream = File.Open(path, FileMode.CreateNew, FileAccess.Write))
{
encoder.Save(outputStream);
}
}
if (_settings.KeepDateModified)
{
File.SetLastWriteTimeUtc(path, File.GetLastWriteTimeUtc(_file));
}
if (_settings.Replace)
{
var backup = GetBackupPath();
File.Replace(path, _file, backup, ignoreMetadataErrors: true);
FileSystem.DeleteFile(backup, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
}
}
private void ConfigureEncoder(BitmapEncoder encoder)
{
switch (encoder)
{
case JpegBitmapEncoder jpegEncoder:
jpegEncoder.QualityLevel = MathHelpers.Clamp(_settings.JpegQualityLevel, 1, 100);
break;
case PngBitmapEncoder pngBitmapEncoder:
pngBitmapEncoder.Interlace = _settings.PngInterlaceOption;
break;
case TiffBitmapEncoder tiffEncoder:
tiffEncoder.Compression = _settings.TiffCompressOption;
break;
}
}
private BitmapSource Transform(BitmapSource source)
{
var originalWidth = source.PixelWidth;
var originalHeight = source.PixelHeight;
var width = _settings.SelectedSize.GetPixelWidth(originalWidth, source.DpiX);
var height = _settings.SelectedSize.GetPixelHeight(originalHeight, source.DpiY);
if (_settings.IgnoreOrientation
&& !_settings.SelectedSize.HasAuto
&& _settings.SelectedSize.Unit != ResizeUnit.Percent
&& originalWidth < originalHeight != (width < height))
{
var temp = width;
width = height;
height = temp;
}
var scaleX = width / originalWidth;
var scaleY = height / originalHeight;
if (_settings.SelectedSize.Fit == ResizeFit.Fit)
{
scaleX = Math.Min(scaleX, scaleY);
scaleY = scaleX;
}
else if (_settings.SelectedSize.Fit == ResizeFit.Fill)
{
scaleX = Math.Max(scaleX, scaleY);
scaleY = scaleX;
}
if (_settings.ShrinkOnly
&& _settings.SelectedSize.Unit != ResizeUnit.Percent
&& (scaleX >= 1 || scaleY >= 1))
{
return source;
}
var scaledBitmap = new TransformedBitmap(source, new ScaleTransform(scaleX, scaleY));
if (_settings.SelectedSize.Fit == ResizeFit.Fill
&& (scaledBitmap.PixelWidth > width
|| scaledBitmap.PixelHeight > height))
{
var x = (int)(((originalWidth * scaleX) - width) / 2);
var y = (int)(((originalHeight * scaleY) - height) / 2);
return new CroppedBitmap(scaledBitmap, new Int32Rect(x, y, (int)width, (int)height));
}
return scaledBitmap;
}
private string GetDestinationPath(BitmapEncoder encoder)
{
var directory = _destinationDirectory ?? Path.GetDirectoryName(_file);
var originalFileName = Path.GetFileNameWithoutExtension(_file);
var supportedExtensions = encoder.CodecInfo.FileExtensions.Split(',');
var extension = Path.GetExtension(_file);
if (!supportedExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
{
extension = supportedExtensions.FirstOrDefault();
}
var fileName = string.Format(
_settings.FileNameFormat,
originalFileName,
_settings.SelectedSize.Name,
_settings.SelectedSize.Width,
_settings.SelectedSize.Height,
encoder.Frames[0].PixelWidth,
encoder.Frames[0].PixelHeight);
var path = Path.Combine(directory, fileName + extension);
var uniquifier = 1;
while (File.Exists(path))
{
path = Path.Combine(directory, fileName + " (" + uniquifier++ + ")" + extension);
}
return path;
}
private string GetBackupPath()
{
var directory = Path.GetDirectoryName(_file);
var fileName = Path.GetFileNameWithoutExtension(_file);
var extension = Path.GetExtension(_file);
var path = Path.Combine(directory, fileName + ".bak" + extension);
var uniquifier = 1;
while (File.Exists(path))
{
path = Path.Combine(directory, fileName + " (" + uniquifier++ + ")" + ".bak" + extension);
}
return path;
}
}
}

View File

@@ -0,0 +1,154 @@
// Copyright (c) Brice Lambson
// The Brice Lambson licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. Code forked from Brice Lambson's https://github.com/bricelam/ImageResizer/
using System.Collections.Generic;
using System.Diagnostics;
using GalaSoft.MvvmLight;
using ImageResizer.Properties;
using Newtonsoft.Json;
namespace ImageResizer.Models
{
[JsonObject(MemberSerialization.OptIn)]
public class ResizeSize : ObservableObject
{
private static readonly IDictionary<string, string> _tokens;
private string _name;
private ResizeFit _fit = ResizeFit.Fit;
private double _width;
private double _height;
private bool _showHeight = true;
private ResizeUnit _unit = ResizeUnit.Pixel;
static ResizeSize()
=> _tokens = new Dictionary<string, string>
{
["$small$"] = Resources.Small,
["$medium$"] = Resources.Medium,
["$large$"] = Resources.Large,
["$phone$"] = Resources.Phone,
};
public ResizeSize(string name, ResizeFit fit, double width, double height, ResizeUnit unit)
{
Name = name;
Fit = fit;
Width = width;
Height = height;
Unit = unit;
}
public ResizeSize()
{
}
[JsonProperty(PropertyName = "name")]
public virtual string Name
{
get => _name;
set => Set(nameof(Name), ref _name, ReplaceTokens(value));
}
[JsonProperty(PropertyName = "fit")]
public ResizeFit Fit
{
get => _fit;
set
{
if (Set(nameof(Fit), ref _fit, value))
{
UpdateShowHeight();
}
}
}
[JsonProperty(PropertyName = "width")]
public double Width
{
get => _width;
set => Set(nameof(Width), ref _width, value);
}
[JsonProperty(PropertyName = "height")]
public double Height
{
get => _height;
set => Set(nameof(Height), ref _height, value);
}
public bool ShowHeight
=> _showHeight;
public bool HasAuto
=> Width == 0 || Height == 0;
[JsonProperty(PropertyName = "unit")]
public ResizeUnit Unit
{
get => _unit;
set
{
if (Set(nameof(Unit), ref _unit, value))
{
UpdateShowHeight();
}
}
}
public double GetPixelWidth(int originalWidth, double dpi)
=> ConvertToPixels(Width, Unit, originalWidth, dpi);
public double GetPixelHeight(int originalHeight, double dpi)
=> ConvertToPixels(
Fit != ResizeFit.Stretch && Unit == ResizeUnit.Percent
? Width
: Height,
Unit,
originalHeight,
dpi);
private static string ReplaceTokens(string text)
=> (text != null && _tokens.TryGetValue(text, out var result))
? result
: text;
private void UpdateShowHeight()
=> Set(
nameof(ShowHeight),
ref _showHeight,
Fit == ResizeFit.Stretch || Unit != ResizeUnit.Percent);
private double ConvertToPixels(double value, ResizeUnit unit, int originalValue, double dpi)
{
if (value == 0)
{
if (Fit == ResizeFit.Fit)
{
return double.PositiveInfinity;
}
Debug.Assert(Fit == ResizeFit.Fill || Fit == ResizeFit.Stretch, "Unexpected ResizeFit value: " + Fit);
return originalValue;
}
switch (unit)
{
case ResizeUnit.Inch:
return value * dpi;
case ResizeUnit.Centimeter:
return value * dpi / 2.54;
case ResizeUnit.Percent:
return value / 100 * originalValue;
default:
Debug.Assert(unit == ResizeUnit.Pixel, "Unexpected unit value: " + unit);
return value;
}
}
}
}

View File

@@ -0,0 +1,14 @@
// Copyright (c) Brice Lambson
// The Brice Lambson licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. Code forked from Brice Lambson's https://github.com/bricelam/ImageResizer/
namespace ImageResizer.Models
{
public enum ResizeUnit
{
Centimeter,
Inch,
Percent,
Pixel,
}
}