manuelbl/QrCodeGenerator

IImageProcessingContext does not contain a definition for Fill

Closed this issue · 4 comments

When I add the extension functions for SixLabors.Imagesharp, I get the error on fill:

IImageProcessingContext does not contain a definition for fill.

The extension method code is below. I can't use System.Drawing() because my target is iOS and Skia had signing issues so I wanted to test SixLabors.


//
// QR code generator library (.NET)
// https://github.com/manuelbl/QrCodeGenerator
//
// Copyright (c) 2021 Manuel Bleichenbacher
// Licensed under MIT License
// https://opensource.org/licenses/MIT
//

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Extensions;
using System;
using System.IO;
using Image = SixLabors.ImageSharp.Image;

namespace Net.Codecrete.QrCodeGenerator
{
    public static class QrCodeBitmapExtensions
    {
        /// <inheritdoc cref="ToBitmap(QrCode, int, int)"/>
        /// <param name="background">The background color.</param>
        /// <param name="foreground">The foreground color.</param>
        public static Image ToBitmap(this QrCode qrCode, int scale, int border, SixLabors.ImageSharp.Color foreground, SixLabors.ImageSharp.Color background)
        {
            // check arguments
            if (scale <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(scale), "Value out of range");
            }
            if (border < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(border), "Value out of range");
            }

            int size = qrCode.Size;
            int dim = (size + border * 2) * scale;

