I'm getting some problems when I try to resize copies of an image multiple times in parallel. I've tried making a console application as simple as possible that demonstrates my issue:
class Program
{
static void Main()
{
var originalFilepath = "C:\\original.png";
var outputPath = "C:\\resized";
Func<int, string> outputFilepath = i => $"{outputPath}\\{i}.png";
var n = 1000;
var width = 100;
var height = 100;
System.IO.Directory.CreateDirectory(outputPath);
using (var originalImage = new MagickImage(originalFilepath))
{
var tasks = new List<Task>();
for (int i=0;i<n;i++)
{
tasks.Add(ResizeAsync(originalImage, width, height, outputFilepath(i)));
}
Task.WhenAll(tasks).Wait();
}
}
static async Task ResizeAsync(MagickImage originalImage, int width, int height, string outputFilepath)
{
await Task.Delay(1);
using (var resizeImage = new MagickImage(originalImage))
{
resizeImage.Resize(width, height);
resizeImage.Write(outputFilepath);
}
}
}
If I run the above code using this image as original image:

I will either get an AccessViolationException or get a number of resized images with artifacts such as:




I'm using Visual Studio 2015 and Magick.NET-Q8-AnyCPU 7.0.7.300
Thanks for creating such a good example. I can reproduce your issue but I have no clue yet what is causing it. Will need to investigate this with a debugger attached. Will get back to you when I have more information.
It turns out that this was a bug in ImagMagick and I just pushed a fix for this to the GIT repository. I will create a new release later this week to resolve this issue.
Awesome! Thank you for the quick response.
@ExplicitlyImplicit I just started a new job on Monday so my focus is on other things at the moment. But I will make sure you get a new release this weekend.
@ExplicitlyImplicit The new release was published yesterday, could you give it another try?
Using build 7.0.7.700 still yields the same kind of artifacts (I tried the console application above).
Could you give it another try with the latest release we have made some more OpenCL improvements.
We have a similar problem, some images turn out completely black (the images are the correct size).
sample code (10k images returns between 20 to 200 all black images depending on the machine):
private static void Main()
{
String[] files = Directory.GetFiles(@"<your path here>", "*.jpg", SearchOption.AllDirectories);
foreach (String file in files)
{
ImagesToProcess.Enqueue(file);
}
List<Thread> threadResize = new List<Thread>();
Thread writeThread = new Thread(WriteWorker);
writeThread.Start();
for (Int32 i = 0; i < Environment.ProcessorCount * 4; i++)
{
Thread resizeThread = new Thread(ResizeWorker);
resizeThread.Start();
threadResize.Add(resizeThread);
}
while (true)
{
if (threadResize.All(thread => thread.ThreadState == ThreadState.Stopped))
{
break;
}
}
Console.WriteLine("done");
Console.ReadKey();
}
private static void ResizeWorker()
{
while (ImagesToProcess.TryDequeue(out String image))
{
using (MagickImage srcImage = new MagickImage(image))
{
MagickGeometry size = new MagickGeometry(400, 400);
srcImage.RenderingIntent = RenderingIntent.Perceptual;
srcImage.Resize(size);
srcImage.Write("<output path here>" + Path.GetFileName(image) + ".jpg");
}
}
}
}
Environment:
So far I have discovered 2 (dirty) fixes:
So it would appear that the resize isn't quite done during the first write.
We moved away from the Q8 versions because of these issues, the only problem so far with Q16 are the black images.
Disabling OpenCL is not a dirty fix. There are just some video cards that don't work properly with OpenCL.
Are you testing against the latest version @GieltjE?
@dlemstra yeah, on a GT730 (2GB) combined with i5-6600k 32GB.
Hi @dlemstra. I see some similar behavior (artifacts, a lot of dark zones) with latest Q8-x64 lib, when trying to resize multiple images in parallel using async tasks (however seems like using single thread works fine)
I'm working in .NET Core 2.0+ env btw
Have you tried disabling OpenCL @ivankarpey?
Hmm, my parallel code not throw this exception:
锘縰sing System;
using System.Threading.Tasks;
namespace Magick.NET.Benchmarks
{
public class Program
{
static void Main()
{
Console.WriteLine("start");
var bm = new MagickBenchmark();
Parallel.For(
0,
1000,
new ParallelOptions
{
MaxDegreeOfParallelism = Environment.ProcessorCount
},
(i) => bm.ResizeJpeg());
Console.WriteLine("end");
Console.ReadKey();
}
}
}
Resize method:
public void ResizeJpeg()
{
using (var image = new MagickImage(Resources.Cover))
{
var width = CalculateWidth(image.Height, image.Width, JpegHeight);
image.Resize(width, JpegHeight);
image.Strip();
image.Quality = 90;
image.Write(GetJpegPath);
}
}
I ran this code with images have different size 1-40mb.