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

Dependency issue with new version of the ImageSharp #426

Open
dejanmauer opened this issue Feb 22, 2024 · 28 comments
Open

Dependency issue with new version of the ImageSharp #426

dejanmauer opened this issue Feb 22, 2024 · 28 comments

Comments

@dejanmauer
Copy link

dejanmauer commented Feb 22, 2024

Let say, I would like to load image (png) from file:
XImage image = XImage.FromFile("d:\\temp\\qrcode.png");

In case I have reference in my project to ImageSharp > 2.1.6 I get this error:

System.MissingMethodException: 'Method not found: 'SixLabors.ImageSharp.Image`1<!!0> SixLabors.ImageSharp.Image.LoadPixelData(Byte[], Int32, Int32)'.'

Can this be fixed to keep compatibiliry with new versions of ImageSharp (3.X)?

@TonyValenti
Copy link

@dejanmauer - lots of folks are running into this issue. I am really hopeful that @ststeiger will enable us to use the latest version of ImageSharp easily.

I've created this branch:
https://github.com/TonyValenti/PdfSharpCore

That enables the latest version of ImageSharp for modern .NET versions and uses the older version for legacy .NET versions.

Here's to hoping @ststeiger incorporates it!

@svenso
Copy link

svenso commented Mar 6, 2024

There is now a security issue on latest working version of image sharp (2.1.6):
GHSA-65x7-c272-7g7r

Edit:
In the mean time, there is a fixed 2.1.7 version available from ImageSharp: https://github.com/SixLabors/ImageSharp/releases/tag/v2.1.7

@johnwc
Copy link

johnwc commented Mar 13, 2024

@ststeiger Can you please comment on all these requests on updating for ImageSharp. This is becoming an issue.

@TonyValenti
Copy link

Later today I'll be submitting a PR that contains everything necessary to resolve this security issue.

@johnwc
Copy link

johnwc commented Mar 13, 2024

Will it include being able to use v3 of ImageSharp. And the bigger question, will @ststeiger respond and approve the PR.

@TonyValenti
Copy link

Yes. V3 for modern .NET and V2 for framework.

We'll have to wait and see if the maintainer of this package accepts it.

@TonyValenti
Copy link

Hi @ststeiger -
I just created this PR:
https://github.com/ststeiger/PdfSharpCore/compare/master...TonyValenti:PdfSharpCore:master?expand=1

Which upgrades various packages, including ImageSharp, to their latest stable, secure versions.

@TonyValenti
Copy link

@johnwc - my PR is here if you want to take a look.

@johnwc
Copy link

johnwc commented Mar 14, 2024

What are the main differences between the two versions of ImageSharpImageSource? The two look almost exactly the same, minus a few method call differences. If that is the case, wouldn't it be better to just make the compile time directives within the few minor differences, rather than duplicate the code for each? I think it would be easier to maintain that way.

@TonyValenti
Copy link

@johnwc -
Here is a screen shot showing the compare:
image

In my experience, when you're dealing with subtle variances like this, you can easily get yourself in trouble by having a single file where you #if things in and out. It is much safer and easier to maintain to branch the file.

@johnwc
Copy link

johnwc commented Mar 14, 2024

It would be better to maintain one file with a few compile time directives, than two files with almost same code. Think of someone else coming in and only changing one file for a security flaw. If it was in the same file, it would be seen and updated at the same time. Also, visual studio makes it very clear on what directive is currently being worked on and debugged with its coloring of the enabled directive. In my 25 years of development, I have never come across an issue of compile time directives being in a file in relation to this version vs that version compiling. The directives make it very clear what is going on.

@TonyValenti
Copy link

That's not a big deal to me either way as long as we can get the maintainer to merge and publish an update.

@Thomas-HG
Copy link

Is there any news on this subject ? We are using this great library but this issue starts to be a big pain on our side :(

Thanks !

@vebaspect
Copy link

Bump. :)

@mtarlac
Copy link

mtarlac commented Mar 30, 2024

same problem here ;(

@tossnet
Copy link

tossnet commented Apr 3, 2024

#421

@balkarov
Copy link

balkarov commented Apr 8, 2024

+1

@robbaman
Copy link

It turns out it's actually pretty easy to work around this by providing a new, ImageSharp 2/3 compatible ImageSource to the ImageSource.ImageSourceImpl static function.

Just create the class:

public class ImageSharp3CompatibleImageSource<TPixel> : ImageSource where TPixel : unmanaged, IPixel<TPixel> {
	public static IImageSource FromImageSharpImage(
		Image<TPixel> image,
		IImageFormat imgFormat,
		int? quality = 75) =>
		new ImageSharpImageSourceImpl<TPixel>("*" + Guid.NewGuid().ToString("B"), image, quality ?? 75, imgFormat is PngFormat);

	protected override IImageSource FromBinaryImpl(
		string name,
		Func<byte[]> imageSource,
		int? quality = 75) {
		Image<TPixel> image = Image.Load<TPixel>(imageSource());
		return new ImageSharpImageSourceImpl<TPixel>(name, image, quality ?? 75, image.Metadata.DecodedImageFormat is PngFormat);
	}

	protected override IImageSource FromFileImpl(string path, int? quality = 75) {
		Image<TPixel> image = Image.Load<TPixel>(path);
		return new ImageSharpImageSourceImpl<TPixel>(path, image, quality ?? 75, image.Metadata.DecodedImageFormat is PngFormat);
	}

	protected override IImageSource FromStreamImpl(
		string name,
		Func<Stream> imageStream,
		int? quality = 75) {
		using (Stream stream = imageStream()) {
			Image<TPixel> image = Image.Load<TPixel>(stream);
			return new ImageSharpImageSourceImpl<TPixel>(name, image, quality ?? 75, image.Metadata.DecodedImageFormat is PngFormat);
		}
	}

	private class ImageSharpImageSourceImpl<TPixel2>(
		string name,
		Image<TPixel2> image,
		int quality,
		bool isTransparent)
		: IImageSource
		where TPixel2 : unmanaged, IPixel<TPixel2> {
		private Image<TPixel2> Image { get; } = image;

		public int Width => Image.Width;

		public int Height => Image.Height;

		public string Name { get; } = name;

		public bool Transparent { get; internal set; } = isTransparent;

		public void SaveAsJpeg(MemoryStream ms) =>
			Image.SaveAsJpeg(ms, new JpegEncoder() {
				Quality = quality
			});

		public void SaveAsPdfBitmap(MemoryStream ms) {
			BmpEncoder encoder = new BmpEncoder() {
				BitsPerPixel = BmpBitsPerPixel.Pixel32
			};
			Image.Save(ms, encoder);
		}
	}
}

And provide it to the static property at application startup (in the Program.cs for instance):

ImageSource.ImageSourceImpl = new ImageSharp3CompatibleImageSource<Rgba32>();

@johnwc
Copy link

johnwc commented Jul 28, 2024

Did anyone else notice that someone just merged an update for dependencies, but did not include any dependency updates for ImageSharp?

@TonyValenti
Copy link

TonyValenti commented Jul 28, 2024 via email

@robbaman
Copy link

Did anyone else notice that someone just merged an update for dependencies, but did not include any dependency updates for ImageSharp?

I assumed it had to do with the new licensing model for ImageSharp and thus wasn't expecting an update... ever.

@johnwc
Copy link

johnwc commented Jul 29, 2024

@robbaman @ststeiger @TonyValenti ImageSharp supposedly already gave the green light to this project for using it under the new license without issue.

@TonyValenti
Copy link

Yes they did but I believe that does not matter to @ststeiger

@johnwc
Copy link

johnwc commented Jul 29, 2024

Yes they did but I believe that does not matter to @ststeiger

Can you point us to where they did?

@TonyValenti
Copy link

#399 (comment)

@IngoManthey
Copy link

IngoManthey commented Sep 18, 2024

@robbaman
That works great. Unfortunately I have to insert a background image. Is there a way to use your code here?

var background = XImage.FromStream(() => File.OpenRead(Invoice.BackgroundImage));
for (var i = 1; i <= pages; ++i)
{
    var pageInfo = renderer.DocumentRenderer.FormattedDocument.GetPageInfo(i);

    var page = renderer.PdfDocument.AddPage();
    var gfx = XGraphics.FromPdfPage(page, XPageDirection.Downwards);
    gfx.DrawImage(background, 0, 0, pageInfo.Width, pageInfo.Height);
    renderer.DocumentRenderer.RenderPage(gfx, i);
}

@robbaman
Copy link

Hi @IngoManthey

Yes it should. The code I mentioned sets a delegate in a static property. This delegate is used by the XImage.FromStream call on the first line of your code sample.

@IngoManthey
Copy link

Hallo@IngoManthey

Ja, das sollte es. Der von mir erwähnte Code setzt einen Delegaten in einer statischen Eigenschaft. Dieser Delegate wird vom XImage.FromStreamAufruf in der ersten Zeile Ihres Codebeispiels verwendet.

Yes it was my mistake, now everything works. Thanks for the answer

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