            if (dim > short.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(scale), "Scale or border too large");
            }

            // create bitmap
            Image<Rgb24> image = new Image<Rgb24>(dim, dim);

            image.Mutate(img =>
            {
                // draw background
                img.Fill(background);
                

                // draw modules
                for (int y = 0; y < size; y++)
                {
                    for (int x = 0; x < size; x++)
                    {
                        if (qrCode.GetModule(x, y))
                        {
                            img.Fill(foreground, new Rectangle((x + border) * scale, (y + border) * scale, scale, scale));
                        }
                    }
                }
            });

            return image;
        }

        /// <summary>
        /// Creates a bitmap (raster image) of this QR code.
        /// <para>
        /// The <paramref name="scale"/> parameter specifies the scale of the image, which is
        /// equivalent to the width and height of each QR code module. Additionally, the number
        /// of modules to add as a border to all four sides can be specified.
        /// </para>
        /// <para>
        /// For example, <c>ToBitmap(scale: 10, border: 4)</c> means to pad the QR code with 4 white
        /// border modules on all four sides, and use 10&#xD7;10 pixels to represent each module.
        /// </para>
        /// <para>
        /// The resulting bitmap uses the pixel format <see cref="PixelFormat.Format24bppRgb"/>.
        /// If not specified, the foreground color is black (0x000000) und the background color always white (0xFFFFFF).
        /// </para>
        /// </summary>
        /// <param name="scale">The width and height, in pixels, of each module.</param>
        /// <param name="border">The number of border modules to add to each of the four sides.</param>
        /// <returns>The created bitmap representing this QR code.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="scale"/> is 0 or negative, <paramref name="border"/> is negative
        /// or the resulting image is wider than 32,768 pixels.</exception>
        public static Image ToBitmap(this QrCode qrCode, int scale, int border)
        {
            return qrCode.ToBitmap(scale, border, SixLabors.ImageSharp.Color.Black, SixLabors.ImageSharp.Color.White);
        }

        /// <inheritdoc cref="ToPng(QrCode, int, int)"/>
        /// <param name="background">The background color.</param>
        /// <param name="foreground">The foreground color.</param>
        public static byte[] ToPng(this QrCode qrCode, int scale, int border, SixLabors.ImageSharp.Color foreground, SixLabors.ImageSharp.Color background)
        {
            using Image image = qrCode.ToBitmap(scale, border, foreground, background);
            using MemoryStream ms = new MemoryStream();
            image.SaveAsPng(ms);
            return ms.ToArray();
        }

        /// <summary>
        /// Creates a PNG image of this QR code and returns it as a byte array.
        /// <para>
        /// The <paramref name="scale"/> parameter specifies the scale of the image, which is
        /// equivalent to the width and height of each QR code module. Additionally, the number
        /// of modules to add as a border to all four sides can be specified.
        /// </para>
        /// <para>
        /// For example, <c>ToPng(scale: 10, border: 4)</c> means to pad the QR code with 4 white
        /// border modules on all four sides, and use 10&#xD7;10 pixels to represent each module.
        /// </para>
        /// <para>
        /// If not specified, the foreground color is black (0x000000) und the background color always white (0xFFFFFF).
        /// </para>
        /// </summary>
        /// <param name="scale">The width and height, in pixels, of each module.</param>
        /// <param name="border">The number of border modules to add to each of the four sides.</param>
        /// <returns>The created bitmap representing this QR code.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="scale"/> is 0 or negative, <paramref name="border"/> is negative
        /// or the resulting image is wider than 32,768 pixels.</exception>
        public static byte[] ToPng(this QrCode qrCode, int scale, int border)
        {
            return qrCode.ToPng(scale, border, SixLabors.ImageSharp.Color.Black, SixLabors.ImageSharp.Color.White);
        }

        /// <inheritdoc cref="SaveAsPng(QrCode, string, int, int)"/>
        /// <param name="background">The background color.</param>
        /// <param name="foreground">The foreground color.</param>
        public static void SaveAsPng(this QrCode qrCode, string filename, int scale, int border, SixLabors.ImageSharp.Color foreground, SixLabors.ImageSharp.Color background)
        {
            using Image image = qrCode.ToBitmap(scale, border, foreground, background);
            image.SaveAsPng(filename);
        }

        /// <summary>
        /// Saves this QR code as a PNG file.
        /// <para>
        /// The <paramref name="scale"/> parameter specifies the scale of the image, which is
        /// equivalent to the width and height of each QR code module. Additionally, the number
        /// of modules to add as a border to all four sides can be specified.
        /// </para>
        /// <para>
        /// For example, <c>SaveAsPng("qrcode.png", scale: 10, border: 4)</c> means to pad the QR code with 4 white
        /// border modules on all four sides, and use 10&#xD7;10 pixels to represent each module.
        /// </para>
        /// <para>
        /// If not specified, the foreground color is black (0x000000) und the background color always white (0xFFFFFF).
        /// </para>
        /// </summary>
        /// <param name="scale">The width and height, in pixels, of each module.</param>
        /// <param name="border">The number of border modules to add to each of the four sides.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="scale"/> is 0 or negative, <paramref name="border"/> is negative
        /// or the resulting image is wider than 32,768 pixels.</exception>
        public static void SaveAsPng(this QrCode qrCode, string filename, int scale, int border)
        {
            qrCode.SaveAsPng(filename, scale, border, SixLabors.ImageSharp.Color.Black, SixLabors.ImageSharp.Color.White);
        }
    }
}```

Thanks for reporting. I will look into it.

I am aware that strong naming was broken in Skia 2.80.3. But now that 2.80.4 and 2.88.0 have been released: is it still broken?

By the way thanks for this awesome library :).
I think it is still broken. I have a MAUI app and I can deploy to an iOS device on Debug with a cable connection. But when I try to upload it to App Store I get the error:

Missing or invalid signature. The bundle 'com.microsoft.libSkiaSharp' at bundle path 'Payload/Istanbul Bridge Conference Application.app/Frameworks/libSkiaSharp.framework' is not signed using an Apple submission certificate. (ID: da574c8d-9ef0-42a9-b7a8-05dfc6df8b41)

To be honest I am not sure where the error comes from; the intricate signing shenanigans of MAUI or skia naming issues.

The reason your code doesn't compile is that a using statement is missing:

using SixLabors.ImageSharp.Drawing.Processing;

In order to use it, you will also need to add the NuGet package SixLabors.ImageSharp.Drawing. SixLabors.ImageSharp is not sufficient.

It also looks as if your error ("is not signed using an Apple submission certificate") is not related to a problem with Skia strong naming but rather a problem with your project and certificates. It could likely also affect your modified app.

I see. When I saw SixLabors.ImageSharp.Drawing, I directly thought it is a part of the package ImageSharp.

For the signing, I am not sure. I will be once I make ImageSharp work and see if I still get a signing error.
Thank you very much for your help; I am closing this issue as I no longer get the error mentioned in the title.