'Image.FromStream throws Parameter is not valid error only on linux
I have some Unit Tests made in .net core that checks if the file which is uploaded from angular frontend is actually resized on the backend.
I have a service that is used in the tests, containing following method :
public byte[] ResizeImage(IFormFile formFile)
{
Image imgFromStream;
using (var memStream = new MemoryStream())
{
formFile.CopyTo(memStream);
memStream.Position = 0;
Console.WriteLine("$$$$$$$ LENGTH :" + memStream.Length);
Console.WriteLine("$$$$$$$ CAN READ :" + memStream.CanRead);
->>>>> imgFromStream = System.Drawing.Image.FromStream(memStream, false,false);
Image thumbnail = imgFromStream.GetThumbnailImage(280, 90, () => false, IntPtr.Zero);
var imageByteArray = new byte[0];
using (MemoryStream mStream = new MemoryStream())
{
thumbnail.Save(mStream, ImageFormat.Png);
imageByteArray = mStream.ToArray();
}
imgFromStream.Dispose();
thumbnail.Dispose();
return imageByteArray;
}
}
The issue is that only on Linux machine, the tests are failing from the line with (---->>>). I've tried with ImageConverter, linux has a bad opinion for that too and it is still not working. I'm out of ideas.
StackTrace : at System.Drawing.Image.InitializeFromStream(Stream stream)
at System.Drawing.Image.LoadFromStream(Stream stream, Boolean keepAlive)
at System.Drawing.Image.FromStream(Stream stream, Boolean useEmbeddedColorManagement, Boolean validateImageData)
The method that creates the Image for tests :
public Image ByteArrayToImage(byte[] byteArrayIn)
{
int size = (int)Math.Sqrt(byteArrayIn.Length);
Bitmap bitmap = new Bitmap(size, size, PixelFormat.Format32bppArgb);
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
try
{
for (int rowIndex = 0; rowIndex < bitmapData.Height; ++rowIndex)
Marshal.Copy(byteArrayIn, rowIndex * bitmap.Width, bitmapData.Scan0 + rowIndex * bitmapData.Stride, bitmap.Width);
}
finally
{
bitmap.UnlockBits(bitmapData);
}
return bitmap;
}
And the byteArrayIn
parameter is generated :
private byte[] GenerateImageByteArray(int sizeInMb)
{
Random rnd = new Random();
Byte[] b = new Byte[sizeInMb * 1024 * 1024]; // convert mb to byte
rnd.NextBytes(b);
//This conversion is needed because the GetThumbnail method from the Service will throw an error
//A random generated byte array can not be converted into a thumbnail
//Only if it's from an image
var image = ByteArrayToImage(b);
var imageByteArray = new byte[0];
using (MemoryStream mStream = new MemoryStream())
{
image.Save(mStream, ImageFormat.Png);
imageByteArray=mStream.ToArray();
}
return imageByteArray;
}
Solution 1:[1]
If you want to use System.Drawing.Common
on linux you need to install GDI+ support libraries:
sudo apt install libc6-dev
sudo apt install libgdiplus
Solution 2:[2]
While not specified by the OP, if you are using .NET 6, System.Drawing.Common
is only supported on Linux via a backwards compatibility runtime config setting. It is completely deprecated in .NET 7.
From MSDN:
To use these APIs for cross-platform apps, migrate to one of the following libraries:
Alternatively, you can enable support for non-Windows platforms in .NET 6 by setting the
System.Drawing.EnableUnixSupport
runtime configuration switch totrue
in theruntimeconfig.json
(runtimeconfig.template.json
) file:
{
"configProperties": {
"System.Drawing.EnableUnixSupport": true
}
}
This configuration switch was added to give cross-platform apps that depend heavily on this package time to migrate to more modern libraries. However, non-Windows bugs will not be fixed. In addition, this switch has been removed in .NET 7.
See here for more info - System.Drawing.Common only supported on Windows
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | LazZiya |
Solution 2 | Dave Black |