Reputation: 473
I have a qr code as existing svg image, let's say this one: https://editsvgcode.com/wamcmgdcp9lf8ru018
I use a javascript qr code reader, that works fine when the qr code is on a flat surface, but doesn't reliably read the code when I put the code on a round surface, eg. a bottle.
So my idea is to apply a Pincushion Distortion on the svg image, that makes the qr code look flat if scanned from a certain angle (straight in front) and distance.
How can apply a pincushion distortion effect on an svg image? Of course, I searched on the internet, but I didn't find anything useful (either other svg filters or articles about removing distortion from raster graphics).
Upvotes: 1
Views: 257
Reputation: 473
Being the submitter of the question, I know that the following answer is a non-solution, as it doesn't filfull the requirement "by svg means" of the original question.
Nevertheless, I want to share my workaround with the community. Thus, I kindly ask you not to dovnvote this answer as "not answering the original question". I will not acceppt this answer as solution, but any other answers as solution, that solves the question with svg means.
Here is my code that turns a svg image into php, and apply a 'cylinder to plane' effect on it (https://phpimagick.com/Imagick/distortImage?distortion_type=Cyclinder%20to%20plane&image_path=Lorikeet). I was happy with a width of 500px and with a distortImageAngle of 20, where the qr code looks flat from a distance of about 25 cm (depending on the size of the bottle/jar).
public function svg2png(string $svg, int $width, int $distortImageAngle):string {
$svg = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>'.$svg;
$image = new \Imagick();
$image->readImageBlob($svg);
$height = $width * $image->getImageHeight() / $image->getImageWidth();
$res = $image->getImageResolution(); // in pixels per centimeter
$x_ratio = $res['x'] / $image->getImageWidth();
$y_ratio = $res['y'] / $image->getImageHeight();
$ratio = $x_ratio;
// https://stackoverflow.com/a/13625767/13192551
$image->removeImage();
$image->setResolution($width * $ratio * 2.54, $height * $ratio * 2.54);
$image->readImageBlob($svg);
$image->setImageFormat("png64");
// https://github.com/Imagick/ImagickDemos/blob/def2cedc27d74e9ddd4a638154651dd3924ade11/src/ImagickDemo/Imagick/distortImage.php
$points = array(
$distortImageAngle, //fov_angle,
//center_x,y,
//fov_output,
//dest_center_x,y
);
$image->setImageBackgroundColor("#ffffff");
$image->setImageVirtualPixelMethod(\Imagick::VIRTUALPIXELMETHOD_BACKGROUND);
$image->distortImage(\Imagick::DISTORTION_CYLINDER2PLANE, $points, true);
$png = $image->getImageBlob();
$image->clear();
$image->destroy();
return($png);
}
The reason for applying a pincushion distortion effect on a svg image was that I needed to read a qr code from bottle or (preserving) jar. My wife's solution: Simply put the qr code on the top (of the jar) or bottom (of the bottle). It had saved a lot of time if I had asked her before.
Upvotes: 1