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

Create qr code with direct link instead of being redirected. #6

Open
Azunyan- opened this issue Feb 4, 2021 · 5 comments
Open

Create qr code with direct link instead of being redirected. #6

Azunyan- opened this issue Feb 4, 2021 · 5 comments

Comments

@Azunyan-
Copy link

Azunyan- commented Feb 4, 2021

I would like to be able to generate a qr code that links directly to the url I want without having it redirect via your site.

@raatmarien
Copy link
Owner

There is a way to do this, which I've been thinking about implementing. You could try to first encode the url the user gives and then fill the rest up with random data, but set the data size to just the length of the URL. There are three main challenges with it: First of all, what do we do if the users URL is long? It can take up too much of the QR code then... Secondly, the library that is used now, doesn't allow this directly. Thirdly, will all QR code scanners handle this correctly? To figure this out, it'll need to be implemented and tested with lots of scanners.

However, at the moment, I don't have time to do this. But if you, or anyone else, do have time to do that, feel free to create a PR and I'm happy to answer any questions :)

@keyeh
Copy link

keyeh commented Apr 1, 2021

Another way could be to append the character # or ? at the end of the URL and put all the drawing data after that

For example, these URL still works correctly:
https://example.com#94N+2DEZQNRDU1ZC94RD/MRD...
https://example.com?USERSDRAWINGDATA94N+2DEZQNRDU1ZC94RD.........
https://bit.ly/3wh8HKG?USERS+RANDOM+DRAWING+DATA+HERE

The # and ? characters are not in the QR code alphanumeric set, but, according to thonky.com / wikipedia

It is possible to use multiple modes in a single QR code by including the mode indicator before each section of bytes that uses that mode

After every indicator that selects an encoding mode is a length field that tells how many characters are encoded in that mode.

So the first part of the URL could use byte mode, and then the drawing data can use alphanumeric.
There are other libraries that support encoding multiple modes in a single QR code.

But it's still a problem that the user's URL needs to be very short... at least this would let the user pick their favorite URL shortener.

@fulldecent
Copy link

fulldecent commented Dec 31, 2021

Here is some progress on using custom URLs.

It is a very dumb genetic algorithm that starts with any QR code, and then mutates closer towards a target image.

A novel contribution here is that the target can be grayscale. The generated QR code will dither, making tradeoffs to get close to the the requested color.

This allows to paint on the part that my-qr.art lets you paint on. And it also lets you paint on the error codes. The whole area is your canvas.

// William Entriken (c) 2021
// qr-spray-and-pray.mqs // Node 17+ // npm -i pngjs qrcode
//
// Create target.png of what you want QR to look like
// Tune parameters
// Output is a QR closer and closer to what you want
//
import QRCode from "qrcode";
import * as fs from "fs";
import{ PNG } from "pngjs";

// Load target /////////////////////////////////////////////////////////////////
const targetData = fs.readFileSync("target.png");
const target = PNG.sync.read(targetData);
var targetGray255 = [];
for (var index=0; index<target.width*target.height; index+=4) {
    targetGray255.push(target.data[index]); // Only keep first channel of four
}

// Create //////////////////////////////////////////////////////////////////////
const options = {
    errorCorrectionLevel: "L",
    version: 6,
    maskPattern: 1,
    margin: 0,
    scale: 1
}
const prefix = "https://phor.net/#";

function loss(suffix) {
    const qrcode = QRCode.create(prefix + suffix, options);
    var loss = 0;
    for (var index=0; index<targetGray255.length; index++) {
        const moduleBit = qrcode.modules.data[index] == 1; // 1 = DARK
        const target255 = targetGray255[index]; // 255 = WHITE
        loss += Math.floor(moduleBit
            ? Math.pow(target255, 1.5)
            : Math.pow(255 - target255, 1.5));
    }
    return loss;
}

function randomSpliceDigits(string, spliceSizes) {
    spliceSizes.forEach(numberOfDigits => {
        const valueToInsert = Math.floor(Math.random() * Math.pow(10, numberOfDigits));
        const stringToInsert = String(valueToInsert).padStart(numberOfDigits, "0");
        const locationToInsert = Math.floor(Math.random() * (string.length - numberOfDigits));
        string = string.substr(0, locationToInsert) + stringToInsert + string.substr(locationToInsert + numberOfDigits);
    });
    return string;
}

// to start, manually set suffix to be as large as possible for version/errorcorrection by trial/getting errors
var bestSuffix = "37348811905212874935831596698511608404485249315311992159406439210629002607128961487044174248108263018999806889709719495546738427914989016968717957729315662204376571097387723144555160821753721774774216159174612135825629709926432407621787044780906828380642588961079399703815370";
var bestLoss = loss(bestSuffix); 

const splicePatterns = [
    [1],
    [2],
    [3],
    [1,2,3],
    [3,3],
    [3,3,3],
    [1,1,1,1,1,1],
    [2,2,2],
];

while (true) {
    const candidateSuffix = randomSpliceDigits(bestSuffix, splicePatterns[Math.floor(Math.random()*splicePatterns.length)]);
    if (candidateSuffix === bestSuffix) continue;
    const candidateLoss = loss(candidateSuffix);
    console.log(candidateLoss, candidateSuffix);
    if (candidateLoss <= bestLoss) {
        bestSuffix = candidateSuffix;
        bestLoss = candidateLoss;
        await QRCode.toFile("best.png", prefix + candidateSuffix, options);
        console.log("❤️");
    }
}

If it's not clear, I have no idea what I'm doing. I'll appreciate any feedback that moves this in the right direction.

target
best

target
best

target
best

target
best

@fulldecent
Copy link

Here is one more less ridiculous approach you can use with my-qr.art:

  1. Use my.qr.art
  2. Scan the result with ZXING
  3. Add your own URL, in uppercase, plus a # as a prefix to that URL (npm install -g qrcode and qrcode -m 1 -e l)
  4. Delete the from that URL (not your prefix) character-by-character until your result is the same version (size) as the my-qr.art version
  5. Add one more # to your prefix and delete one character from the front of that URL (not your prefix) (this shifts everything over one bit)

Done.

Result:
ph

That URL is direct to my website, designed with my-qr.art, and works on iPhone.

@grenache
Copy link

my-qr.art is very impressive and able to make some awesome looking QR codes. Unfortunately, I can't use them in projects because the domain name is unfamiliar and doesn't add trust. I believe people will be less likely to click links to a unrelated qr code website. The link-redirection is a deal breaker.

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

5 participants