Skip to content

Commit f074af3

Browse files
Replace ImageMagick with ImageSharp for image processing
Refactored the codebase to use SixLabors.ImageSharp instead of ImageMagick for all image processing tasks, including watermarking and GIF frame counting. Removed all OpenCL-related code and updated documentation, comments, and developer notes to reflect the new dependency. Updated global usings and ensured watermark resizing is handled per image to avoid shared state.
1 parent 4d212f3 commit f074af3

2 files changed

Lines changed: 32 additions & 40 deletions

File tree

Add Identity To Content/ImageProcessor.cs

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,14 @@ public static async Task ProcessImagesAsync(List<DroppedObject> imageFiles, stri
1919
// Create the output directory if it does not exist
2020
Directory.CreateDirectory(outputDirectory);
2121

22-
// Enable OpenCL
23-
OpenCL.IsEnabled = true;
24-
// Inform the user if OpenCL is enabled or disabled
25-
// This can be useful for debugging and troubleshooting
26-
// If OpenCL is disabled, some operations may fall back to CPU processing
27-
// If OpenCL is enabled, the GPU will be used for processing
28-
// This can significantly speed up image processing operations
29-
// Note: OpenCL must be supported by the GPU and the drivers for it to work
30-
// This uses a feature of the ImageMagick library to enable OpenCL support
31-
// A ?: ternary operator is used to display a message based on the IsEnabled property
32-
Console.WriteLine($"OpenCL is {(OpenCL.IsEnabled ? "enabled" : "disabled")}.");
33-
3422
// Inform the user which GPU acceleration is enabled
3523
Console.WriteLine($"Available hardware acceleration codec: {GetHardwareAccelerationCodec()}");
3624

3725
// Process each image file in the list
3826
Console.WriteLine("------------------");
3927

4028
// Process each image file in the list
41-
using (var watermark = new MagickImage(watermarkPath))
29+
using (var watermark = Image.Load<Rgba32>(watermarkPath))
4230
{
4331
// Limit the number of concurrent tasks to 8
4432
var tasks = imageFiles.Select(async (imageFile, index) =>
@@ -48,25 +36,34 @@ public static async Task ProcessImagesAsync(List<DroppedObject> imageFiles, stri
4836
throw new ArgumentNullException(nameof(imageFile), "Image file path or name is null");
4937

5038
// Load the image file
51-
using (var image = new MagickImage(imageFile.FullPath))
39+
using (var image = Image.Load<Rgba32>(imageFile.FullPath))
5240
{
5341
// Calculate the maximum dimensions for the watermark
54-
int maxWidth = (int)(image.Width / 3);
55-
int maxHeight = (int)(image.Height / 3);
42+
int maxWidth = image.Width / 3;
43+
int maxHeight = image.Height / 3;
5644

57-
// Resize watermark if it exceeds the 9-grid dimensions
58-
if (watermark.Width > maxWidth || watermark.Height > maxHeight)
45+
// Clone and resize watermark for this image to avoid shared mutation
46+
using var scaledWatermark = watermark.Clone(ctx =>
5947
{
60-
watermark.Resize((uint)maxWidth, (uint)maxHeight);
61-
}
48+
// Resize watermark if it exceeds the 9-grid dimensions
49+
if (watermark.Width > maxWidth || watermark.Height > maxHeight)
50+
{
51+
ctx.Resize(new ResizeOptions
52+
{
53+
Size = new Size(maxWidth, maxHeight),
54+
Mode = ResizeMode.Max
55+
});
56+
}
57+
});
6258

63-
// Composite the watermark onto the image
64-
image.Composite(watermark, Gravity.Southwest, CompositeOperator.Over);
59+
// Composite the watermark onto the image at the bottom-left (Southwest)
60+
var location = new Point(0, image.Height - scaledWatermark.Height);
61+
image.Mutate(ctx => ctx.DrawImage(scaledWatermark, location, 1f));
6562

6663
// Save the image with the watermark
6764
string outputFilePath = Path.Combine(outputDirectory, Path.GetFileName(imageFile.FullPath));
6865
// Write the image to the output directory
69-
await image.WriteAsync(outputFilePath);
66+
await image.SaveAsync(outputFilePath);
7067
}
7168

7269
// Calculate and display progress percentage
@@ -100,12 +97,6 @@ public static async Task ProcessGifsAsync(List<DroppedObject> gifFiles, string w
10097
// foreground colour green
10198
Console.ForegroundColor = ConsoleColor.Green;
10299

103-
// Enable OpenCL for ImageMagick
104-
OpenCL.IsEnabled = true;
105-
// Inform the user if OpenCL is enabled or disabled
106-
// Using a ternary operator to display a message based on the IsEnabled property
107-
Console.WriteLine($"OpenCL is {(OpenCL.IsEnabled ? "enabled" : "disabled")}.");
108-
109100
// reset foreground colour
110101
Console.ResetColor();
111102

@@ -642,16 +633,15 @@ private static void DisplayVideoProgressBar(double progress, int currentFrame, i
642633
/// <param name="gifFilePath">The path to the GIF file.</param>
643634
/// <returns>The number of frames in the GIF file.</returns>
644635
/// <remarks>
645-
/// This method uses the Magick.NET library to load the GIF file and count the number of frames.
636+
/// This method uses the SixLabors.ImageSharp library to load the GIF file and count the number of frames.
646637
/// </remarks>
647-
/// <seealso cref="MagickImageCollection"/>
648638
private static int GetGifFrameCount(string gifFilePath)
649639
{
650-
// Load the GIF file into a MagickImageCollection
651-
using (var collection = new MagickImageCollection(gifFilePath))
640+
// Load the GIF file and count the frames
641+
using (var gif = Image.Load(gifFilePath))
652642
{
653-
// Return the number of frames in the collection
654-
return collection.Count;
643+
// Return the number of frames in the image
644+
return gif.Frames.Count;
655645
}
656646
}
657647

Add Identity To Content/Program.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
global using System.Threading.Tasks;
55
global using System.Linq;
66
global using System.Diagnostics;
7-
//Xabe.FFmpeg and ImageMagick are not included in the .NET SDK, you need to install them using NuGet.
7+
//Xabe.FFmpeg and SixLabors.ImageSharp are not included in the .NET SDK, you need to install them using NuGet.
88
// The using directive for Xabe.FFmpeg does not highlight in Visual Studio, but it is still recognized.
99
global using Xabe.FFmpeg;
10-
global using ImageMagick;
10+
global using SixLabors.ImageSharp;
11+
global using SixLabors.ImageSharp.Processing;
12+
global using SixLabors.ImageSharp.PixelFormats;
1113
global using System.Text.RegularExpressions;
1214

1315
// Developer Notes:
@@ -18,9 +20,9 @@
1820
// Sometimes you may have to manually terminate ffmpeg processes in Task Manager.
1921
// sometimes the gif conversion may only output the converted video,
2022
// you will have to add them back through the process again to add the watermark.
21-
// You need to download ImageMagick and FFmpeg to run this program.
23+
// You need to download FFmpeg to run this program.
2224
// You need to have the watermark.png file in the same directory as the source files.
23-
// The FFmpeg and ImageMagick paths must be placed in the same directory as the executable once it is built, GitHub does not allow uploading these files.
25+
// The FFmpeg path must be placed in the same directory as the executable once it is built, GitHub does not allow uploading these files.
2426
// The program will log errors to error.log and unsupported files to unsupported_files.log.
2527
// Note: this project was built with the assistance of GitHub Copilot X Chat AI.
2628

@@ -37,7 +39,7 @@ namespace AddIdentityToContent
3739
/// <seealso cref="FileProcessor"/>
3840
/// <seealso cref="ImageProcessor"/>
3941
/// <seealso cref="Logger"/>
40-
/// <seealso cref="ImageMagick"/>
42+
/// <seealso cref="SixLabors.ImageSharp"/>
4143
/// <seealso cref="Xabe.FFmpeg"/>
4244
internal class Program
4345
{

0 commit comments

Comments
 (0)