-
-
Notifications
You must be signed in to change notification settings - Fork 306
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
Rounded Corners Pull Request #127
Comments
Wow! That looks great! A PR would be much appreciated! I'll see if it can be at least implemented in the ImageMagick output, GD seems too clunky to draw round corners anyway... |
@abhibeckert thanks for sharing your experience, if PR needs a lot of cleaning and tests ... can you share the snippet which creates the rounded corners here? |
So the main challenge I had is SVG doesn't seem to handle shapes that touch each other - it tends to draw hairline cracks in between. I wasn't able to completely eliminate the issue but I was able to get pretty close by overlapping shapes... which is mostly where the code became messy as I was it was largely trial end error with minimal planning. Here's my test code: https://gist.github.com/abhibeckert/2bfb6a884c7fdd3194af86bd28ef9c10 I will clean it up some time soon as I plan to use it in production. |
The hairlines happen when the modules are not in the same |
Thanks for sharing your code, it is really helpful. |
Hey @abhibeckert, since i had time over the long weekend i did some thinking and played around with your test code and wanted to share some feedback and ideas. Edit: here's the updated example of yours: https://gist.github.com/codemasher/6309f5159f1008cb988f54dde439a64b So unfortunately the render issues are a common problem and exist since forever (the oldest Stackoverflow questions on that issue date back to like 2011) and the most common suggestion is to put everything that shall not cause issues in a single path, as I mentioned before. There's the I do like the So we need to go the hard and ugly way and generate a single path element with all modules (dark and light) shaped accordingly to their neighbour fields. So since it has been asked in #126 before, I came up with a method that returns a bitmask that indicates the status of the 8 fields around the current one, and which I'm willing to add to /**
* Checks the status neighboring modules of the given module at ($x, $y) and returns a bitmask with the results.
*
* The 8 flags of the bitmask represent the status of each of the neighbouring fields,
* starting with the lowest bit for top left, going clockwise:
*
* 1 2 3
* 8 # 4
* 7 6 5
*
* @todo: when $M_TYPE_VALUE is given, it should check for the same $M_TYPE while igrnoring the IS_DARK flag
*
* (this method may be added to QRMatrix as direct array access is faster than method calls)
*/
protected function checkNeighbours(int $x, int $y, int $M_TYPE_VALUE):int{
$bits = 0;
// may be added as constant to QRMatrix
$neighbours = [
0b00000001 => [-1, -1],
0b00000010 => [ 0, -1],
0b00000100 => [ 1, -1],
0b00001000 => [ 1, 0],
0b00010000 => [ 1, 1],
0b00100000 => [ 0, 1],
0b01000000 => [-1, 1],
0b10000000 => [-1, 0]
];
foreach($neighbours as $bit => $coord){
if($this->matrix->check($x + $coord[0], $y + $coord[1])){
$bits |= $bit;
}
}
return $bits;
} In addition I made paths (with relative coordinates) for all of the necessary shapes: The shapes just need to be parametrized with the common values as numbered arguments ( cheers! |
Oh, i forgot to mention that I've added some |
This is it: $bits = $this->checkNeighbours($x, $y, $M_TYPE);
$check = fn(int $all, int $any):bool => ($bits & ($all | (~$any & 0xff))) === $all;
// 1 2 3
// 8 # 4
// 7 6 5
// checking if a rounded corner on 1 (top left) only is valid
// for this, the right (4) and bottom edge (6) must have neighbours, top (2) and left (8) must not
// neighbours on the corners (1,3,5,7) are optional
// $bits = 0b00101101
$check(0b00101000, 0b01010101); // -> true |
Ok, so i have implemented the thing, code over here. Turns out it is surprisingly tricky to recreate the effect in an ImageMagick raster image as there seems no easy way to just draw a path and fill it with a color. However, it always possible to convert the SVG to a raster image via the Inkscape command line interface. The result looks something like this: I have also added an option to inverse the effect, so that it "flows" along the dark modules: |
@codemasher there's a bug in your example code. Specifically this line:
Fails because |
Hey, i haven't updated the examples here in this thread and on gist, instead i have added the full working example over here: https://github.com/chillerlan/php-qrcode/blob/main/examples/svgMeltedModules.php |
@codemasher the example doesnt seem to be working with latest version. |
@kusiu it works fine with |
@codemasher I've added one more tweak:
(replace the gradient with a solid color, if that's what you're using... I normally use a subtle gradient) The extra stroke fixes the edge issues in this example (note this issue only occurs with some SVG renderers): ![]() The slightly fatter dark blocks result in this: ![]() |
Hey, thank you for the feedback! I'll check out adding a stroke, but so far i haven't run into the render issue again. |
I think this is only working with dev-main currently. |
@YeftaAW how so? Please open a new discussion for your issue. |
I've written a custom output class to generate rounded corners, like this:
It works fine for my use case, but would you be interested in a pull request? If you are then I'll clean it up, write some tests, etc.
Also it currently only outputs to SVG. Which is all I need myself, I wouldn't want to write the code to do rounded corners as a bitmap...
The text was updated successfully, but these errors were encountered: