dotnet / dotnet/winforms

System.Drawing.Image.FromStream(...) throws "Parameter is not valid." when Stream.Read does not return full file length

Open
#14,064 0 comments 0 reactions 1 assignee Claimed by @ricardobossan View on GitHub
area-System.Drawing
Dominant language
C#
Stars
4.9k
Forks
1.1k
Avg merge
20h 23m
Merged PRs (30d)
103

Description

This happens when `Image.FromStream(...)` calls `Stream.Read(buffer, offset, count)` - where `count` is the full length of the image file (it calls it a number of times first with a smaller count value) - and less than `count` is returned.

This is a problem with any seekable Stream implementation that "chunks" reads - like downloading large file in multiple parts...

Sample code:

```C#
var file = new System.IO.File.OpenRead("C:\\test.png");
// No problem:
var img = System.Drawing.Image.FromStream(file);

var file2 = new System.IO.File.OpenRead("C:\\test.png");
var strm = new MyStream(file2);
// will throw Exception "Parameter is not valid."
var img2 = System.Drawing.Image.FromStream(strm);

Console.WriteLine("Won't reach this line");

// Custom Stream to simulate .Read returning less than full count
class MyStream(System.IO.Stream src) : System.IO.Stream {
public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite =>false ;
public override long Length => src.Length;
public override long Position { get => src.Position; set => src.Position=value; }
public override void Flush() => throw new NotImplementedException();
public override long Seek(long offset, SeekOrigin origin) => src.Seek(offset, origin);
public override void SetLength(long value) => throw new NotImplementedException();
public override void Write(byte[] buffer, int offset, int count) => throw new NotImplementedException();

// IMPORTANT PART:
const int ChunkSize = 128 * 1024;
public override int Read(byte[] buffer, int offset, int count) {
if (count > ChunkSize) count = ChunkSize;
return src.Read(buffer, offset, count);
}
}
```

Test image:
Image

Possibly related to https://github.com/dotnet/winforms/issues/8824

Using System.Drawing.Common nuget package v. 10.0.0

Proposed solution (not aware of implementation): Use `Stream.ReadExact` instead of `Stream.Read`

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.