dagronf / QRCode

A quick and beautiful macOS/iOS/tvOS/watchOS QR Code generator/detector library for SwiftUI, Swift and Objective-C.
MIT License
438 stars 57 forks source link

Adding a logo template inset after creating a template seems not to affect created mask size #24

Closed keremerkan closed 1 year ago

keremerkan commented 1 year ago

I don't know if this is the intended mechanism but here it goes :)

If I don't want to use a predefined mask in my logo template and rely on the transparency of the image, I presume I should directly add the image to the template:

doc.logoTemplate = QRCode.LogoTemplate(image: image)

This lets QRCode library to generate a mask for the template. But the resulting logo image is way too big:

IMG_0085

Then I inset the image:

doc.logoTemplate?.inset = 500.0

Enhancement suggestion: Here I believe inset should be a relative size inside the QR Code, similar to the shape insetFraction variable for pixel shapes. That way, we could write something like:

doc.logoTemplate?.insetFraction = 0.25

And the logo would get reduced to the necessary percentage size regardless of the CGImage size. PS: This should be done ignoring additionalQuietZonePixels value so that the logo size does not change with any additional quiet zone width.

BUG: Now here is the bug (or unexpected behavior). When I inset the image with the command above, The image itself gets reduced in size, but the mask stays the same. Please see the resulting image:

IMG_0084

You can see that the pixels are masked with the original image size, while the image itself is smaller. Is this expected or am I again missing some configuration?

Thanks!

dagronf commented 1 year ago

I'll answer this in two parts.

Part 1

doc.logoTemplate = QRCode.LogoTemplate(image: image)

This method of masking treats the image as the same size as the resulting QR code. Looking at the documentation the transparent part of the image lets the qrcode components through, and the non-transparent parts show the image.

If your cat/heart image fill the entire image, then the first image you present is correct according to the interface.

I'm guessing what you're looking for is an image something like this :- cat-heart

Note that the image positions the image in the lower right with transparent pixels.

If you want padding between your image and the QR code components, add padding to the image directly like this :-

cat-heart-white-spacing

dagronf commented 1 year ago

I'll need some time for part 2...

keremerkan commented 1 year ago

I understand that the first image is correct. But after insetting the image, shouldn't it also inset the mask? I believe there may be a bug there.

keremerkan commented 1 year ago

I wrote an extension func to inset the image and add a border around. That way I have full control over the shape and mask. But this time, I encountered another problem. Since the mask removes pixels from the QR Code, the resulting image looks a little ugly in my opinion.

Can we add a setting to LogoTemplate class so that it does not use any mask and simply overlays the image directly on the code image? I can fork the project to add this, but since it is a trivial setting to add, I thought it would be better to do it on the main project.

To test this, I changed

func applyingMask(matrix: BoolMatrix, dimension: CGFloat) -> BoolMatrix

and

func applyingTransparency(matrix: BoolMatrix, dimension: CGFloat) -> BoolMatrix

functions to simply return the boolMatrix untouched. The resulting image is the following:

IMG_DD086B95AD6B-1

I believe this looks much prettier than removing pixels behind the logo. Adding a setting that disables masking would be great here.

dagronf commented 1 year ago

@keremerkan v14.4.0 has just been pushed up with an additional parameter to the LogoTemplate initializer (masksQRCodePixels) which turns on/off the qr pixel masking

keremerkan commented 1 year ago

@dagronf thanks! Just tested it and it works perfectly.