codebude / QRCoder

A pure C# Open Source QR Code implementation
MIT License
4.43k stars 1.08k forks source link

Cannot use 5 argument version of QRCode constructor under Windows .net 8.0 with Nuget 1.5.1 #536

Closed catdsnny closed 1 month ago

catdsnny commented 1 month ago

Type of issue

[x] Bug
[ ] Question (e.g. about handling/usage)
[ ] Request for new feature/improvement

Expected Behavior

Should be able to use 5 argument version of constructor

Current Behavior

The 5 argument version of the constructor does not exist in Nuget package v 1.5.1

Possible Solution (optional)

Update the Nuget package with current version of code

Steps to Reproduce (for bugs)

Create a new C# console solution with .NET 8.0 Add QRCode 1.5.1 with Nuget Try to call the 5 argument version of QRCode constructor to make an QR with an embedded image. Get compile error

Your Environment

Windows 10 .NET 8.0 Standard Nuget v 1.5.1

codebude commented 1 month ago

When talking about QrCode constructor you mean the constructor of the QrCode renderer class? If so, this has no overload with 5 arguments. Please check the wiki: https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#21-qrcode-renderer-in-detail

To give you a more detailed answer it would be helpful if you could post a short snippet of your code that throws the error.

catdsnny commented 1 month ago

Overload version 4 - the params after #5 are defaults. Anyway only 2 versions of the constructor signature exist. I solved the problem using ImageSharp to merge the logo with QRCode. For those similarly situated this was my solution. Thanks to chatgpt for providing 1bit to 32bit conversion code.

            byte[] qrCodeImage = qrCode.GetGraphic(20);

            Image<Rgba32> qrImage =

SixLabors.ImageSharp.Image.Load(ConvertTo32Bit(qrCodeImage));

            Image<Rgba32> logo =

SixLabors.ImageSharp.Image.Load("logo.png");

            int x = (qrImage.Width - logo.Width) / 2;
            int y = (qrImage.Height - logo.Height) / 2;

            qrImage.Mutate(ctx => ctx.DrawImage(logo, new

SixLabors.ImageSharp.Point(x, y), new GraphicsOptions { AlphaCompositionMode = PixelAlphaCompositionMode.SrcOver, BlendPercentage = 1f }));

            qrImage.Save(@"logo-with-image.png");

    static byte[] ConvertTo32Bit(byte[] qrCodeImage)
    {
        using (var ms = new MemoryStream(qrCodeImage))
        {
            using (var bitmap = new Bitmap(ms))
            {
                using (var convertedBitmap = new Bitmap(bitmap.Width,

bitmap.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { using (var graphics = Graphics.FromImage(convertedBitmap)) { graphics.DrawImage(bitmap, 0, 0); }

                    using (var stream = new MemoryStream())
                    {
                        convertedBitmap.Save(stream,

System.Drawing.Imaging.ImageFormat.Png); return stream.ToArray(); } } } } }

On Fri, May 24, 2024 at 5:42 PM Raffael Herrmann @.***> wrote:

When talking about QrCode constructor you mean the constructor of the QrCode renderer class? If so, this has no overload with 5 arguments. Please check the wiki: https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#21-qrcode-renderer-in-detail

To give you a more detailed answer it would be helpful if you could post a short snippet of your code that throws the error.

— Reply to this email directly, view it on GitHub https://github.com/codebude/QRCoder/issues/536#issuecomment-2130406288, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAUBNHD3Z6YGXLX5CZQDR2DZD6X4ZAVCNFSM6AAAAABIIHRULKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMZQGQYDMMRYHA . You are receiving this because you authored the thread.Message ID: @.***>

codebude commented 1 month ago

Ok, I re-checked it with a simple test application:

QRCodeGenerator qrGenerator = new QRCodeGenerator();
QRCodeData qrCodeData = qrGenerator.CreateQrCode("The text which should be encoded.", QRCodeGenerator.ECCLevel.Q);
QRCode qrCode = new QRCode(qrCodeData);
var bmp = (Bitmap)Bitmap.FromFile(@"C:\\test.png");
Bitmap qrCodeImage = qrCode.GetGraphic(20, Color.Black, Color.White, bmp, 15);
pictureBox1.BackgroundImageLayout = ImageLayout.Zoom;
pictureBox1.BackgroundImage = qrCodeImage;

The application runs perfectly fine:

image

All four overloads are showing up:

image

Enviroment was QRCoder 1.5.1 from Nuget, .NET8 as target framework and Windows as development environment;

image

I can't see a bug here. The problem seems to be in your setup.

andreflourenco commented 3 weeks ago

I have the same problem in NET 6. I've created a very simple console application:

Program.cs

using System.Drawing;
using System.Drawing.Imaging;

byte[] qrCodeImageContent = null;
using (var qrGenerator = new QRCodeGenerator())
{
    using (var qrCodeData = qrGenerator.CreateQrCode("HELLO", QRCodeGenerator.ECCLevel.M))
    {
        using (var qrCode = new QRCode(qrCodeData))
        {
            var qrCodeBitmap = qrCode.GetGraphic(10, Color.Black, Color.White, false);
            using (var buffer = new MemoryStream())
            {
                qrCodeBitmap.Save(buffer, ImageFormat.Png);
                qrCodeImageContent = buffer.ToArray();
            };
        }
    }
}

QRCodeTest.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="QRCoder" Version="1.5.1" />
    <PackageReference Include="System.Drawing.Common" Version="8.0.6" />
  </ItemGroup>

</Project>

The error in console is:

error CS0246: The type or namespace name 'QRCode' could not be found (are you missing a using directive or an assembly reference?)
Shane32 commented 3 weeks ago

Change this line as follows:

<TargetFramework>net6.0-windows</TargetFramework>
andreflourenco commented 3 weeks ago

Change this line as follows:

<TargetFramework>net6.0-windows</TargetFramework>

That would make my code platform specific, right?

It wasn't before and I would not like it to be...

Shane32 commented 3 weeks ago

The QRCode class uses System.Drawing.Bitmap which is unavailable on non-Windows platforms starting with .NET 6. Please use a cross-platform renderer such as PngByteQRCode instead. See chart of available renderers here:

For reference, also see MS docs on System.Drawing.Common:

andreflourenco commented 3 weeks ago

OK, so using PngByteQRCode I reckon it would look something like:

using QRCoder;
using System.Drawing;

byte[] qrCodeImageContent = null;
using (var qrGenerator = new QRCodeGenerator())
{
    using (var qrCodeData = qrGenerator.CreateQrCode("HELLO", QRCodeGenerator.ECCLevel.M))
    {
        using (var qrCode = new PngByteQRCode(qrCodeData))
        {
            qrCodeImageContent = qrCode.GetGraphic(10, Color.Black, Color.White, false);
        }
    }
}

But could not figure out what would be the equivalent for the color parameters, since now it is a byte array. Can they be obtained from the System.Drawing.Color instances?

Shane32 commented 3 weeks ago
var color = System.Drawing.Color.Red;
var darkColorRgba = new byte[] { color.R, color.G, color.B, color.A };

There could probably be an overload for this added...