My pride for Image::DecodeQR::WeChat
I have just submitted on CPAN inspired
this blitz-style QR japh. Lame as it may be, enjoy.
Said module is my first to use XS and a significant milestone for
me as I have managed finally to port OpenCV API into Perl.
It's been adjusted for PM's rendering particularities and
hopefully copy+pasting
the text from the Download link will
produce the correct output.
Tested on a Linux unicode-enabled
terminal. If there is no download link for below code
then click on Download code below
https://perlmonks.org/?node_id=11142119;displaytype=displaycode
If anyone has suggestions on how to fix this monstrosity between code tags let me know
(edit: pre tags shows the unicode but breaks other things).
Apropos the QR-code below: ideally I would just use the black brick
and a white space but unfortunately whatever i do the space gets shrinked
i tried various unicode spaces but nothing worked, they all got shrinked
below I am using a thin horizontal line as space which will most likely
confuse the decoder.
██████████████▁▁▁▁▁▁██▁▁▁▁▁▁██████▁▁██████████████
██▁▁▁▁▁▁▁▁▁▁██▁▁██████▁▁▁▁▁▁▁▁████▁▁██▁▁▁▁▁▁▁▁▁▁██
██▁▁██████▁▁██▁▁██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██▁▁██████▁▁██
██▁▁██████▁▁██▁▁▁▁██▁▁▁▁██▁▁██▁▁▁▁▁▁██▁▁██████▁▁██
██▁▁██████▁▁██▁▁██████▁▁██▁▁██████▁▁██▁▁██████▁▁██
██▁▁▁▁▁▁▁▁▁▁██▁▁██▁▁██▁▁████████▁▁▁▁██▁▁▁▁▁▁▁▁▁▁██
██████████████▁▁██▁▁██▁▁██▁▁██▁▁██▁▁██████████████
▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██▁▁████▁▁▁▁▁▁▁▁██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
████▁▁██▁▁▁▁████▁▁▁▁▁▁████████▁▁▁▁▁▁██████▁▁████▁▁
████▁▁██████▁▁██████▁▁██████▁▁▁▁██████▁▁▁▁██▁▁▁▁██
▁▁▁▁▁▁▁▁▁▁▁▁██████▁▁▁▁████████▁▁██▁▁▁▁████████████
▁▁▁▁▁▁▁▁██▁▁▁▁██████████████▁▁████▁▁▁▁▁▁██▁▁▁▁██▁▁
▁▁▁▁████▁▁████████▁▁████▁▁██▁▁▁▁████████▁▁██▁▁████
▁▁▁▁████████▁▁██▁▁██▁▁██▁▁▁▁▁▁▁▁▁▁██████▁▁▁▁██▁▁██
██▁▁██▁▁██▁▁██▁▁████▁▁██▁▁██▁▁▁▁██▁▁██████▁▁██▁▁██
▁▁██▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████▁▁██████▁▁▁▁▁▁▁▁████▁▁████
████▁▁██▁▁████▁▁██▁▁██▁▁██▁▁▁▁▁▁██████████▁▁██▁▁▁▁
▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████▁▁██▁▁██▁▁██▁▁▁▁▁▁████▁▁▁▁▁▁
██████████████▁▁████▁▁████████▁▁██▁▁██▁▁██▁▁██████
██▁▁▁▁▁▁▁▁▁▁██▁▁▁▁████▁▁██▁▁██▁▁██▁▁▁▁▁▁██▁▁████▁▁
██▁▁██████▁▁██▁▁▁▁████▁▁██████▁▁██████████▁▁▁▁██▁▁
██▁▁██████▁▁██▁▁██▁▁▁▁██▁▁██▁▁██▁▁▁▁▁▁██████▁▁▁▁▁▁
██▁▁██████▁▁██▁▁▁▁▁▁▁▁▁▁████▁▁▁▁▁▁██▁▁▁▁████▁▁▁▁██
██▁▁▁▁▁▁▁▁▁▁██▁▁██▁▁▁▁██▁▁██▁▁████▁▁▁▁██▁▁▁▁▁▁▁▁▁▁
██████████████▁▁████▁▁▁▁▁▁██▁▁▁▁██▁▁▁▁██▁▁▁▁▁▁████
use utf8;
eval join'',
map{
$_->[0]=~s/[\x{2588}\n]//gr
=~s/█//gr
=~s/&/&/gr
=~s/</</gr
=~s/>/>/gr
=~s/[/[/gr
=~s/]/]/gr
}
([<<'EOP']);
███████use█ █Tex
+█t:█:█QRC█o█de█;█
us█e███████
█ utf8█;█
bi█n███m█od██e█(█
+;██ST█D█O█UT█, ':e█
█n███c█od█ing██(█
+;█utf8)'██)███;
██m█y █@███a█
█ ███=█ ██m█ap █
+███{████ ██&
+;#91;spl█i█t██/█/███,
+█
█$███_█&#93; } █split("█
+█████ ",████ "&
+#9608;██a█n███o█
█phele█s██ █cog██, t█r
+ue█ █a█rcho█n of█ junk█
███████"█)█;`
+08;
█
█p█r█i█n█t█ █j█o█
+;i█n█ ███████
"\n",
map██ █{
█ y█/* ██/██\█x█
+;{2█588}\x{25
█████9█████
+;█1}/; ████████
+█$_
██} map█ █{█ █j
oi██n '', █ma█p█ █{ $█_π
+8;.█$█_█████ ██
+█} █@███
██$_█ █}█ @{Te█xt::Q██
+R██C██ode█████&
+#9608;-██&gt;█n█e
w(██)-&gt;plo█t(
██ j█oin █████π
+8;█""██,███ ███
+███
███ma██p {█
█ ████j█o█i█n("
+"█,█@█$_)█ =~ m██
(&#91;███^^███&gt;&gt;
+&#93;*█(.)(█.█)(.)&#91;&lt;█π
+8;█&lt;█^^██&#93;?(oO█(█
i███████ou█uu█&#
+9608;u)████)█?█)██ &#
+9608;an████d
█ j██o
i███n "██"███,█
+m███ap █{██ █($1█`
+08;+█$██████3=
█=█████4-█$██	
+608;██2███)████
+ ? " "█ █:█ ██(42%11
-$██2█==█$1+$3) █? uc : l█c █
+;██} ($███a█&#91;█$2	
+608;
█&#93;█-&gt;&#91;███$3&#
+93;█)
███ }██ ██m█a█
+;█p {██ &#91;m██$█&#91;&#
+9608;9
█50█618371████&gt;&gt;`
+08;█!█42!&lt;█&lt;1██7█38
+6█1█059███&#93;█
█$█████████
+;g&#93;█ }███████
+██ "450█222█5████`
+08;08██
5████201█0█350█0101█&#
+9608;302██3█2████07█&
+#9608;331█051█
31███2█2█06██03██
+;█1██2█3████2315π
+8;████0█6█4█00
5██3█370█07███1██
+;03██531██2████3π
+8;█33█1" █████
█=█████████
+;~█ m$x██?██████
+;.y?██.z?.&#91;█████wro
+n
██g█&#93;█?$████g&
+#9608;
█)}
EOP
here is the more readable japh (Above I am "shaping" perl script as a QR code):
use Text::QRCode;
use utf8;
binmode(STDOUT, ':encoding(utf8)');
binmode(STDERR, ':encoding(utf8)');
my @a = map { [split//,$_] } split(" ", "anopheles cog, true archon of
+ junk");
print join "\n",
map {
y/* /\x{2588}\x{2591}/; $_
} map { join undef, map { $_.$_ } @$_ } @{Text::QRCode->new()->plo
+t(
join "", map {
join("",@$_) =~ m([^^>>]*(.)(.)(.)[<<^^]?(oO(iouuuu))?) and
join "", map { ($1+$3==4-$2) ? " " : (42%11-$2==$1+$3) ? uc :
+lc } ($a[$2]->[$3])
} map { [m$[950618371>>!42!<<173861059]$g] }
"45022250852010350010130232073310513122060312323150640053370
+0710353123331" =~ m$x?.y?.z?.[wrong]?$g
)}
;
bw, bliako
Re: Shameless plug and QR japh
by cavac (Parson) on Apr 08, 2022 at 11:18 UTC
|
It took me quite a bit to get the labyrinth on my homenode cavac sort of working. And it only displays correctly on Google Chrome (using Ubuntu 20.04 here, might look different on other operating systems with different fonts installed. And i am using pre tags, not code tags.
One way to render it better on PerlMonks would be to use a HTML table with colored cells. Something like this:
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="20px" height="20px" bgcolor="white"></td><td width="20px" h
+eight="20px" bgcolor="black"></td><td width="20px" height="20px" bgco
+lor="white"></td><td width="20px" height="20px" bgcolor="black"></td>
</tr><tr>
<td width="20px" height="20px" bgcolor="black"></td><td width="20px" h
+eight="20px" bgcolor="white"></td><td width="20px" height="20px" bgco
+lor="black"></td><td width="20px" height="20px" bgcolor="white"></td>
</tr>
</table>
Which will give you:
So, to generate a (mostly) PM compatible version, you would do something like this:
#!/usr/bin/env perl
use strict;
use warnings;
use Text::QRCode;
my $qr = Text::QRCode->new()->plot("YAPH");
my $black = '<td width="15px" height="15px" bgcolor="black"></td>';
my $white = '<td width="15px" height="15px" bgcolor="white"></td>';
print "<p> </p>;\n"; # Add "silent zone"
print '<table border="0" border="0" cellspacing="0" cellpadding="0">',
+ "\n";
foreach my $line (@{$qr}) {
print "<tr>";
foreach my $elem (@{$line}) {
if($elem eq '*') {
print $black;
} else {
print $white;
}
}
print "</tr>\n";
}
print '<\table">', "\n";
print "<p> </p>;\n"; # Add "silent zone"
Resulting in a somewhat useable QR code:
perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'
| [reply] [d/l] [select] |
|
▄▄▄▄▄▄▄ ▄ ▄ ▄▄▄▄▄▄▄
█ ▄▄▄ █ ▄ ▄ ▀ █ ▄▄▄ █
█ ███ █ ▄ ▄█ █ ███ █
█▄▄▄▄▄█ ▄▀█▀▄ █▄▄▄▄▄█
▄▄▄ ▄▄▄▄█ █ ▄▄▄ ▄
▄ ▄█ ▀▄▄▄ ▀█ █▄█ █▄█▄
▄▀▄█▀▄▀█▀ █▀█▄█▀▄▄
▄▄▄▄▄▄▄ ██ ▄ ▀ ▄▀▄▄▄
█ ▄▄▄ █ █▄█ ▄ █ ▄ ▄█▄
█ ███ █ ▄▄ █ █▄█ ▀█▀▄
█▄▄▄▄▄█ ██▄█▀█▄█▀▀▄█▄
| [reply] |
|
| [reply] |
|
|
|
After thinking about the problem a bit, you could, in theory, use "colspan" for a simplistic run-length compression:
#!/usr/bin/env perl
use strict;
use warnings;
use Text::QRCode;
my $qr = Text::QRCode->new()->plot("YAPH");
my $pixelsize = 15;
my $black = '<td width="' . $pixelsize . 'px" height="' . $pixelsize .
+ 'px" bgcolor="black"></td>';
my $white = '<td width="' . $pixelsize . 'px" height="' . $pixelsize .
+ 'px" bgcolor="white"></td>';
print '<table border="0">', "\n";
my $firstline = 1;
my $saved = 0;
foreach my $line (@{$qr}) {
print "<tr>";
my $firstelem = 1;
my $width = 0;
my $color = '';
foreach my $elem (@{$line}) {
if($firstline) {
# First line, no compression. This sets the correct column
+ width for all columns
if($elem eq '*') {
print $black;
} else {
print $white;
}
} else {
if($firstelem) {
$color = $elem;
$width = 1;
$firstelem = 0;
} else {
if($color eq $elem) {
$width++;
$saved++;
} else {
my $realcol = 'white';
if($elem eq '*') {
$realcol = 'black';
}
print '<td colspan="' . $width . '" height="' . $p
+ixelsize . 'px" bgcolor="' . $realcol . '"></td>';
$color = $elem;
$width = 1;
}
}
}
if(!$firstline) {
# print last element of the current line
my $realcol = 'white';
if($elem eq '*') {
$realcol = 'black';
}
print '<td colspan="' . $width . '" height="' . $pixelsize
+ . 'px" bgcolor="' . $realcol . '"></td>';
}
$firstline = 0;
}
print "</tr>\n";
}
print '<\table">', "\n";
print '<!-- run length compression saved ', $saved, ' table fields-->'
+, "\n";
I've run into a formatting problem doing this (probably some stupid oversight on my part), but it might be worth the effort if you need to "compress" your code to the 64K limit in PerlMonks. See What is PerlMonks post size limit?
perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'
| [reply] [d/l] [select] |
|
#!/usr/bin/env perl
use strict;
use warnings;
use Text::QRCode;
my $qr = Text::QRCode->new()->plot("YAPH");
my $pixelsize = 15;
print '<table border="0" cellspacing="0" cellpadding="0">', "\n";
my $firstline = 1;
my $saved = 0;
foreach my $line (@{$qr}) {
print "<tr>";
my $firstelem = 1;
my $width = 0;
my $color = '';
my $firstblockinline = 1;
foreach my $elem (@{$line}) {
if($firstline) {
# First line, no compression. This sets the correct column
+ width for all columns
my $realcol = mapColor($elem);
print '<td width="' . $pixelsize . 'px" height="' . $pixel
+size . 'px" bgcolor="' . $realcol . '"></td>';
} else {
if($firstelem) {
$color = $elem;
$width = 1;
$firstelem = 0;
} else {
if($color eq $elem) {
$width++;
$saved++;
} else {
my $realcol = mapColor($color);
print '<td colspan="' . $width . '" ';
if($firstblockinline) {
print 'height="' . $pixelsize . 'px" ';
$firstblockinline = 0;
}
print 'bgcolor="' . $realcol . '"></td>';
$color = $elem;
$width = 1;
}
}
}
}
if(!$firstline) {
# print last element of the current line
my $realcol = mapColor($color);
print '<td colspan="' . $width . '" height="' . $pixelsize . '
+px" bgcolor="' . $realcol . '"></td>';
}
print "</tr>\n";
$firstline = 0;
}
print '</table>', "\n";
print '<!-- run length compression saved ', $saved, ' table fields-->'
+, "\n";
sub mapColor {
my ($inval) = @_;
if($inval eq '*') {
return 'black';
}
return 'white';
}
Which means i can turn it into this:
#!/usr/bin/env perl
use strict;
use warnings;
use GD;
my $img = GD::Image->newFromPng('tentacle.png', 0);
my ($w, $h) = $img->getBounds();
my $pixelsize = 15;
print '<table border="0" cellspacing="0" cellpadding="0">', "\n";
my $saved = 0;
for(my $y = 0; $y < $h; $y++) {
print "<tr>";
my $firstelem = 1;
my $width = 0;
my $color = '';
my $firstblockinline = 1;
for(my $x = 0; $x < $w; $x++) {
my $index = $img->getPixel($x, $y);
my ($r,$g,$b) = $img->rgb($index);
my $elem = sprintf("#%02X%02X%02X", $r, $g, $b);
if(!$y) {
# First line, no compression. This sets the correct column
+ width for all columns
print '<td width="' . $pixelsize . 'px" height="' . $pixel
+size . 'px" bgcolor="' . $elem . '"></td>';
} else {
if($firstelem) {
$color = $elem;
$width = 1;
$firstelem = 0;
} else {
if($color eq $elem) {
$width++;
$saved++;
} else {
print '<td colspan="' . $width . '" ';
if($firstblockinline) {
print 'height="' . $pixelsize . 'px" ';
$firstblockinline = 0;
}
print 'bgcolor="' . $color . '"></td>';
$color = $elem;
$width = 1;
}
}
}
}
if($y) {
# print last element of the current line
print '<td colspan="' . $width . '" height="' . $pixelsize . '
+px" bgcolor="' . $color . '"></td>';
}
print "</tr>\n";
}
print '</table>', "\n";
print '<!-- run length compression saved ', $saved, ' table fields-->'
+, "\n";
Which results in the ability to display (low res) colorful images in PerlMonks, using nothing but allowed HTML tags:
<!-- run length compression saved 709 table fields-->
perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'
| [reply] [d/l] [select] |
Re: Shameless plug and QR japh
by etj (Deacon) on Mar 23, 2022 at 14:36 UTC
|
First, congrats on cracking XS (not easy) and getting OpenCV working!
This is amazingly good timing, as a PDL user is just looking to get OpenCV working in the context of PDL (see https://github.com/PDLPorters/pdl/issues/362 and latest state of play on https://sourceforge.net/p/pdl/mailman/message/37627428/).
We've identified that a vital next step would be to make an Alien::OpenCV that captures whether OpenCV is installed on the user's machine, and would need a ->cflags and ->libs method for use in other modules' Makefile.PL etc. Do you feel like making such a module, and/or helping the user get further with their OpenCV adventure? | [reply] |
|
An Alien module would be great, but I am totally alien to Alien. Also, OpenCV discourage you from using pkg-config (which is more or less standard with any *nix dev tools package), instead they suggest cmake (which is a hit+miss for both M$ and *nix). See this forum post. In fact the only failed test I have for Image::DecodeQR::WeChat is on a M$ machine with no cmake. Installing OpenCV binaries on M$ does not include cmake.
So, an Alien module would be a breaze on *nix but it will be a real headache for M$ windows. But I am prepared to give it a try in about a month's time.
In the meantime, I include some code, at the bottom, I use to detect OpenCV flags in above module's Makefile.PL.
Regarding compiling OpenCV code as part of XS. There's a trick suggested by Botje @ #perl: do not include any OpenCV code or headers in the XS file. Place them in separate C++ files, and add an entry function which does not depend on OpenCV data structures and headers at all. So that excludes at the moment passing or returning said data structures lest they are casted to anonymous pointers which is a fair solution. Then link that C++ code to XS careful with function name mangling. Including OpenCV headers in XS clashes with Perl's internals (seed and ... cv come to mind and also the linked posts mention it, plus Inline::CPP + OpenCV = problems. I have used that trick successfully, so at least there is a way. I explain the process and various subleties at the pod of Image::DecodeQR::WeChat. Having C++ code linking to XS is another tough to crack. But solvable.
bw, bliako
| [reply] [d/l] [select] |
|
Fair enough. There's an Alien::cmake3 you could use to get cmake available in more places.
| [reply] |
|
|