Skip to content

Commit e718433

Browse files
committed
feat: initial commit
0 parents  commit e718433

15 files changed

Lines changed: 1085 additions & 0 deletions

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/src/Pixsys.Library.Media.ImageManager/.build/CakeRelease/
2+
/src/Pixsys.Library.Media.ImageManager/.vs/
3+
/src/Pixsys.Library.Media.ImageManager/Pixsys.Library.Media.ImageManager/bin/
4+
/src/Pixsys.Library.Media.ImageManager/Pixsys.Library.Media.ImageManager/obj/
5+
/src/Pixsys.Library.Media.ImageManager/.config/CakeRelease.settings.json

README.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Image Manager
2+
3+
This manager will save and transform your images as a Fluent API, using SixLabors.ImageSharp library.
4+
5+
## 1. Installation
6+
7+
### 1.1 Register your settings in `appsettings.json`
8+
9+
Create a new section called `ImageManager` and add the following properties:
10+
11+
| Name | Optional? | Description
12+
|----------|----------|------------|
13+
| TemporaryFolder | Yes | Sets where the temporary image folder is located. Useful when you're working with uploaded images.
14+
| Profiles | Yes | Sets all the profiles. Each profile contains a name, a array of sizes required for your needs, and a true/false property telling if you want to keep the original image when resizing.
15+
16+
```json
17+
"ImageManager": {
18+
"TemporaryFolder": "<TEMP_FOLDER>",
19+
"Profiles": [
20+
{
21+
"Name": "<PROFILE_NAME>",
22+
"Sizes": [
23+
{
24+
"Width": <WIDTH>,
25+
"Height": <HEIGHT>
26+
},
27+
{
28+
"Width": <WIDTH>,
29+
"Height": <HEIGHT>
30+
}
31+
],
32+
"KeepOriginalWhenResizing": <KEEP_ORIGINAL_WHEN_RESIZING>
33+
},
34+
{
35+
"Name": "<PROFILE_NAME>",
36+
"Sizes": [
37+
{
38+
"Width": <WIDTH>,
39+
"Height": <HEIGHT>
40+
},
41+
{
42+
"Width": <WIDTH>,
43+
"Height": <HEIGHT>
44+
}
45+
],
46+
"KeepOriginalWhenResizing": <KEEP_ORIGINAL_WHEN_RESIZING>
47+
}
48+
]
49+
}
50+
```
51+
52+
If profiles are set, the following image folder structure will be created:
53+
54+
```
55+
├── <IMAGE_FOLDER>
56+
│ ├── <PROFILE_1>
57+
│ │ ├── <WIDTH_1xHEIGHT1> //ex: folder named '200x200'
58+
│ │ │ ├── IMG
59+
│ │ ├── <WIDTH_2xHEIGHT2>
60+
│ │ │ ├── IMG
61+
```
62+
63+
### 1.2 Register the service in `Program.cs`
64+
65+
```csharp
66+
67+
using Pixsys.Library.Media.ImageManager;
68+
69+
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
70+
71+
_ = builder.AddImageManager();
72+
73+
```
74+
75+
### 2 Usage
76+
77+
#### 2.1 Inject the service into your controller
78+
79+
```csharp
80+
private readonly IImageManager _imageManager;
81+
82+
public MyController(IImageManager imageManager)
83+
{
84+
_imageManager = imageManager;;
85+
}
86+
```
87+
88+
#### 2.2 Methods
89+
90+
First, you set if the image manager must process a server-stored image (`ForImage`) or an uploaded one (`FromFormFile`).
91+
92+
Then you can apply multiple manipulations (such as `resize`,`crop`,`Sepia`,...) and/or save the output.
93+
94+
If you specify a profile name in the `SaveAsync` method, it will create resized images in the 'profile name' folder.
95+
96+
#### 2.2.1 Example
97+
98+
```csharp
99+
await _imageManager
100+
.ForImage(<FILE_PATH>)
101+
.BlackWhite()
102+
.AutoOrient()
103+
.Resize(new SixLabors.ImageSharp.Processing.ResizeOptions
104+
{
105+
Mode = SixLabors.ImageSharp.Processing.ResizeMode.Max,
106+
Size = new Size(300, 400)
107+
})
108+
.Flip(SixLabors.ImageSharp.Processing.FlipMode.Horizontal)
109+
.Grayscale()
110+
.Polaroid()
111+
.Vignette()
112+
.Sepia()
113+
.Pixelate()
114+
.OilPaint()
115+
.SaveAsync(new DirectoryInfo(webRootPath), "output", Pixsys.Library.Media.Common.Enums.ImageFormat.Webp, false, "test");
116+
```
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
3+
<metadata>
4+
<id>Pixsys.Library.Media.ImageManager</id>
5+
<title>Pixsys.Library.Media.ImageManager</title>
6+
<description>This manager will save and transform your images as a Fluent API, using SixLabors.ImageSharp library</description>
7+
<authors>Sylvain Signore</authors>
8+
<version>0.0.0.0</version>
9+
<readme>README.md</readme>
10+
<projectUrl>https://github.com/PixsysBE/Pixsys.Library.Media.ImageManager</projectUrl>
11+
<dependencies>
12+
<group targetFramework="net8.0" >
13+
<dependency id="Pixsys.Library.Media.Common" version="1.0.0" />
14+
<dependency id="Pixsys.Library.Common" version="1.0.0" />
15+
</group>
16+
</dependencies>
17+
</metadata>
18+
<files>
19+
<file src="bin\Release\**\*.dll" target="lib" />
20+
<file src="bin\Release\**\*.xml" target="lib" />
21+
<file src="..\..\..\README.md" target="README.md" />
22+
</files>
23+
</package>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": 1,
3+
"isRoot": true,
4+
"tools": {
5+
"cake.tool": {
6+
"version": "4.0.0",
7+
"commands": [
8+
"dotnet-cake"
9+
]
10+
}
11+
}
12+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# NOTE: Requires **VS2019 16.3** or later
2+
3+
# StyleCopeRules
4+
# Description: StyleCopeRules custom ruleset
5+
6+
# Code files
7+
[*.{cs,vb}]
8+
9+
10+
# Default severity for analyzer diagnostics - Requires **VS2019 16.5** or later
11+
dotnet_analyzer_diagnostic.severity = warning
12+
13+
dotnet_diagnostic.SA1101.severity = none
14+
15+
[*.{cs,vb}]
16+
#### Naming styles ####
17+
18+
# Naming rules
19+
20+
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
21+
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
22+
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
23+
24+
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
25+
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
26+
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
27+
28+
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
29+
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
30+
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
31+
32+
# Symbol specifications
33+
34+
dotnet_naming_symbols.interface.applicable_kinds = interface
35+
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
36+
dotnet_naming_symbols.interface.required_modifiers =
37+
38+
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
39+
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
40+
dotnet_naming_symbols.types.required_modifiers =
41+
42+
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
43+
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
44+
dotnet_naming_symbols.non_field_members.required_modifiers =
45+
46+
# Naming styles
47+
48+
dotnet_naming_style.begins_with_i.required_prefix = I
49+
dotnet_naming_style.begins_with_i.required_suffix =
50+
dotnet_naming_style.begins_with_i.word_separator =
51+
dotnet_naming_style.begins_with_i.capitalization = pascal_case
52+
53+
dotnet_naming_style.pascal_case.required_prefix =
54+
dotnet_naming_style.pascal_case.required_suffix =
55+
dotnet_naming_style.pascal_case.word_separator =
56+
dotnet_naming_style.pascal_case.capitalization = pascal_case
57+
58+
dotnet_naming_style.pascal_case.required_prefix =
59+
dotnet_naming_style.pascal_case.required_suffix =
60+
dotnet_naming_style.pascal_case.word_separator =
61+
dotnet_naming_style.pascal_case.capitalization = pascal_case
62+
dotnet_style_operator_placement_when_wrapping = beginning_of_line
63+
tab_width = 4
64+
indent_size = 4
65+
end_of_line = crlf
66+
67+
[*.cs]
68+
csharp_using_directive_placement = outside_namespace:silent
69+
csharp_prefer_simple_using_statement = true:suggestion
70+
csharp_prefer_braces = true:silent
71+
csharp_style_namespace_declarations = block_scoped:silent
72+
csharp_style_prefer_method_group_conversion = true:silent
73+
csharp_style_prefer_top_level_statements = true:silent
74+
csharp_style_prefer_primary_constructors = true:suggestion
75+
csharp_style_expression_bodied_methods = false:silent
76+
csharp_style_expression_bodied_constructors = false:silent
77+
csharp_style_expression_bodied_operators = false:silent
78+
csharp_style_expression_bodied_properties = true:silent
79+
csharp_style_expression_bodied_indexers = true:silent
80+
csharp_style_expression_bodied_accessors = true:silent
81+
csharp_indent_labels = one_less_than_current
82+
csharp_style_expression_bodied_lambdas = true:silent
83+
csharp_space_around_binary_operators = before_and_after
84+
85+
dotnet_diagnostic.SA1009.severity = none #SA1009ClosingParenthesisMustBeSpacedCorrectly
86+
dotnet_diagnostic.SA1636.severity = none #SA1636FileHeaderCopyrightTextMustMatch
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.8.34525.116
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pixsys.Library.Media.ImageManager", "Pixsys.Library.Media.ImageManager\Pixsys.Library.Media.ImageManager.csproj", "{D1C47FC5-8269-46EA-B2DE-2E17B9C17C48}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{D1C47FC5-8269-46EA-B2DE-2E17B9C17C48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{D1C47FC5-8269-46EA-B2DE-2E17B9C17C48}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{D1C47FC5-8269-46EA-B2DE-2E17B9C17C48}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{D1C47FC5-8269-46EA-B2DE-2E17B9C17C48}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {353EA252-474D-415C-A588-AB0233AEAA49}
24+
EndGlobalSection
25+
EndGlobal
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// -----------------------------------------------------------------------
2+
// <copyright file="ImageManagerExtensions.cs" company="Pixsys">
3+
// Copyright (c) Pixsys. All rights reserved.
4+
// </copyright>
5+
// -----------------------------------------------------------------------
6+
7+
using Microsoft.AspNetCore.Builder;
8+
using Microsoft.Extensions.DependencyInjection;
9+
using Microsoft.Extensions.DependencyInjection.Extensions;
10+
using Pixsys.Library.Media.ImageManager.Interfaces;
11+
using Pixsys.Library.Media.ImageManager.Models;
12+
13+
#pragma warning disable IDE0130 // Namespace does not match folder structure
14+
namespace Pixsys.Library.Media.ImageManager
15+
#pragma warning restore IDE0130 // Namespace does not match folder structure
16+
{
17+
/// <summary>
18+
/// The Image Manager extensions.
19+
/// </summary>
20+
public static class ImageManagerExtensions
21+
{
22+
/// <summary>
23+
/// Adds the Image manager.
24+
/// </summary>
25+
/// <param name="builder">The builder.</param>
26+
/// <returns>The updated builder.</returns>
27+
public static WebApplicationBuilder AddImageManager(this WebApplicationBuilder builder)
28+
{
29+
_ = builder.Services.Configure<ImageManagerSettings>(builder.Configuration.GetSection(nameof(ImageManager)));
30+
builder.Services.TryAddTransient<IImageManager, ImageManager>();
31+
return builder;
32+
}
33+
}
34+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// -----------------------------------------------------------------------
2+
// <copyright file="ImageManagerHelper.cs" company="Pixsys">
3+
// Copyright (c) Pixsys. All rights reserved.
4+
// </copyright>
5+
// -----------------------------------------------------------------------
6+
7+
using Pixsys.Library.Media.ImageManager.Models;
8+
9+
namespace Pixsys.Library.Media.ImageManager.Helpers
10+
{
11+
/// <summary>
12+
/// The image manager helper.
13+
/// </summary>
14+
internal static class ImageManagerHelper
15+
{
16+
/// <summary>
17+
/// Deletes one or more images asynchronously.
18+
/// </summary>
19+
/// <param name="folder">The folder.</param>
20+
/// <param name="fileName">The file name.</param>
21+
/// <param name="profiles">The profiles.</param>
22+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
23+
public static async Task DeleteAsync(DirectoryInfo folder, string fileName, List<ImageProfile>? profiles = null)
24+
{
25+
if (!string.IsNullOrWhiteSpace(fileName))
26+
{
27+
if (profiles != null)
28+
{
29+
foreach (ImageProfile profile in profiles)
30+
{
31+
foreach (SixLabors.ImageSharp.Size size in profile.Sizes)
32+
{
33+
string dimensionSourceFolder = folder.FullName + size.Width + "x" + size.Height;
34+
string deletePath = Path.Combine(dimensionSourceFolder, fileName);
35+
if (File.Exists(deletePath))
36+
{
37+
await Task.Run(() => File.Delete(deletePath));
38+
}
39+
}
40+
}
41+
}
42+
43+
string fileDeletePath = Path.Combine(folder.FullName, fileName);
44+
if (File.Exists(fileDeletePath))
45+
{
46+
await Task.Run(() => File.Delete(fileDeletePath));
47+
}
48+
}
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)