First commit
BIN
UnitTest/TestImages/1.jpg
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
UnitTest/TestImages/2.png
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
UnitTest/TestImages/3.png
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
UnitTest/TestImages/4.jpg
Normal file
|
After Width: | Height: | Size: 91 KiB |
BIN
UnitTest/TestImages/5.jpg
Normal file
|
After Width: | Height: | Size: 99 KiB |
BIN
UnitTest/TestImages/6.jpg
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
UnitTest/TestImages/7.jpg
Normal file
|
After Width: | Height: | Size: 530 KiB |
BIN
UnitTest/TestImages/sample_wm.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
76
UnitTest/UnitTest.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using SixLabors.Fonts;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using Watermark.Net.src.WatermarkNet.Core;
|
||||
using Watermark.Net.src.WatermarkNet.Types;
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
[TestClass]
|
||||
public class UnitTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void TextWatermarkTest()
|
||||
{
|
||||
var watermarker = new Watermarker();
|
||||
var watermark = new TextWatermark();
|
||||
|
||||
watermark.Text = "Test";
|
||||
watermark.Color = Color.White;
|
||||
watermark.Font = SystemFonts.CreateFont("Arial", 1);
|
||||
watermark.Position = Watermark.Net.src.WatermarkNet.Enums.ImagePosition.BottomCenter;
|
||||
watermark.RotateAngle = 90;
|
||||
var resultedImage = watermarker.ProcessImage("TestImages/2.png", "test/text", watermark);
|
||||
|
||||
Assert.IsTrue(File.Exists(resultedImage.Path));
|
||||
Assert.IsNotNull(resultedImage);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ImageWatermarkTest()
|
||||
{
|
||||
var watermarker = new Watermarker();
|
||||
var watermark = new ImageWatermark();
|
||||
|
||||
watermark.ImagePath = "TestImages/sample_wm.png";
|
||||
watermark.Position = Watermark.Net.src.WatermarkNet.Enums.ImagePosition.Center;
|
||||
watermark.Scale = 1;
|
||||
var resultedImage = watermarker.ProcessImage("TestImages/2.png", "test/image", watermark);
|
||||
|
||||
Assert.IsTrue(File.Exists(resultedImage.Path));
|
||||
Assert.IsNotNull(resultedImage);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TextWatermarkDirectoryProccessTest()
|
||||
{
|
||||
var watermarker = new Watermarker("test/text/pave");
|
||||
var watermark = new TextWatermark();
|
||||
|
||||
watermark.Text = "Test";
|
||||
watermark.Color = Rgba32.ParseHex("FFFFFF50");
|
||||
watermark.Font = SystemFonts.CreateFont("Arial", 14);
|
||||
watermark.Scale = 1f;
|
||||
watermark.Position = Watermark.Net.src.WatermarkNet.Enums.ImagePosition.TopLeft;
|
||||
watermark.Pave = true;
|
||||
watermarker.ProcessDirectory("TestImages", watermark);
|
||||
|
||||
Assert.IsTrue(Directory.GetFiles(watermarker.OutputDir)?.Length > 0);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ImageWatermarkDirectoryProccessTest()
|
||||
{
|
||||
var watermarker = new Watermarker("test/image/pave");
|
||||
var watermark = new ImageWatermark();
|
||||
|
||||
watermark.ImagePath = "TestImages/sample_wm.png";
|
||||
watermark.Position = Watermark.Net.src.WatermarkNet.Enums.ImagePosition.Center;
|
||||
watermark.Scale = 1;
|
||||
watermark.Pave = true;
|
||||
var resultedImage = watermarker.ProcessDirectory("TestImages", watermark);
|
||||
|
||||
Assert.IsTrue(Directory.GetFiles(watermarker.OutputDir)?.Length > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
51
UnitTest/UnitTest.csproj
Normal file
@@ -0,0 +1,51 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.4.3" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.4.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2"><IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Watermark.Net\Watermark.Net.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="TestImages\1.jpg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="TestImages\2.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="TestImages\3.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="TestImages\4.jpg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="TestImages\5.jpg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="TestImages\6.jpg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="TestImages\7.jpg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="TestImages\sample_wm.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
2
UnitTest/Usings.cs
Normal file
@@ -0,0 +1,2 @@
|
||||
global using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
global using Watermark;
|
||||
BIN
Watermark.Net/.vs/ProjectEvaluation/watermark.net.strings.v9.bin
Normal file
BIN
Watermark.Net/.vs/Watermark.Net/DesignTimeBuild/.dtbcache.v2
Normal file
BIN
Watermark.Net/.vs/Watermark.Net/v17/.futdcache.v2
Normal file
BIN
Watermark.Net/.vs/Watermark.Net/v17/.suo
Normal file
132
Watermark.Net/.vs/Watermark.Net/v17/DocumentLayout.backup.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\",
|
||||
"Documents": [
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|d:\\dev\\getready\\watermark.net\\watermark.net\\watermark.net.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|",
|
||||
"RelativeMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|solutionrelative:watermark.net.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|d:\\dev\\getready\\watermark.net\\watermark.net\\watermark.net.csproj||{04B8AB82-A572-4FEF-95CE-5222444B6B64}|",
|
||||
"RelativeMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|solutionrelative:watermark.net.csproj||{04B8AB82-A572-4FEF-95CE-5222444B6B64}|"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|d:\\dev\\getready\\watermark.net\\watermark.net\\src\\watermarknet.common\\watermarker.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|solutionrelative:src\\watermarknet.common\\watermarker.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|d:\\dev\\getready\\watermark.net\\watermark.net\\src\\watermarknet.types\\sourceimage.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|solutionrelative:src\\watermarknet.types\\sourceimage.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|d:\\dev\\getready\\watermark.net\\watermark.net\\src\\watermarknet.types\\imagewatermark.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|solutionrelative:src\\watermarknet.types\\imagewatermark.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|d:\\dev\\getready\\watermark.net\\watermark.net\\src\\watermarknet.types\\textwatermark.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|solutionrelative:src\\watermarknet.types\\textwatermark.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|D:\\dev\\Watermark.NET\\UnitTest\\UnitTest.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
}
|
||||
],
|
||||
"DocumentGroupContainers": [
|
||||
{
|
||||
"Orientation": 0,
|
||||
"VerticalTabListWidth": 256,
|
||||
"DocumentGroups": [
|
||||
{
|
||||
"DockedWidth": 200,
|
||||
"SelectedChildIndex": 0,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "Watermark.Net.csproj",
|
||||
"DocumentMoniker": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\Watermark.Net.csproj",
|
||||
"RelativeDocumentMoniker": "Watermark.Net.csproj",
|
||||
"ToolTip": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\Watermark.Net.csproj",
|
||||
"RelativeToolTip": "Watermark.Net.csproj",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000758|",
|
||||
"WhenOpened": "2025-07-23T00:08:42.641Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 4,
|
||||
"Title": "ImageWatermark.cs",
|
||||
"DocumentMoniker": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Types\\ImageWatermark.cs",
|
||||
"RelativeDocumentMoniker": "src\\WatermarkNet.Types\\ImageWatermark.cs",
|
||||
"ToolTip": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Types\\ImageWatermark.cs",
|
||||
"RelativeToolTip": "src\\WatermarkNet.Types\\ImageWatermark.cs",
|
||||
"ViewState": "AgIAAA4AAAAAAAAAAAAQwEMAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-07-22T00:18:31.318Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 3,
|
||||
"Title": "SourceImage.cs",
|
||||
"DocumentMoniker": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Types\\SourceImage.cs",
|
||||
"RelativeDocumentMoniker": "src\\WatermarkNet.Types\\SourceImage.cs",
|
||||
"ToolTip": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Types\\SourceImage.cs",
|
||||
"RelativeToolTip": "src\\WatermarkNet.Types\\SourceImage.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-07-22T00:18:29.952Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "Watermark.Net",
|
||||
"DocumentMoniker": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\Watermark.Net.csproj",
|
||||
"RelativeDocumentMoniker": "Watermark.Net.csproj",
|
||||
"ToolTip": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\Watermark.Net.csproj",
|
||||
"RelativeToolTip": "Watermark.Net.csproj",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000758|",
|
||||
"WhenOpened": "2025-07-22T00:16:02.548Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 6,
|
||||
"Title": "UnitTest.cs",
|
||||
"DocumentMoniker": "D:\\dev\\Watermark.NET\\UnitTest\\UnitTest.cs",
|
||||
"RelativeDocumentMoniker": "..\\..\\..\\Watermark.NET\\UnitTest\\UnitTest.cs",
|
||||
"ToolTip": "D:\\dev\\Watermark.NET\\UnitTest\\UnitTest.cs",
|
||||
"RelativeToolTip": "..\\..\\..\\Watermark.NET\\UnitTest\\UnitTest.cs",
|
||||
"ViewState": "AgIAABgAAAAAAAAAAADgvyYAAAABAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-07-22T00:10:06.88Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 5,
|
||||
"Title": "TextWatermark.cs",
|
||||
"DocumentMoniker": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Types\\TextWatermark.cs",
|
||||
"RelativeDocumentMoniker": "src\\WatermarkNet.Types\\TextWatermark.cs",
|
||||
"ToolTip": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Types\\TextWatermark.cs",
|
||||
"RelativeToolTip": "src\\WatermarkNet.Types\\TextWatermark.cs",
|
||||
"ViewState": "AgIAABoAAAAAAAAAAAAUwFIAAAABAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-07-21T23:58:35.959Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 2,
|
||||
"Title": "Watermarker.cs",
|
||||
"DocumentMoniker": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Common\\Watermarker.cs",
|
||||
"RelativeDocumentMoniker": "src\\WatermarkNet.Common\\Watermarker.cs",
|
||||
"ToolTip": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Common\\Watermarker.cs",
|
||||
"RelativeToolTip": "src\\WatermarkNet.Common\\Watermarker.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAABUAAAAcAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-07-15T22:39:18.693Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
132
Watermark.Net/.vs/Watermark.Net/v17/DocumentLayout.json
Normal file
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\",
|
||||
"Documents": [
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|d:\\dev\\getready\\watermark.net\\watermark.net\\watermark.net.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|",
|
||||
"RelativeMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|solutionrelative:watermark.net.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|d:\\dev\\getready\\watermark.net\\watermark.net\\watermark.net.csproj||{04B8AB82-A572-4FEF-95CE-5222444B6B64}|",
|
||||
"RelativeMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|solutionrelative:watermark.net.csproj||{04B8AB82-A572-4FEF-95CE-5222444B6B64}|"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|d:\\dev\\getready\\watermark.net\\watermark.net\\src\\watermarknet.common\\watermarker.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|solutionrelative:src\\watermarknet.common\\watermarker.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|d:\\dev\\getready\\watermark.net\\watermark.net\\src\\watermarknet.types\\sourceimage.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|solutionrelative:src\\watermarknet.types\\sourceimage.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|d:\\dev\\getready\\watermark.net\\watermark.net\\src\\watermarknet.types\\imagewatermark.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|solutionrelative:src\\watermarknet.types\\imagewatermark.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|d:\\dev\\getready\\watermark.net\\watermark.net\\src\\watermarknet.types\\textwatermark.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}|Watermark.Net.csproj|solutionrelative:src\\watermarknet.types\\textwatermark.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|D:\\dev\\Watermark.NET\\UnitTest\\UnitTest.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
}
|
||||
],
|
||||
"DocumentGroupContainers": [
|
||||
{
|
||||
"Orientation": 0,
|
||||
"VerticalTabListWidth": 256,
|
||||
"DocumentGroups": [
|
||||
{
|
||||
"DockedWidth": 200,
|
||||
"SelectedChildIndex": 0,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "Watermark.Net.csproj",
|
||||
"DocumentMoniker": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\Watermark.Net.csproj",
|
||||
"RelativeDocumentMoniker": "Watermark.Net.csproj",
|
||||
"ToolTip": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\Watermark.Net.csproj",
|
||||
"RelativeToolTip": "Watermark.Net.csproj",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000758|",
|
||||
"WhenOpened": "2025-07-23T00:08:42.641Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 4,
|
||||
"Title": "ImageWatermark.cs",
|
||||
"DocumentMoniker": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Types\\ImageWatermark.cs",
|
||||
"RelativeDocumentMoniker": "src\\WatermarkNet.Types\\ImageWatermark.cs",
|
||||
"ToolTip": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Types\\ImageWatermark.cs",
|
||||
"RelativeToolTip": "src\\WatermarkNet.Types\\ImageWatermark.cs",
|
||||
"ViewState": "AgIAAA4AAAAAAAAAAAAQwEMAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-07-22T00:18:31.318Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 3,
|
||||
"Title": "SourceImage.cs",
|
||||
"DocumentMoniker": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Types\\SourceImage.cs",
|
||||
"RelativeDocumentMoniker": "src\\WatermarkNet.Types\\SourceImage.cs",
|
||||
"ToolTip": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Types\\SourceImage.cs",
|
||||
"RelativeToolTip": "src\\WatermarkNet.Types\\SourceImage.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-07-22T00:18:29.952Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "Watermark.Net",
|
||||
"DocumentMoniker": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\Watermark.Net.csproj",
|
||||
"RelativeDocumentMoniker": "Watermark.Net.csproj",
|
||||
"ToolTip": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\Watermark.Net.csproj",
|
||||
"RelativeToolTip": "Watermark.Net.csproj",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000758|",
|
||||
"WhenOpened": "2025-07-22T00:16:02.548Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 6,
|
||||
"Title": "UnitTest.cs",
|
||||
"DocumentMoniker": "D:\\dev\\Watermark.NET\\UnitTest\\UnitTest.cs",
|
||||
"RelativeDocumentMoniker": "..\\..\\..\\Watermark.NET\\UnitTest\\UnitTest.cs",
|
||||
"ToolTip": "D:\\dev\\Watermark.NET\\UnitTest\\UnitTest.cs",
|
||||
"RelativeToolTip": "..\\..\\..\\Watermark.NET\\UnitTest\\UnitTest.cs",
|
||||
"ViewState": "AgIAABgAAAAAAAAAAADgvyYAAAABAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-07-22T00:10:06.88Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 5,
|
||||
"Title": "TextWatermark.cs",
|
||||
"DocumentMoniker": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Types\\TextWatermark.cs",
|
||||
"RelativeDocumentMoniker": "src\\WatermarkNet.Types\\TextWatermark.cs",
|
||||
"ToolTip": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Types\\TextWatermark.cs",
|
||||
"RelativeToolTip": "src\\WatermarkNet.Types\\TextWatermark.cs",
|
||||
"ViewState": "AgIAABoAAAAAAAAAAAAUwFIAAAABAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-07-21T23:58:35.959Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 2,
|
||||
"Title": "Watermarker.cs",
|
||||
"DocumentMoniker": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Common\\Watermarker.cs",
|
||||
"RelativeDocumentMoniker": "src\\WatermarkNet.Common\\Watermarker.cs",
|
||||
"ToolTip": "D:\\dev\\GetReady\\Watermark.Net\\Watermark.Net\\src\\WatermarkNet.Common\\Watermarker.cs",
|
||||
"RelativeToolTip": "src\\WatermarkNet.Common\\Watermarker.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAABUAAAAcAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-07-15T22:39:18.693Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
Watermark.Net/.vs/Watermark.Net/v17/TestStore/0/000.testlog
Normal file
BIN
Watermark.Net/.vs/Watermark.Net/v17/TestStore/0/testlog.manifest
Normal file
21
Watermark.Net/Watermark.Net.csproj
Normal file
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||
<AssemblyVersion>0.25.7.23</AssemblyVersion>
|
||||
<Title>Waternark.NET</Title>
|
||||
<Authors>Geckon01</Authors>
|
||||
<Description>Watermark.Net is .NET library for adding text and image watermarks to images. Built on SixLabors.ImageSharp, it provides a simple yet comprehensive API for all your watermarking needs.</Description>
|
||||
<FileVersion>0.25.7.23</FileVersion>
|
||||
<Version>0.25.7.23</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
|
||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.3" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
43
Watermark.Net/Watermark.Net.sln
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.4.33213.308
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Watermark.Net", "Watermark.Net.csproj", "{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "..\UnitTest\UnitTest.csproj", "{26E6D8A0-CFB1-4A30-A4DD-D6DBBDADB388}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample", "..\Sample\Sample.csproj", "{E28B3D42-E65D-4178-A25B-8B76FC6F9673}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Watrmark.Net CLI", "..\Watrmark.Net CLI\Watrmark.Net CLI.csproj", "{EC1F992E-6B68-45E7-8879-8576F728A6F3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5000C6D8-A7CD-4815-A724-EEE51AD8AFDA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{26E6D8A0-CFB1-4A30-A4DD-D6DBBDADB388}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{26E6D8A0-CFB1-4A30-A4DD-D6DBBDADB388}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{26E6D8A0-CFB1-4A30-A4DD-D6DBBDADB388}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{26E6D8A0-CFB1-4A30-A4DD-D6DBBDADB388}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E28B3D42-E65D-4178-A25B-8B76FC6F9673}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E28B3D42-E65D-4178-A25B-8B76FC6F9673}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E28B3D42-E65D-4178-A25B-8B76FC6F9673}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E28B3D42-E65D-4178-A25B-8B76FC6F9673}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EC1F992E-6B68-45E7-8879-8576F728A6F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EC1F992E-6B68-45E7-8879-8576F728A6F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EC1F992E-6B68-45E7-8879-8576F728A6F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EC1F992E-6B68-45E7-8879-8576F728A6F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {BDD35E29-9EA2-4833-B2F4-26E051B7AF10}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
342
Watermark.Net/src/WatermarkNet.Common/Watermarker.cs
Normal file
@@ -0,0 +1,342 @@
|
||||
using SixLabors.Fonts;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Drawing.Processing;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using Watermark.Net.src.WatermarkNet.Enums;
|
||||
using Watermark.Net.src.WatermarkNet.Types;
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
using Image = SixLabors.ImageSharp.Image;
|
||||
|
||||
namespace Watermark.Net.src.WatermarkNet.Core
|
||||
{
|
||||
public class Watermarker
|
||||
{
|
||||
private string _outputDir;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the output directory for processed images.
|
||||
/// </summary>
|
||||
public string OutputDir { get { return _outputDir; } set { _outputDir = value; } }
|
||||
public Watermarker()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Watermarker(string outputDir)
|
||||
{
|
||||
_outputDir = outputDir;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes all images in a directory applying watermark.
|
||||
/// </summary>
|
||||
/// <param name="directory">Source directory containing images to process.</param>
|
||||
/// <param name="watermark">Watermark configuration.</param>
|
||||
/// <returns>List of processed images with watermark information.</returns>
|
||||
public List<WmarkedImage> ProcessDirectory<T>(string directory, T watermark)
|
||||
where T : WatermarkImageBase
|
||||
{
|
||||
List<WmarkedImage> processedImages = new List<WmarkedImage>();
|
||||
foreach (var imageFile in Directory.GetFiles(directory))
|
||||
{
|
||||
//Do not process directories and hidden files
|
||||
if (File.GetAttributes(imageFile).HasFlag(FileAttributes.Directory) || File.GetAttributes(imageFile).HasFlag(FileAttributes.Hidden))
|
||||
continue;
|
||||
|
||||
WmarkedImage? resultedImage = null;
|
||||
if (typeof(T).IsAssignableTo(typeof(ImageWatermark)))
|
||||
{
|
||||
var concreateWatermark = (ImageWatermark)Convert.ChangeType(watermark, typeof(ImageWatermark));
|
||||
resultedImage = ProcessImage(imageFile, this.OutputDir, concreateWatermark);
|
||||
}
|
||||
if (typeof(T).IsAssignableTo(typeof(TextWatermark)))
|
||||
{
|
||||
var concreateWatermark = (TextWatermark)Convert.ChangeType(watermark, typeof(TextWatermark));
|
||||
resultedImage = ProcessImage(imageFile, this.OutputDir, concreateWatermark);
|
||||
}
|
||||
if (resultedImage != null)
|
||||
processedImages.Add(resultedImage);
|
||||
}
|
||||
return processedImages;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies an image watermark to a single image.
|
||||
/// </summary>
|
||||
/// <param name="imagePath">Path to source image file.</param>
|
||||
/// <param name="outputDirectory">Output directory for processed image.</param>
|
||||
/// <param name="watermark">Image watermark configuration.</param>
|
||||
/// <returns>Processed image information or null on failure.</returns>
|
||||
/// <exception cref="FileNotFoundException">Thrown when source image or watermark image is missing.</exception>
|
||||
public WmarkedImage? ProcessImage(string imagePath, string outputDirectory, ImageWatermark watermark)
|
||||
{
|
||||
if (!File.Exists(imagePath)) { throw new FileNotFoundException("Source file not found!", imagePath); }
|
||||
if (!File.Exists(watermark.ImagePath)) { throw new FileNotFoundException("Watermark file not found!", imagePath); }
|
||||
if (!Directory.Exists(outputDirectory)) { Directory.CreateDirectory(outputDirectory); }
|
||||
|
||||
WmarkedImage? resultedImage = null;
|
||||
using (var targetImage = Image.Load(imagePath))
|
||||
using (var watermarkImage = Image.Load(watermark.ImagePath))
|
||||
{
|
||||
var scaledWmWidth = (int)Math.Round(watermarkImage.Width * watermark.Scale);
|
||||
var scaledWmHeight = (int)Math.Round(watermarkImage.Height * watermark.Scale);
|
||||
watermarkImage.Mutate(x => x.Resize(new Size(scaledWmWidth, scaledWmHeight)));
|
||||
|
||||
using (var markedImage = targetImage.Clone(ctx => this.ApplyScalingWaterMarkImage(ctx, watermark, watermarkImage, targetImage)))
|
||||
{
|
||||
resultedImage = new WmarkedImage(markedImage, outputDirectory + Path.DirectorySeparatorChar + Path.GetFileName(imagePath));
|
||||
markedImage.Save(resultedImage.Path);
|
||||
}
|
||||
}
|
||||
return resultedImage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies a text watermark to a single image.
|
||||
/// </summary>
|
||||
/// <param name="imagePath">Path to source image file.</param>
|
||||
/// <param name="outputDirectory">Output directory for processed image.</param>
|
||||
/// <param name="watermark">Text watermark configuration.</param>
|
||||
/// <returns>Processed image information or null on failure.</returns>
|
||||
/// <exception cref="FileNotFoundException">Thrown when source image is missing.</exception>
|
||||
public WmarkedImage? ProcessImage(string imagePath, string outputDirectory, TextWatermark watermark)
|
||||
{
|
||||
if(!File.Exists(imagePath)) { throw new FileNotFoundException("Source file not found!", imagePath); }
|
||||
if (!Directory.Exists(outputDirectory)) { Directory.CreateDirectory(outputDirectory); }
|
||||
|
||||
WmarkedImage? resultedImage = null;
|
||||
using (var targetImage = Image.Load(imagePath))
|
||||
{
|
||||
using (var markedImage = targetImage.Clone(ctx => this.ApplyScalingWaterMarkText(ctx, watermark)))
|
||||
{
|
||||
resultedImage = new WmarkedImage(markedImage, outputDirectory + Path.DirectorySeparatorChar + Path.GetFileName(imagePath));
|
||||
markedImage.Save(resultedImage.Path);
|
||||
}
|
||||
}
|
||||
return resultedImage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates origin point for text watermark based on position and size.
|
||||
/// </summary>
|
||||
/// <param name="width">Target image width.</param>
|
||||
/// <param name="height">Target image height.</param>
|
||||
/// <param name="watermarkSize">Watermark text size.</param>
|
||||
/// <param name="position">Position on target image.</param>
|
||||
/// <returns>Calculated origin point coordinates.</returns>
|
||||
private PointF CalcWatermarkOrigin(int width, int height, float watermarkSize, ImagePosition position)
|
||||
{
|
||||
var origin = new PointF(0, 0);
|
||||
//Static value 1 pt is 72 px per inch
|
||||
var pixelsPerInch = 72;
|
||||
var wmHeight = watermarkSize / pixelsPerInch;
|
||||
|
||||
switch (position)
|
||||
{
|
||||
case ImagePosition.TopLeft:
|
||||
origin = new PointF(watermarkSize / 2, wmHeight / 2);
|
||||
break;
|
||||
case ImagePosition.TopCenter:
|
||||
origin = new PointF(width / 2, wmHeight / 2);
|
||||
break;
|
||||
case ImagePosition.TopRight:
|
||||
origin = new PointF(width - watermarkSize * 2, wmHeight / 2);
|
||||
break;
|
||||
case ImagePosition.CenterLeft:
|
||||
origin = new PointF(watermarkSize / 2, height / 2.5f);
|
||||
break;
|
||||
case ImagePosition.Center:
|
||||
origin = new PointF(width / 2, height / 2.5f);
|
||||
break;
|
||||
case ImagePosition.CenterRight:
|
||||
origin = new PointF(width - watermarkSize * 2, height / 2.5f);
|
||||
break;
|
||||
case ImagePosition.BottomLeft:
|
||||
origin = new PointF(watermarkSize / 2, height - watermarkSize * 2);
|
||||
break;
|
||||
case ImagePosition.BottomCenter:
|
||||
origin = new PointF(width / 2, height - watermarkSize * 2);
|
||||
break;
|
||||
case ImagePosition.BottomRight:
|
||||
origin = new PointF(width - watermarkSize * 2, height - watermarkSize * 2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return origin;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates origin point for image watermark based on position and dimensions.
|
||||
/// </summary>
|
||||
/// <param name="width">Target image width.</param>
|
||||
/// <param name="height">Target image height.</param>
|
||||
/// <param name="wmWidth">Watermark image width.</param>
|
||||
/// <param name="wmHeight">Watermark image height.</param>
|
||||
/// <param name="position">Position on target image.</param>
|
||||
/// <returns>Calculated origin point coordinates.</returns>
|
||||
private Point CalcWatermarkOrigin(int width, int height, int wmWidth,int wmHeight, ImagePosition position)
|
||||
{
|
||||
var origin = new Point(0, 0);
|
||||
|
||||
var wmPaddingX = width - wmWidth;
|
||||
var paddingSide = wmPaddingX / 2;
|
||||
|
||||
switch (position)
|
||||
{
|
||||
case ImagePosition.TopLeft:
|
||||
origin = new Point(wmWidth / 2, wmHeight / 2);
|
||||
break;
|
||||
case ImagePosition.TopCenter:
|
||||
origin = new Point((int)paddingSide, wmHeight / 2);
|
||||
break;
|
||||
case ImagePosition.TopRight:
|
||||
origin = new Point(width - wmWidth * 2, wmHeight / 2);
|
||||
break;
|
||||
case ImagePosition.CenterLeft:
|
||||
origin = new Point(wmWidth / 2, height / 2);
|
||||
break;
|
||||
case ImagePosition.Center:
|
||||
origin = new Point((int)paddingSide, (int)(height / 2));
|
||||
break;
|
||||
case ImagePosition.CenterRight:
|
||||
origin = new Point(width - wmWidth * 2, height / 2);
|
||||
break;
|
||||
case ImagePosition.BottomLeft:
|
||||
origin = new Point(wmWidth / 2, height - wmHeight);
|
||||
break;
|
||||
case ImagePosition.BottomCenter:
|
||||
origin = new Point((int)paddingSide, height - wmHeight);
|
||||
break;
|
||||
case ImagePosition.BottomRight:
|
||||
origin = new Point(width - wmWidth * 2, height - wmHeight);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return origin;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines horizontal alignment based on watermark position.
|
||||
/// </summary>
|
||||
/// <param name="imagePosition">Watermark position on image.</param>
|
||||
/// <returns>Corresponding horizontal alignment setting.</returns>
|
||||
private HorizontalAlignment HorizontalAlignmentFromPosition(ImagePosition imagePosition)
|
||||
{
|
||||
switch (imagePosition)
|
||||
{
|
||||
case ImagePosition.TopCenter:
|
||||
return HorizontalAlignment.Center;
|
||||
break;
|
||||
case ImagePosition.Center:
|
||||
return HorizontalAlignment.Center;
|
||||
break;
|
||||
case ImagePosition.BottomCenter:
|
||||
return HorizontalAlignment.Center;
|
||||
break;
|
||||
}
|
||||
return HorizontalAlignment.Left;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies text watermark to image with automatic scaling and positioning.
|
||||
/// </summary>
|
||||
/// <param name="processingContext">Image processing context.</param>
|
||||
/// <param name="watermark">Text watermark configuration.</param>
|
||||
/// <returns>Processing context with applied watermark.</returns>
|
||||
private IImageProcessingContext ApplyScalingWaterMarkText(IImageProcessingContext processingContext, TextWatermark watermark)
|
||||
{
|
||||
Size imgSize = processingContext.GetCurrentSize();
|
||||
FontRectangle size = TextMeasurer.MeasureSize(watermark.Text, new TextOptions(watermark.Font));
|
||||
|
||||
// Find out how much we need to scale the text to fill the space (up or down)
|
||||
float scalingFactor = Math.Min(imgSize.Width / size.Width, imgSize.Height / size.Height);
|
||||
|
||||
// Create a new font
|
||||
Font scaledFont = new Font(watermark.Font, scalingFactor / 16 * (watermark.Font.Size * watermark.Scale));
|
||||
ImagePosition[] centerImagePositions = { ImagePosition.CenterLeft, ImagePosition.CenterRight, ImagePosition.Center };
|
||||
//processingContext.SetGraphicsOptions(new GraphicsOptions { AlphaCompositionMode = SixLabors.ImageSharp.PixelFormats.PixelAlphaCompositionMode.Clear});
|
||||
//If set, apply backround color
|
||||
if (watermark.BackroundColor != null)
|
||||
processingContext.BackgroundColor((Color)watermark.BackroundColor);
|
||||
|
||||
var textOptions = new RichTextOptions(scaledFont)
|
||||
{
|
||||
ColorFontSupport = ColorFontSupport.MicrosoftColrFormat,
|
||||
Origin = CalcWatermarkOrigin(imgSize.Width, imgSize.Height, scaledFont.Size, watermark.Position),
|
||||
HorizontalAlignment = HorizontalAlignmentFromPosition(watermark.Position),
|
||||
VerticalAlignment = VerticalAlignment.Top,
|
||||
};
|
||||
|
||||
if (watermark.Pave)
|
||||
{
|
||||
foreach (ImagePosition position in (ImagePosition[])Enum.GetValues(typeof(ImagePosition)))
|
||||
{
|
||||
textOptions.Origin = CalcWatermarkOrigin(imgSize.Width, imgSize.Height, scaledFont.Size, position);
|
||||
textOptions.HorizontalAlignment = HorizontalAlignmentFromPosition(position);
|
||||
processingContext.DrawText(textOptions, watermark.Text, watermark.Color);
|
||||
}
|
||||
return processingContext;
|
||||
}
|
||||
return processingContext
|
||||
.DrawText(textOptions, watermark.Text, watermark.Color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies image watermark to target image with scaling and positioning.
|
||||
/// </summary>
|
||||
/// <param name="processingContext">Image processing context.</param>
|
||||
/// <param name="watermark">Image watermark configuration.</param>
|
||||
/// <param name="watermarkImage">Watermark image instance.</param>
|
||||
/// <param name="targetImage">Target image being processed.</param>
|
||||
/// <returns>Processing context with applied watermark.</returns>
|
||||
private IImageProcessingContext ApplyScalingWaterMarkImage(IImageProcessingContext processingContext, ImageWatermark watermark, Image watermarkImage, Image targetImage)
|
||||
{
|
||||
var scaleFactor = 1f;
|
||||
if (targetImage.Width > targetImage.Height)
|
||||
scaleFactor = (float)targetImage.Width / targetImage.Height;
|
||||
else
|
||||
scaleFactor = (float) targetImage.Height / targetImage.Width;
|
||||
|
||||
var wmPaddingX = (targetImage.Width - watermarkImage.Width) / 2;
|
||||
var wmPaddingY = (targetImage.Height - watermarkImage.Height) / 2;
|
||||
//scaleFactor = 1;
|
||||
var minWmPadding = 50;
|
||||
var scaledWmWidth = wmPaddingX > minWmPadding && wmPaddingY > minWmPadding
|
||||
? watermarkImage.Width * scaleFactor
|
||||
: watermarkImage.Width / scaleFactor;
|
||||
var scaledWmHeight = wmPaddingX > minWmPadding && wmPaddingY > minWmPadding
|
||||
? watermarkImage.Height * scaleFactor
|
||||
: watermarkImage.Height / scaleFactor;
|
||||
|
||||
//If set, apply backround color
|
||||
if (watermark.BackroundColor != null)
|
||||
processingContext.BackgroundColor((Color)watermark.BackroundColor);
|
||||
|
||||
watermarkImage.Mutate(x => x.Resize(new Size((int)scaledWmWidth, (int)scaledWmHeight)));
|
||||
var wmPositionOrigin = CalcWatermarkOrigin(targetImage.Width, targetImage.Height, watermarkImage.Width, watermarkImage.Height, watermark.Position);
|
||||
|
||||
if (watermark.Pave)
|
||||
{
|
||||
foreach (ImagePosition position in (ImagePosition[])Enum.GetValues(typeof(ImagePosition)))
|
||||
{
|
||||
wmPositionOrigin = CalcWatermarkOrigin(targetImage.Width, targetImage.Height, watermarkImage.Width, watermarkImage.Height, position);
|
||||
try
|
||||
{
|
||||
processingContext.DrawImage(watermarkImage, wmPositionOrigin, watermark.Opacity);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.ToString());
|
||||
}
|
||||
}
|
||||
return processingContext;
|
||||
}
|
||||
|
||||
return processingContext.DrawImage(watermarkImage, wmPositionOrigin, watermark.Opacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
Watermark.Net/src/WatermarkNet.Enums/ImagePosition.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Watermark.Net.src.WatermarkNet.Enums
|
||||
{
|
||||
public enum ImagePosition
|
||||
{
|
||||
TopLeft = 0,
|
||||
TopCenter = 1,
|
||||
TopRight = 2,
|
||||
CenterLeft = 3,
|
||||
Center = 4,
|
||||
CenterRight = 5,
|
||||
BottomLeft = 6,
|
||||
BottomCenter = 7,
|
||||
BottomRight = 8
|
||||
}
|
||||
}
|
||||
75
Watermark.Net/src/WatermarkNet.Types/ImageWatermark.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Watermark.Net.src.WatermarkNet.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a configurable image-based watermark with scaling, positioning, and transparency controls.
|
||||
/// </summary>
|
||||
public class ImageWatermark : WatermarkImageBase
|
||||
{
|
||||
private string _imagePath;
|
||||
private float? _opacity;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the absolute path to the watermark image file.
|
||||
/// Supported formats: PNG, JPEG, BMP, GIF.
|
||||
/// </summary>
|
||||
/// <exception cref="FileNotFoundException">
|
||||
/// Thrown when setting a value that doesn't point to an existing file.
|
||||
/// </exception>
|
||||
public string ImagePath
|
||||
{
|
||||
get => _imagePath;
|
||||
set
|
||||
{
|
||||
if (!File.Exists(value))
|
||||
throw new FileNotFoundException("Watermark image not found", value);
|
||||
|
||||
_imagePath = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the transparency level of the watermark.
|
||||
/// Range: 0.0 (fully transparent) to 1.0 (completely opaque).
|
||||
/// Default: 1.0
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when value is outside the 0.0-1.0 range.
|
||||
/// </exception>
|
||||
public float Opacity
|
||||
{
|
||||
get => _opacity ?? 1f;
|
||||
set
|
||||
{
|
||||
if (value < 0 || value > 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(Opacity),
|
||||
"Opacity must be between 0.0 and 1.0");
|
||||
|
||||
_opacity = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the scale factor applied to the watermark image relative to the target image.
|
||||
/// Default: 0.2 (20% of target image width)
|
||||
/// </summary>
|
||||
public float Scale { get; set; } = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ImageWatermark class with specified image path.
|
||||
/// </summary>
|
||||
/// <param name="imagePath">Path to the watermark image file.</param>
|
||||
public ImageWatermark(string imagePath) : this()
|
||||
{
|
||||
ImagePath = imagePath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ImageWatermark class with default values.
|
||||
/// </summary>
|
||||
public ImageWatermark() { }
|
||||
|
||||
}
|
||||
}
|
||||
13
Watermark.Net/src/WatermarkNet.Types/SourceImage.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using SixLabors.ImageSharp;
|
||||
|
||||
namespace Watermark.Net.src.WatermarkNet.Types
|
||||
{
|
||||
internal class SourceImage
|
||||
{
|
||||
private string _path;
|
||||
private Image _image;
|
||||
|
||||
public Image Image => _image;
|
||||
public String Path => _path;
|
||||
}
|
||||
}
|
||||
83
Watermark.Net/src/WatermarkNet.Types/TextWatermark.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using SixLabors.Fonts;
|
||||
using SixLabors.ImageSharp;
|
||||
|
||||
namespace Watermark.Net.src.WatermarkNet.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a configurable text-based watermark with styling, positioning, and rendering options.
|
||||
/// </summary>
|
||||
public class TextWatermark : WatermarkImageBase
|
||||
{
|
||||
private string _text;
|
||||
private Font _font;
|
||||
private float _padding;
|
||||
private Color _color;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the color of the text watermark.
|
||||
/// Default: White (#FFFFFF)
|
||||
/// </summary>
|
||||
public Color Color
|
||||
{
|
||||
get => _color;
|
||||
set => _color = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text content for the watermark.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentException">Thrown when value is null or whitespace.</exception>
|
||||
public string Text
|
||||
{
|
||||
get => _text;
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
throw new ArgumentException("Watermark text cannot be empty", nameof(Text));
|
||||
_text = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the font used to render the text watermark.
|
||||
/// Default: Arial 12pt
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentNullException">Thrown when value is null.</exception>
|
||||
public Font Font
|
||||
{
|
||||
get => _font;
|
||||
set => _font = value ?? throw new ArgumentNullException(nameof(Font));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the padding space around the text watermark in pixels.
|
||||
/// Default: 10px
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when value is negative.</exception>
|
||||
public float Padding
|
||||
{
|
||||
get => _padding;
|
||||
set
|
||||
{
|
||||
if (value < 0) throw new ArgumentOutOfRangeException(nameof(Padding), "Padding cannot be negative");
|
||||
_padding = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the rotation angle for the text watermark in degrees.
|
||||
/// Default: 0 (no rotation)
|
||||
/// </summary>
|
||||
public float Rotation { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the TextWatermark class with default values.
|
||||
/// </summary>
|
||||
public TextWatermark()
|
||||
{
|
||||
_color = Color.White;
|
||||
_font = SystemFonts.CreateFont("Arial", 12);
|
||||
_padding = 10f;
|
||||
}
|
||||
}
|
||||
}
|
||||
60
Watermark.Net/src/WatermarkNet.Types/WatermarkImageBase.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using SixLabors.ImageSharp;
|
||||
using Watermark.Net.src.WatermarkNet.Enums;
|
||||
|
||||
namespace Watermark.Net.src.WatermarkNet.Types
|
||||
{
|
||||
public class WatermarkImageBase
|
||||
{
|
||||
protected ImagePosition _postion;
|
||||
protected float _scale;
|
||||
protected int _rotateAngle;
|
||||
protected bool _pave;
|
||||
protected Color? _backround;
|
||||
|
||||
public ImagePosition Position
|
||||
{
|
||||
get { return _postion; }
|
||||
set
|
||||
{
|
||||
_postion= value;
|
||||
}
|
||||
}
|
||||
|
||||
public float Scale
|
||||
{
|
||||
get { return _scale; }
|
||||
set
|
||||
{
|
||||
if(value <= 0) { throw new ArgumentOutOfRangeException("Scale", "Image scale can not be less or equal zero."); }
|
||||
_scale= value;
|
||||
}
|
||||
}
|
||||
|
||||
public int RotateAngle
|
||||
{
|
||||
get { return _rotateAngle; }
|
||||
set
|
||||
{
|
||||
if (Math.Abs(value) > 180) { throw new ArgumentOutOfRangeException("RotateAngle", "Image rotate angle can not be larger than 180°."); }
|
||||
_rotateAngle= value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Pave
|
||||
{
|
||||
get { return _pave; }
|
||||
set { _pave = value; }
|
||||
}
|
||||
|
||||
public Color? BackroundColor
|
||||
{
|
||||
get { return _backround; }
|
||||
set { _backround = value; }
|
||||
}
|
||||
|
||||
public WatermarkImageBase()
|
||||
{
|
||||
_scale= 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Watermark.Net/src/WatermarkNet.Types/WmarkedImage.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using SixLabors.ImageSharp;
|
||||
|
||||
namespace Watermark.Net.src.WatermarkNet.Types
|
||||
{
|
||||
public class WmarkedImage
|
||||
{
|
||||
public string Path { get; }
|
||||
public Image Image { get; }
|
||||
public WmarkedImage(Image image, string path)
|
||||
{
|
||||
this.Image = image;
|
||||
this.Path= path;
|
||||
}
|
||||
}
|
||||
}
|
||||
69
Watrmark.Net CLI/Extensions.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Watrmark.Net_CLI
|
||||
{
|
||||
internal class Extensions
|
||||
{
|
||||
private static void ClearRow(int row)
|
||||
{
|
||||
Console.SetCursorPosition(0, row);
|
||||
Console.Write(new String(' ', Console.WindowWidth));
|
||||
Console.SetCursorPosition(0, row);
|
||||
}
|
||||
|
||||
private static void DrawTextProgressBar(double percentComplite)
|
||||
{
|
||||
int totalChunks = Console.WindowWidth / 2;
|
||||
|
||||
//draw empty progress bar
|
||||
Console.CursorLeft = 0;
|
||||
Console.Write("["); //start
|
||||
Console.CursorLeft = totalChunks + 1;
|
||||
Console.Write("]"); //end
|
||||
Console.CursorLeft = 1;
|
||||
|
||||
int numChunksComplete = Convert.ToInt16(totalChunks * percentComplite);
|
||||
|
||||
//draw completed chunks
|
||||
Console.BackgroundColor = ConsoleColor.Green;
|
||||
Console.Write("".PadRight(numChunksComplete));
|
||||
|
||||
//draw incomplete chunks
|
||||
Console.BackgroundColor = ConsoleColor.Gray;
|
||||
Console.Write("".PadRight(totalChunks - numChunksComplete));
|
||||
|
||||
//draw totals
|
||||
Console.CursorLeft = totalChunks + 5;
|
||||
Console.BackgroundColor = ConsoleColor.Black;
|
||||
}
|
||||
|
||||
public static void DrawStats(string imagePath, int filesComplite, int filesTotal, Stopwatch stopwatch)
|
||||
{
|
||||
var complitePercent = Convert.ToDouble(filesComplite) / filesTotal;
|
||||
var operationsPerSecond = Convert.ToDouble(filesComplite) / stopwatch.Elapsed.TotalSeconds;
|
||||
|
||||
Console.CursorVisible = false;
|
||||
ClearRow(0);
|
||||
Console.WriteLine($"Processed file: {imagePath}");
|
||||
DrawTextProgressBar(complitePercent);
|
||||
Console.Write($"{Math.Round(complitePercent * 100, 0)}% \t");
|
||||
Console.WriteLine($"{filesComplite} of {filesTotal}");
|
||||
ClearRow(2);
|
||||
Console.WriteLine($"{Math.Round(operationsPerSecond, 0)} per second");
|
||||
}
|
||||
|
||||
public static void DrawCompliteStats(TimeSpan elapsedTime)
|
||||
{
|
||||
Console.Clear();
|
||||
Console.SetCursorPosition(0, 0);
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine($"Work complite in {elapsedTime.Minutes} min. {elapsedTime.TotalSeconds} sec.");
|
||||
Console.ResetColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
91
Watrmark.Net CLI/Program.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using CommandLine;
|
||||
using Watermark.Net.src.WatermarkNet.Types;
|
||||
using System.Diagnostics;
|
||||
using Watermark.Net.src.WatermarkNet.Core;
|
||||
using Watrmark.Net_CLI.Watermakr.Net.CLI.Enums;
|
||||
using Watrmark.Net_CLI.Watermark.Net.CLI.Models;
|
||||
using Watrmark.Net_CLI.Watermak.Net.CLI.Constants;
|
||||
using Watrmark.Net_CLI;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
Parser.Default.ParseArguments<ConsoleOptions>(args)
|
||||
.WithParsed<ConsoleOptions>(option => {
|
||||
switch (option.WatermarkType)
|
||||
{
|
||||
case WatermarkType.Image:
|
||||
if (option.FilePath != null)
|
||||
ProccessSingleFile(option);
|
||||
if (option.DirectoryPath != null)
|
||||
ProccessDirectory(option);
|
||||
break;
|
||||
case WatermarkType.Text:
|
||||
if (option.FilePath != null)
|
||||
ProccessSingleText(option);
|
||||
else
|
||||
ProccessDirectoryText(option);
|
||||
break;
|
||||
}
|
||||
|
||||
})
|
||||
.WithNotParsed(error => { });
|
||||
|
||||
static void ProccessSingleFile(ConsoleOptions options)
|
||||
{
|
||||
|
||||
}
|
||||
static void ProccessDirectory(ConsoleOptions options)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void ProccessSingleText(ConsoleOptions options)
|
||||
{
|
||||
|
||||
}
|
||||
static void ProccessDirectoryText(ConsoleOptions options)
|
||||
{
|
||||
if (options.WatermarkText == null || options.WatermarkText == string.Empty)
|
||||
throw new ArgumentNullException("Watermark text can not be null");
|
||||
if(options.DirectoryPath == null || !Directory.Exists(options.DirectoryPath))
|
||||
throw new ArgumentNullException("Specified files directory not found");
|
||||
if (options.OutputPath == null || !Directory.Exists(options.OutputPath))
|
||||
throw new ArgumentNullException("Specified output directory not found");
|
||||
|
||||
var directoryFiles = Directory.GetFiles(options.DirectoryPath);
|
||||
|
||||
var filesTotal = directoryFiles.Length;
|
||||
var chunkSize = filesTotal / (options.ThreadsNumber ?? Environment.ProcessorCount);
|
||||
var filesChunks = directoryFiles.ToList().Chunk(chunkSize < 1 ? 1: chunkSize);
|
||||
var filesComplite = 0;
|
||||
|
||||
var watermark = new TextWatermark{
|
||||
Text = options.WatermarkText,
|
||||
Color = options.WatermarkColor ?? Constans.DefaultTextColor,
|
||||
Position = options.WatermarkPositon ?? Constans.DefaultWatermarkPosition,
|
||||
BackroundColor = options.WatermarkBackround ?? Constans.DefaultBackroundColor,
|
||||
Font = Constans.DefaultWatermarkFont,
|
||||
Scale = options.WatermarkScale ?? Constans.DefaultWatermarkScale
|
||||
};
|
||||
var watermarker = new Watermarker();
|
||||
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
Console.Clear();
|
||||
|
||||
Parallel.ForEach(filesChunks, new ParallelOptions { MaxDegreeOfParallelism = options.ThreadsNumber ?? Environment.ProcessorCount }, chunk =>
|
||||
{
|
||||
foreach (var imagePath in chunk)
|
||||
{
|
||||
var resultedImage = watermarker.ProcessImage(imagePath, options.OutputPath, watermark);
|
||||
|
||||
lock (stopwatch)
|
||||
{
|
||||
Extensions.DrawStats(resultedImage.Path, ++filesComplite, filesTotal, stopwatch);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
stopwatch.Stop();
|
||||
Extensions.DrawCompliteStats(stopwatch.Elapsed);
|
||||
}
|
||||
8
Watrmark.Net CLI/Properties/launchSettings.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"profiles": {
|
||||
"Watrmark.Net CLI": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "--type Text --text Lorem -p Center -o \"Z:\\Загрузки\\testout\" -d \"Z:\\Загрузки\\test\\1\" --scale 2 --threads 8"
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Watrmark.Net CLI/Watermak.Net.CLI.Constants/Constans.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using SixLabors.Fonts;
|
||||
using Watermark.Net.src.WatermarkNet.Enums;
|
||||
|
||||
namespace Watrmark.Net_CLI.Watermak.Net.CLI.Constants
|
||||
{
|
||||
internal class Constans
|
||||
{
|
||||
public static readonly SixLabors.ImageSharp.Color DefaultTextColor = SixLabors.ImageSharp.Color.LightGray;
|
||||
public static readonly SixLabors.ImageSharp.Color DefaultBackroundColor = SixLabors.ImageSharp.Color.White;
|
||||
public static readonly ImagePosition DefaultWatermarkPosition = ImagePosition.Center;
|
||||
public static readonly Font DefaultWatermarkFont = SystemFonts.CreateFont("Tahoma", 14);
|
||||
public static readonly float DefaultWatermarkScale = 1;
|
||||
}
|
||||
}
|
||||
42
Watrmark.Net CLI/Watermakr.Net.CLI.Enums/ConsoleOptions.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Watrmark.Net_CLI.Watermark.Net.CLI.Models;
|
||||
using Watermark.Net.src.WatermarkNet.Enums;
|
||||
using CommandLine;
|
||||
|
||||
namespace Watrmark.Net_CLI.Watermakr.Net.CLI.Enums
|
||||
{
|
||||
internal class ConsoleOptions
|
||||
{
|
||||
[Option("type", Required = true, HelpText = "")]
|
||||
public WatermarkType WatermarkType { get; set; }
|
||||
|
||||
[Option('f', "file", Required = false, HelpText = "")]
|
||||
public string? FilePath { get; set; }
|
||||
|
||||
[Option('d', "directory", Group = "wmoptions", HelpText = "")]
|
||||
public string? DirectoryPath { get; set; }
|
||||
|
||||
[Option('w', "watermark", Group = "wmoptions", HelpText = "")]
|
||||
public string? WatermarkPath { get; set; }
|
||||
|
||||
[Option('o', "output", Required = true, HelpText = "")]
|
||||
public string? OutputPath { get; set; }
|
||||
|
||||
[Option("text", Group = "wmoptions", HelpText = "")]
|
||||
public string? WatermarkText { get; set; }
|
||||
|
||||
[Option('c', "color", Required = false, HelpText = "")]
|
||||
public SixLabors.ImageSharp.Color? WatermarkColor { get; set; }
|
||||
|
||||
[Option('b', "wmbackroud", Required = false, HelpText = "")]
|
||||
public SixLabors.ImageSharp.Color? WatermarkBackround { get; set; }
|
||||
|
||||
[Option('s', "scale", Required = false, HelpText = "")]
|
||||
public float? WatermarkScale { get; set; }
|
||||
|
||||
[Option('p', "position", Required = false, HelpText = "")]
|
||||
public ImagePosition? WatermarkPositon { get; set; }
|
||||
|
||||
[Option("threads", Required = false, HelpText = "")]
|
||||
public int? ThreadsNumber { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Watrmark.Net_CLI.Watermark.Net.CLI.Models
|
||||
{
|
||||
internal enum WatermarkType
|
||||
{
|
||||
Image,
|
||||
Text
|
||||
}
|
||||
}
|
||||
21
Watrmark.Net CLI/Watrmark.Net CLI.csproj
Normal file
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RootNamespace>Watrmark.Net_CLI</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Copyright>Geckon01</Copyright>
|
||||
<AssemblyVersion>0.24.7.1</AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Watermark.NET\Watermark.Net.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||