Closed wuyu8512 closed 9 months ago
We’ll need an input image that triggers the crash.
This is very odd code btw? Why are you creating that byte[]
and copying to it?
This error does not appear in the same picture, but occurs randomly in tens of thousands of pictures. Many steps are omitted here. Even without these steps, this code will generate errors.
@br3aker I'm a little confused following this code so will need your assistance diagnosing if I can?
I'm assuming the unused property paddedPixelsCount
is meaningless? I'm not sure how we can go out of bounds here given that the lanes are created as a multiple of that width.
@wuyu8512 Are you operating on image
or outImage
? I'm still struggling to understand why you are wrapping memory, the buffer never gets set to null
does it?
If you need direct pixel access for your operations. This is the best and secure way.
image.ProcessPixelRows(accessor =>
{
for (int y = 0; y < accessor.Height; y++)
{
Span<Bgra32> row = accessor.GetRowSpan(y);
Span<byte> byteRow = MemoryMarshal.Cast<Bgra32, byte>(row);
// Manipulate the row bytes directly.
}
});
@wuyu8512 Are you operating on
image
oroutImage
?
i was operating on image
I'm still struggling to understand why you are wrapping memory
I hope to be compatible with both ImageSharp and SkiaSharp, so getting all the data and processing it will make it easier for me to write a universal library
the buffer never gets set to
null
does it?
Yes, I updated all the code
Assuming that the object of the Save method is changed to inputImage
object, the error will not occur, so it is suspected that something unexpected happened to WrapMemory.
Save doesn't mutate the image. It only encodes it.
I can't see where pixels
is set to null in your sample. I'm assuming then that you are passing the pixels
buffer in its entirety to your custom filter methods to operate upon before saving?
WrapMemory
depends on the buffer being available and its dimensions unchanged for the lifetime of the operation. Any change there will lead to issues.
You should create a 2D buffer abstraction that allows per-row access instead of using the array for your custom methods. That would be the only type you implement for both ImageSharp and SkiaSharp.
Save doesn't mutate the image. It only encodes it.
Sorry, my express was not good, I modify my express again
I can't see where pixels is set to null in your sample. I'm assuming then that you are passing the pixels buffer in its entirety to your custom filter methods to operate upon before saving?
Yes, the pixels buffer will never set null
, This code can be reproduced directly
You should create a 2D buffer abstraction that allows per-row access instead of using the array for your custom methods. That would be the only type you implement for both ImageSharp and SkiaSharp.
i will try
After forcing the use of Webp, the problem no longer occurs
var filePath = Path.Combine(imgaeBasePath, path);
using var inputImage = await SixLabors.ImageSharp.Image.LoadAsync<Bgra32>(filePath);
var pixel = new byte[inputImage.Height * inputImage.Width * Unsafe.SizeOf<Bgra32>()];
inputImage.CopyPixelDataTo(pixel);
using var outputImage = SixLabors.ImageSharp.Image.WrapMemory<Bgra32>(pixel, inputImage.Width, inputImage.Height);
var stream = new MemoryStream();
await outputImage.SaveAsWebpAsync(stream, new SixLabors.ImageSharp.Formats.Webp.WebpEncoder() { Quality = 95 });
stream.Position = 0;
return Results.File(stream, SixLabors.ImageSharp.Formats.Webp.WebpFormat.Instance.DefaultMimeType);
I suspect that WrapMemory
is not related to the issue at all but just to check, can you see if you can replicate using JpegEncoder
only and no wrapping?
If so, please let me know and also let me know the dimension range of the images you are using?
if use LoadPixelData
Replace WrapMemory
, Problem no longer recurs
my image are most around 10001500 and 500 750(md version)
Since this issue only occurs in my production environment, I'm sorry I can't always test it
Is this sample (but using the jpeg encoder) enough to trigger the issue?
https://github.com/SixLabors/ImageSharp/issues/2595#issuecomment-1833125178
Is this sample (but using the jpeg encoder) enough to trigger the issue?
yes
Isn't it the source
that has to be padded by 3 bytes actually?
I need to refresh my memory about the SIMD packing/unpacking algorithms, but I would think this could be a more likely case, assuming a83b3b699a0caac6b6935b7e5e51c10475ae8915 from #2120 implemented the mirror operation of #1462.
In this case UnpackIntoRgbPlanes
would need to operate on a copy of sourceRow
when processing the last row:
This is how it's done in the decoder:
I can repro this without WrapMemory
:
Configuration.Default.MemoryAllocator = new SimpleGcMemoryAllocator();
Parallel.For(0, 10_000, i =>
{
using Image<Bgra32> image = new Image<Bgra32>(Random.Shared.Next(3000) + 1, Random.Shared.Next(3000) + 1);
using MemoryStream stream = new MemoryStream();
image.SaveAsJpeg(stream);
});
This can be further reduced to
Configuration configuration = Configuration.CreateDefaultInstance();
configuration.MemoryAllocator = new SimpleGcMemoryAllocator();
using Image<Bgra32> image = new(configuration, 132, 1606);
using MemoryStream stream = new();
image.SaveAsJpeg(stream);
Prerequisites
DEBUG
andRELEASE
modeImageSharp version
3.0.2
Other ImageSharp packages and versions
No
Environment (Operating system, version and so on)
Ubuntu 22.04.3 LTS
.NET Framework version
.Net 8
Description
Steps to Reproduce
Sorry for my bad English, When big number of requests(about avg 2request/1s), an error will throw, But I can't reproduce it on my local computer
Images
No response