Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MagickImage cannot detect correct image format with ReadAsync #1174

Closed
d2phap opened this issue Apr 9, 2022 · 4 comments
Closed

MagickImage cannot detect correct image format with ReadAsync #1174

d2phap opened this issue Apr 9, 2022 · 4 comments
Milestone

Comments

@d2phap
Copy link
Sponsor

d2phap commented Apr 9, 2022

Magick.NET version

11.1.0 - Magick.NET-Q16-OpenMP-x64

Environment (Operating system, version and so on)

Windows 10 21H2

Description

  • Probably similar to Load image from Stream #422 but happens to both
    <MagickImage>.ReadAsync() and <MagickImageCollection>.ReadAsync() function.
  • I'm using ReadAsync because it supports CancellationToken, and it's convenient to do some quick check before loading entire image file which is time-consuming.
  • Error:
    TIFF directory is missing required "ImageLength" field. `MissingRequired' @ error/tiff.c/TIFFErrors/656
    
  • Sample file: icon256.zip
  • See Step to Reproduce for more details.

Steps to Reproduce

Code produces error:

var filename = @"D:\icon256.ico";

// Some settings
var settings = new MagickReadSettings();

using var imgM = new MagickImage();
// Check something here
// ...
// ...

// read image file async
await imgM.ReadAsync(filename, settings, cancelToken);

// ❌ Error:
// TIFF directory is missing required "ImageLength" field.
// `MissingRequired' @ error/tiff.c/TIFFErrors/656

Code without error:

Solution 1: Directly pass filename to constructor

using var imgM = new MagickImage(filename, settings);

// no error!

Solution 2: Tell what the format is

// Some settings
var settings = new MagickReadSettings() {
    Format = MagickFormat.Ico,
};

using var imgM = new MagickImage();
// Check something here
// ...
// ...

// read image file async
await imgM.ReadAsync(filename, settings, cancelToken);

// no error!

You can access full source code at:
https://github.com/d2phap/ImageGlass/blob/v9/v9/IgCodecs/ImageMagickIgCodec/Main.cs#L493

@dlemstra
Copy link
Owner

Thanks for reporting this I just pushed a fix for this issue that will be resolved in the next release.

@dlemstra dlemstra added this to the 11.1.1 milestone Apr 10, 2022
@d2phap
Copy link
Sponsor Author

d2phap commented May 11, 2022

I hope this fix can be released some time this week, or else I will miss it for ImageGlass 9.0 beta 1 🕊

@d2phap
Copy link
Sponsor Author

d2phap commented May 13, 2022

Hi @dlemstra,

The bug still persists when using MagickImageCollection.ReadAsync() 😅
Sample file: icon256.zip

using var imgColl = new MagickImageCollection();

// ❌ CANNOT detect format
settings.Format = MagickFormat.Ico;
await imgColl.ReadAsync(filename, settings, cancelToken);

// ✅ CAN detect format
await imgColl.ReadAsync(filename, settings, cancelToken);

// ✅ CAN detect format
imgColl.Read(filename, settings);

I checked the MagickImageCollection source code a bit, and found this:
filename is not passed to the AddImages()

public async Task ReadAsync(string fileName, IMagickReadSettings<QuantumType>? readSettings, CancellationToken cancellationToken)
{
Throw.IfNullOrEmpty(nameof(fileName), fileName);
var bytes = await File.ReadAllBytesAsync(fileName, cancellationToken).ConfigureAwait(false);
cancellationToken.ThrowIfCancellationRequested();
Clear();
AddImages(bytes, 0, bytes.Length, readSettings, false);
}

settings.FileName = null;

private void AddImages(ReadOnlySequence<byte> data, IMagickReadSettings<QuantumType>? readSettings, bool ping)
{
if (data.IsSingleSegment)
{
AddImages(data.FirstSpan, readSettings, ping);
return;
}
var settings = CreateSettings(readSettings);
settings.Ping = ping;
settings.FileName = null;
var wrapper = new ReadOnlySequenceWrapper(data);
var reader = new ReadWriteStreamDelegate(wrapper.Read);
var seeker = new SeekStreamDelegate(wrapper.Seek);
var teller = new TellStreamDelegate(wrapper.Tell);
var result = _nativeInstance.ReadStream(settings, reader, seeker, teller);
AddImages(result, settings);
}

@dlemstra
Copy link
Owner

Seems that I only fixed this in the MagickImage class and not in the MagickImageCollection. Just pushed a patch for this and I will publish a new release this weekend for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants