0

Problem

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.

Question

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).

BogisW
  • 401
  • 2
  • 16
  • 1
    SVG doesn't really support non-affine transforms. You might be able to fake one using an feDisplacementMap but you'd need to generate a raster image that applied the distortion. – Robert Longson Mar 14 '23 at 22:01
  • Probably you could find a `` solution. See ["Pinch/pucker an image in canvas"](https://stackoverflow.com/questions/33402497/pinch-pucker-an-image-in-canvas) – herrstrietzel Mar 15 '23 at 20:04
  • Thank you all. I'm not sure it's "not supported", see https://codepen.io/johanberonius/pen/RopjYW. But I understand, that there is no easy standard solution with svg means. – BogisW Mar 19 '23 at 11:03

1 Answers1

0

Disclaimer

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.

Using PHP/Imagick

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);
  }

Non-programming solution

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.

BogisW
  • 401
  • 2
  • 16