NAME

    Image::DecodeQR::WeChat - Decode QR code(s) from images using the
    OpenCV/WeChat library via XS

VERSION

    Version 0.01

SYNOPSIS

        # this ensures that both input params can contain utf8 strings
        # but also results (somehow but beyond me)
        use utf8;
        use Image::DecodeQR::WeChat;
    
        # this will be fixed, right now params are hardoded in XS code
        my $payloads = Image::DecodeQR::WeChat::decode_xs(
            # the input image containing one or more QR-codes
            'an-input-image.png',
    
            # the dir with model parameters required by the library.
            # These come with this package and are curtesy of WeChat
            # which is part of OpenCV contrib packages
            # They are installed with this package and their default location
            # is given by Image::DecodeQR::WeChat::modelsdir()
            # Alternatively, specify your own model files:
            Image::DecodeQR::WeChat::modelsdir(),
    
            # outbase for all output files, optional
            # if more than one QR-codes were detected then an index will
            # be appended to the filename. And there will be png image files
            # containing the portion of the image which was detected
            # and there will be txt files with QR-code text (payload)
            # and its bounding box. And there will be an overall
            # text file with all payloads. This last one will be
            # printed to STDOUT if no outbase was specified:
            'output.detected',
    
            # verbosity level. 0:mute, 1:C code messages, 10:C+XS code
            10,
    
            # display results in a window with QR codes found highlighted
            # make sure you have an interactive shell and GUI
            1,
    
            # dump image and metadata to files for each QR code detected
            # only if outbase was specified
            1,
        );
        die "failed" unless $payloads;
        print "Payload got: $_\n" for (@$payloads);
    
        # The above decode_xs() expects all parameters to be present
        # while decode() below takes a hash of params and fills the
        # missing params with defaults. Then it calls decode_xs()
        # So, it is still calling XS code but via a Perl sub
        # The important bit is that the modelsdir is filled in automatically
        # rather than the user looking for it
        my $payloads = Image::DecodeQR::WeChat::decode({
            # these are required
            'input' => 'input.jpg',
            'outbase' => 'outs',
            # these are optional and have defaults
            #'modelsdir' => '...', # use it only if you have your own models
            #'verbosity' => 0,
            #'graphicaldisplayresult'' => 0,
            #'dumpqrimagestofile' => 0,
        });
        die "failed" unless $payloads;
        print "Payload got: $_\n" for (@$payloads);

    This code calls functions and methods from OpenCV/WeChat library
    (written in C++) for decoding one or more QR codes found embedded in
    images. It's just that: a very thin wrapper of a C++ library written in
    XS. It only interfaces the OpenCV/WeChat library for QR code decoding.

    It can detect multiple QR codes embeded in a single image. And has been
    successfully tested with as small sizes as 55 x 55 px.

    The payload(s) (the QR-code's text) are returned back as an ARRAYref.

    Optionally, it can output the portion of the input image corresponding
    to each QR-code, its bounding box and the payload in separate files,
    useful for debugging and identification when multiple QR codes exist in
    a single input image.

    Following this code as an example, it will be trivial to interface
    other parts of the OpenCV library:

        Ιδού πεδίον δόξης λαμπρόν
           (behold a glorious field of glory)

EXPORT

    decode()

    decode_xs()

    modelsdir()

SUBROUTINES/METHODS

  Image::DecodeQR::WeChat::decode_xs(infile, modelsdir, outbase, verbosity,
 graphicaldisplayresult, dumpqrimagestofile) 

    It takes in the filename of an input image which may contain one or
    more QR codes and returns back an ARRAYref of strings containing all
    the payloads of the codes which have successfully been decoded (some QR
    codes may fail to be decoded because of resolution or quality etc.)

    It returns undef on failure.

    It returns an empty ARRAYref (i.e. a ref to an empty array) if no QR
    codes were found or decoded successfully.

    These are the parameters it requires. They must all be present, with
    optinal parameters allowed to be undef:

    infile : the input image with zero or more QR codes. All the image
    formats of OpenCV's
    https://docs.opencv.org/4.5.5/d4/da8/group__imgcodecs.html|imread() are
    supported.

    modelsdir : the location of the directory holding all model files (CNN
    trained models) required for QR code detection. These models are
    already included with this package and will be installed in a shared
    dir during installation. Their total size is about 1MB. They have been
    kindly contributed by WeChat along with their library for QR Code
    detection. They can be found
    https://github.com/WeChatCV/opencv_3rdparty|here. The installed models
    location is returned by modelsdir(). If you do not want to experiment
    with your own models then just plug the output of modelsdir() to this
    parameter, else specify your own.

    outbase : optionally specify output files basename which will contain
    detected QR-codes' payloads, bounding boxes and QR-code images
    extracted from the input image (one set of files for each QR-code
    detected). If dumpqrimagestofile is set to 1 all the aforementioned
    files will be created. If it is set to 0 then only the payloads will be
    saved in a single file (all in one file). If outbase is left undef then
    nothing is written to a file. As usual all detected codes' data is
    returned back via the returned value of decode_xs().

     verbosity	levels: 0 is mute, 1 is only for C code, 10 is for C+XS
    code.

     graphicaldisplayresult : if set to 1, it will display a window with
    the input image and the detected QR-code(s) outlined.

    dumpqrimagestofile : if set to 0, and outbase is specified, then all
    payloads are written to a single file using the basename specified. If
    set to 1 a lot more information is written to separate files, one for
    each detected code. This is mainly for debugging purposes because the
    returned value contains the payloads and their corresponding QR-codes'
    bounding boxes. See outbase above.

  Image::DecodeQR::WeChat::decode_xs(\%params) 

    This is a Perl wrapper to the decode_xs() so that user can specify only
    a minimal set of parameters and the will be filled in by defaults.

    Like decode_xs(), it returns undef on failure.

    It returns an empty ARRAYref (i.e. a ref to an empty array) if no QR
    codes were found or decoded successfully.

    The  params  hashref:

    input : the name of the input image file which can contain one or more
    QR codes.

    outbase : optional, if specified payloads (QR-code text) will be dumped
    to a text file. If further, dumpqrimagestofile is set to 1 then image
    files with the detected QR-codes will be dumped one for each QR-code as
    well as text files with payloads and bounding boxes wrt the input
    imaghe.

    modelsdir : optional, use it only if you want to use your own model
    files (for their format have a look at
    https://docs.opencv.org/4.x/d5/d04/classcv_1_1wechat__qrcode_1_1WeChatQRCode.html,
    they are CNN training files). This package has included the model files
    kindly submitted by WeChat as a contribution to OpenCV and will be
    installed in your system with all other files. Use modelsdir() to see
    the location of installed model files. Their total size is about 1MB.

    verbosity : default is 0 which is muted. 1 is for verbose C code and 10
    is for verbose C and XS code.

    dumpqrimagestofile : default is 0, set to 1 to have lots of image and
    text files dumped (relative to outbase) for each QR code detected.

    graphicaldisplayresult : default is 0, set to 1 to have a window
    popping up with the input image and the QR-code detected highlighted,
    once for each code detected.

  Image::DecodeQR::WeChat::modelsdir() 

    Return the path where the models included in this package have been
    installed. This is useful when you want to use decode_xs() and need to
    specify the modelsdir. Just pass the output of this to it.

IMPLEMENTATION DETAILS

    This code demonstrates how to call OpenCV (modern OpenCV v4) C++
    methods using the technique suggested by Botje @ #perl in order to
    avoid all the function, macro, data structures name clashes between
    Perl and OpenCV (for example seed(), do_open(), do_close() and most
    notably struct cv and namespace cv in Perl and OpenCV respectively).

    The trick suggested is to put all the OpenCV-calling code in a separate
    C++ file and provide high-level functions to be called by XS. So that
    the XS code does not see any OpenCV header files.

    Makefile.PL will happily compile any .c and/or .cpp files found in the
    dir it resides by placing OBJECT => '$(O_FILES)' in %WriteMakefileArgs.
    And will have no problems with specifying also these:

        CC      => 'g++',
        LD      => 'g++',
        XSOPT   => '-C++',

    With one caveat, g++ compiler will mangle the names of the functions
    when placing them in the object files. And that will cause XSLoader to
    report missing and undefined symbols.

    The cure to this is to wrap any function you want to remain unmangled
    within

        #ifdef __cplusplus
        extern "C" {
        #endif

    and

        #ifdef __cplusplus
        } //extern "C" {
        #endif

    This only need happen in the header file:  wechat_qr_decode_lib.hpp .

INSTALLING OpenCV

    In my case downloading OpenCV using Linux's package manager was not
    successful.It required to add another repository which wanted to
    install its own versions of packages I already had.

    Download OpenCV sources and also its contributed modules.

    Extract the sources and changed to the source dir.

    From within the source dir extract the contrib archive.

    Create a build dir and change to it.

    There are two ways to make cmake just tolerable: cmake-gui and ccmake.
    The former is a full-gui interface to setting the billion cmake
    variables. Use it if you are on a machine which offers a GUI: cmake-gui
    .. . If you are on a remote host possibly over telnet or ssh then do
    not despair because c<ccmake> is the CLI, curses-based equivalent to
    cmake-gui, use it like: ccmake .. .

    Once on the interface first configure, then check the list of all
    variables (you can search on both, for searching in the CLI one press /
    and then n for next hit) to suit you and then generate, quit and
    VERBOSE=1 make -j4 all

    I guess, variables you want to change are OPENCV_EXTRA_MODULES_PATH and
    OPENCV_ENABLE_NONFREE and anything that has to do with CNN or DNN. But
    I only guess.

AUTHOR

    Andreas Hadjiprocopis, <bliako at cpan.org>

BUGS

    Please report any bugs or feature requests to bug-image-decodeqr-wechat
    at rt.cpan.org, or through the web interface at
    https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Image-DecodeQR-WeChat.
    I will be notified, and then you'll automatically be notified of
    progress on your bug as I make changes.

SUPPORT

    You can find documentation for this module with the perldoc command.

        perldoc Image::DecodeQR::WeChat

    You can also look for information at:

      * RT: CPAN's request tracker (report bugs here)

      https://rt.cpan.org/NoAuth/Bugs.html?Dist=Image-DecodeQR-WeChat

      * CPAN Ratings

      https://cpanratings.perl.org/d/Image-DecodeQR-WeChat

      * Search CPAN

      https://metacpan.org/release/Image-DecodeQR-WeChat

ACKNOWLEDGEMENTS

    The great Open Source https://opencv.org/|OpenCV image processing
    library and its contributed module
    https://docs.opencv.org/4.x/dd/d63/group__wechat__qrcode.html which
    form the backbone of this module and do all the heavy lifting.

    Botje and xenu at #perl for help.

    Jiro Nishiguchi (https://metacpan.org/author/JIRO ) whose (obsolete
    with modern - at the time of writing - OpenCV) module Image::DecodeQR
    serves as the skeleton for this module.

    Thank you! to all those who responded to this SO question
    https://stackoverflow.com/questions/71402095/perl-xs-create-and-return-array-of-strings-char-taken-from-calling-a-c-funct

LICENSE AND COPYRIGHT

    This software is Copyright (c) 2022 by Andreas Hadjiprocopis.

    This is free software, licensed under:

      The Artistic License 2.0 (GPL Compatible)

HUGS

    !Almaz!

POD ERRORS

    Hey! The above document had some coding errors, which are explained
    below:

    Around line 164:

      You forgot a '=back' before '=head2'

    Around line 287:

      You forgot a '=back' before '=head1'

      You forgot a '=back' before '=head1'

    Around line 328:

      alternative text
      'https://docs.opencv.org/4.x/dd/d63/group__wechat__qrcode.html'
      contains non-escaped | or /

    Around line 334:

      alternative text 'https://metacpan.org/author/JIRO ' contains
      non-escaped | or /