Skip to content

Commit

Permalink
adjusted codes and distributed to PyPI
Browse files Browse the repository at this point in the history
  • Loading branch information
x-hw committed Sep 9, 2016
1 parent a45072a commit cc12688
Show file tree
Hide file tree
Showing 13 changed files with 895 additions and 132 deletions.
675 changes: 675 additions & 0 deletions LICENSE.md

Large diffs are not rendered by default.

Empty file added MyQR/__init__.py
Empty file.
120 changes: 120 additions & 0 deletions MyQR/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
from MyQR.mylibs import theqrmodule
from PIL import Image

# Alignment Pattern Locations
alig_location = [
(6, 18), (6, 22), (6, 26), (6, 30), (6, 34), (6, 22, 38), (6, 24, 42), (6, 26, 46), (6, 28, 50), (6, 30, 54), (6, 32, 58), (6, 34, 62), (6, 26, 46, 66), (6, 26, 48, 70), (6, 26, 50, 74), (6, 30, 54, 78), (6, 30, 56, 82), (6, 30, 58, 86), (6, 34, 62, 90), (6, 28, 50, 72, 94), (6, 26, 50, 74, 98), (6, 30, 54, 78, 102), (6, 28, 54, 80, 106), (6, 32, 58, 84, 110), (6, 30, 58, 86, 114), (6, 34, 62, 90, 118), (6, 26, 50, 74, 98, 122), (6, 30, 54, 78, 102, 126), (6, 26, 52, 78, 104, 130), (6, 30, 56, 82, 108, 134), (6, 34, 60, 86, 112, 138), (6, 30, 58, 86, 114, 142), (6, 34, 62, 90, 118, 146), (6, 30, 54, 78, 102, 126, 150), (6, 24, 50, 76, 102, 128, 154), (6, 28, 54, 80, 106, 132, 158), (6, 32, 58, 84, 110, 136, 162), (6, 26, 54, 82, 110, 138, 166), (6, 30, 58, 86, 114, 142, 170)
]

def combine(ver, qr_name, bg_name, colorized, contrast, brightness, save_place):
from PIL import ImageEnhance, ImageFilter

qr = Image.open(qr_name)
qr = qr.convert('RGBA') if colorized else qr

bg0 = Image.open(bg_name).convert('RGBA')
con = contrast if contrast else 1.0
bg0 = ImageEnhance.Contrast(bg0).enhance(con)
bri = brightness if brightness else 1.0
bg0 = ImageEnhance.Brightness(bg0).enhance(bri)

if bg0.size[0] < bg0.size[1]:
bg0 = bg0.resize((qr.size[0]-24, (qr.size[0]-24)*int(bg0.size[1]/bg0.size[0])))
else:
bg0 = bg0.resize(((qr.size[1]-24)*int(bg0.size[0]/bg0.size[1]), qr.size[1]-24))

bg = bg0 if colorized else bg0.convert('1')

aligs = []
if ver > 1:
aloc = alig_location[ver-2]
for a in range(len(aloc)):
for b in range(len(aloc)):
if not ((a==b==0) or (a==len(aloc)-1 and b==0) or (a==0 and b==len(aloc)-1)):
for i in range(3*(aloc[a]-2), 3*(aloc[a]+3)):
for j in range(3*(aloc[b]-2), 3*(aloc[b]+3)):
aligs.append((i,j))

for i in range(qr.size[0]-24):
for j in range(qr.size[1]-24):
if not ((i in (18,19,20)) or (j in (18,19,20)) or (i<24 and j<24) or (i<24 and j>qr.size[1]-49) or (i>qr.size[0]-49 and j<24) or ((i,j) in aligs) or (i%3==1 and j%3==1) or (bg0.getpixel((i,j))[3]==0)):
qr.putpixel((i+12,j+12), bg.getpixel((i,j)))

qr_name = os.path.join(save_place, os.path.splitext(os.path.basename(bg_name))[0] + '_qrcode.png')
qr.resize((qr.size[0]*3, qr.size[1]*3)).save(qr_name)
return qr_name

def run():
import argparse
argparser = argparse.ArgumentParser()
argparser.add_argument('WORDs', help = 'The words to produce you QR-code picture, like a URL or a sentence. Please read the README file for the supported characters.')
argparser.add_argument('-v', '--version', type = int, choices = range(1,41), help = 'The version means the length of a side of the QR-Code picture. From little size to large is 1 to 40.')
argparser.add_argument('-l', '--level', choices = list('LMQH'), help = 'Use this argument to choose an Error-Correction-Level: L(Low), M(Medium) or Q(Quartile), H(High). Otherwise, just use the default one: H')
argparser.add_argument('-p', '--picture', help = 'the picture e.g. example_pic.jpg')
argparser.add_argument('-c', '--colorized', action = 'store_true', help = "Produce a colorized QR-Code with your picture. Just works when there is a correct '-p' or '--picture'.")
argparser.add_argument('-con', '--contrast', type = float, help = 'A floating point value controlling the enhancement of contrast. Factor 1.0 always returns a copy of the original image, lower factors mean less color (brightness, contrast, etc), and higher values more. There are no restrictions on this value. Default: 1.0')
argparser.add_argument('-bri', '--brightness', type = float, help = 'A floating point value controlling the enhancement of brightness. Factor 1.0 always returns a copy of the original image, lower factors mean less color (brightness, contrast, etc), and higher values more. There are no restrictions on this value. Default: 1.0')
args = argparser.parse_args()

tempdir = os.path.join(os.path.expanduser('~'), '.myqr')

try:
# the default version depends on WORDs and level
# init as 0
ver = args.version if args.version else 0
# the default level is Q
ecl = args.level if args.level else 'H'

if not os.path.exists(tempdir):
os.makedirs(tempdir)

try:
ver, qr_name = theqrmodule.get_qrcode(ver, ecl, args.WORDs, tempdir)
except TypeError:
qr_name = args.picture = None

if args.picture and args.picture[-4:]=='.gif':
print('it takes a while, please wait for minutes...')

import imageio

im = Image.open(args.picture)
im.save(os.path.join(tempdir, '0.png'))
while True:
try:
seq = im.tell()
im.seek(seq + 1)
im.save(os.path.join(tempdir, '%s.png' %(seq+1)))
except EOFError:
break

imsname = []
for s in range(seq+1):
bg_name = os.path.join(tempdir, '%s.png' % s)
imsname.append(combine(ver, qr_name, bg_name, args.colorized, args.contrast, args.brightness, tempdir))

ims = [imageio.imread(pic) for pic in imsname]
qr_name = os.path.splitext(os.path.basename(args.picture))[0] + '_qrcode.gif'
imageio.mimsave(qr_name, ims)
elif args.picture:
qr_name = combine(ver, qr_name, args.picture, args.colorized, args.contrast, args.brightness, os.getcwd())
elif qr_name:
qr = Image.open(qr_name)
qr_name = os.path.basename(qr_name)
qr.resize((qr.size[0]*3, qr.size[1]*3)).save(qr_name)

if qr_name:
print('Succeed! \nCheck out your ' +str(ver) + '-' + str(ecl) + ' QR-code at', os.path.abspath(qr_name))
except:
raise
finally:
import shutil
if os.path.exists(tempdir):
shutil.rmtree(tempdir)
#
if __name__ == '__main__':
run()
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
14 changes: 7 additions & 7 deletions mylibs/theqrmodule.py → MyQR/mylibs/theqrmodule.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# -*- coding: utf-8 -*-

from mylibs import data, ECC, structure, matrix, draw
from MyQR.mylibs import data, ECC, structure, matrix, draw

supported_chars = r'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ·,.:;+-*/\~!@#$%^&`[]()?_{}|'

# ver: Version (from 1 to 40)
# ver: Version (from 0 to 40) 0 means default
# ecl: Error Correction Level (L,M,Q,H)
# get a qrcode picture of 3*3 pixels per module
def get_qrcode(ver, ecl, str, save_place):
# ver == 0: default that is depending on str and ecl
if ver not in range(41):
print('WARNING: Version Error! Please choose a version from 1 to 40!')
if ecl not in 'LMQH':
print('WARNING: Version Error! Please choose a version from 0 to 40!')
elif ecl not in 'LMQH':
print('WARNING: Level Error! Please choose one of L,M,Q,H!')
if any(i not in supported_chars for i in str):
print('WARNING: Input Error! Please read the README file for the supported characters!!')
elif any(i not in supported_chars for i in str):
print('WARNING: Input Error! Some characters are not supported.')
else:
# Data Coding
ver, data_codewords = data.encode(ver, ecl, str)
Expand All @@ -28,5 +28,5 @@ def get_qrcode(ver, ecl, str, save_place):
# Get the QR Matrix
qrmatrix = matrix.get_qrmatrix(ver, ecl, final_bits)

# Draw the picture and Save it, then return the absolute path
# Draw the picture and Save it, then return the real ver and the absolute name
return ver, draw.draw_qrcode(save_place, qrmatrix)
48 changes: 30 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

* **update (160908)**: added a **web** version - [amazing-qrcode](http://www.amazing-qrcode.com/) *(made by [Maras0830](https://github.com/Maras0830))*

* **update (160910)**: distributed to **PyPI** - [MyQR](https://pypi.python.org/pypi/MyQR/1.0.0) !


## Overview 概述
Expand Down Expand Up @@ -55,7 +57,17 @@ It can generate <u>common qr-code</u>, <u> artistic qr-code (black & white or co

![](https://github.com/sylnsfar/qrcode/blob/master/example/zootopia_qrcode.gif)![](https://github.com/sylnsfar/qrcode/blob/master/example/daftpunktocat-guy_qrcode0.gif)



## Install 安装

```python
pip(3) install myqr
```

(ps. If you haven't install **myqr**, you should `python(3) myqr.py` instead of `myqr` blow.)



## Usage 用法

Expand All @@ -64,10 +76,10 @@ It can generate <u>common qr-code</u>, <u> artistic qr-code (black & white or co
![](https://github.com/sylnsfar/qrcode/blob/master/example/0.png)

```
python myqr.py [-h]
[-v {1,2,3,...,40}]
[-l {L,M,Q,H}]
Words
myqr [-h]
[-v {1,2,3,...,40}]
[-l {L,M,Q,H}]
Words
```

* Use argument `-h` for help.
Expand All @@ -79,7 +91,7 @@ python myqr.py [-h]

```markdown
#1 url
python myqr.py https://github.com
myqr https://github.com
```

* **Simplest way**: Just input a URL or a sentence, then get your QR-Code in the current directory.
Expand All @@ -90,7 +102,7 @@ python myqr.py https://github.com

```markdown
#2 -v, -l
python myqr.py https://github.com -v 10 -l Q
myqr https://github.com -v 10 -l Q
```

* The **default** length of a side of QR-Code depends on the numbers of words you input. And the **default** level (Error Correction Level) is **H** (the highest).
Expand All @@ -108,14 +120,14 @@ python myqr.py https://github.com -v 10 -l Q

![](https://github.com/sylnsfar/qrcode/blob/master/example/1.png)![](https://github.com/sylnsfar/qrcode/blob/master/example/2.png)

python myqr.py [-h]
[-v {1,2,3,...,40}]
[-l {L,M,Q,H}]
[-p picture_file]
[-c]
[-con contrast]
[-bri brightness]
Words
myqr [-h]
[-v {1,2,3,...,40}]
[-l {L,M,Q,H}]
[-p picture_file]
[-c]
[-con contrast]
[-bri brightness]
Words
* arguments `-h`, `-v` and `-l` is as mentioned above.

参数 `-h`, `-v``-l` 如上文述。
Expand All @@ -126,7 +138,7 @@ python myqr.py https://github.com -v 10 -l Q

```markdown
#1 -p
python myqr.py https://github.com -p github.jpg
myqr https://github.com -p github.jpg
```

* The `-p` is to combine the QR-Code with the following picture which is in the same directory as the program. The resulting picture is <u>**black and white** </u> by default.
Expand All @@ -140,7 +152,7 @@ python myqr.py https://github.com -p github.jpg

```markdown
#2 -c
python myqr.py https://github.com -p github.jpg -c
myqr https://github.com -p github.jpg -c
```

* The `-c` is to make the resulting picture **colorized**.
Expand All @@ -153,7 +165,7 @@ python myqr.py https://github.com -p github.jpg -c

```markdown
#3 -con, -bri
python myqr.py https://github.com -p github.jpg [-c] -con 1.5 -bri 1.6
myqr https://github.com -p github.jpg [-c] -con 1.5 -bri 1.6
```

* The `-con` flag changes the contrast of the picture - a low number corresponds to low contrast and a high number to high contrast. Default: 1.0.
Expand Down
110 changes: 3 additions & 107 deletions myqr.py
Original file line number Diff line number Diff line change
@@ -1,111 +1,7 @@
# -*- coding: utf-8 -*-

import argparse, os
from mylibs import theqrmodule
from PIL import Image
# To be used just when PyInstaller is not installed

# Alignment Pattern Locations
alig_location = [
(6, 18), (6, 22), (6, 26), (6, 30), (6, 34), (6, 22, 38), (6, 24, 42), (6, 26, 46), (6, 28, 50), (6, 30, 54), (6, 32, 58), (6, 34, 62), (6, 26, 46, 66), (6, 26, 48, 70), (6, 26, 50, 74), (6, 30, 54, 78), (6, 30, 56, 82), (6, 30, 58, 86), (6, 34, 62, 90), (6, 28, 50, 72, 94), (6, 26, 50, 74, 98), (6, 30, 54, 78, 102), (6, 28, 54, 80, 106), (6, 32, 58, 84, 110), (6, 30, 58, 86, 114), (6, 34, 62, 90, 118), (6, 26, 50, 74, 98, 122), (6, 30, 54, 78, 102, 126), (6, 26, 52, 78, 104, 130), (6, 30, 56, 82, 108, 134), (6, 34, 60, 86, 112, 138), (6, 30, 58, 86, 114, 142), (6, 34, 62, 90, 118, 146), (6, 30, 54, 78, 102, 126, 150), (6, 24, 50, 76, 102, 128, 154), (6, 28, 54, 80, 106, 132, 158), (6, 32, 58, 84, 110, 136, 162), (6, 26, 54, 82, 110, 138, 166), (6, 30, 58, 86, 114, 142, 170)
]
from MyQR.__main__ import run

argparser = argparse.ArgumentParser()
argparser.add_argument('WORDs', help = 'The words to produce you QR-code picture, like a URL or a sentence. Please read the README file for the supported characters.')
argparser.add_argument('-v', '--version', type = int, choices = range(1,41), help = 'The version means the length of a side of the QR-Code picture. From little size to large is 1 to 40.')
argparser.add_argument('-l', '--level', choices = list('LMQH'), help = 'Use this argument to choose an Error-Correction-Level: L(Low), M(Medium) or Q(Quartile), H(High). Otherwise, just use the default one: H')
argparser.add_argument('-p', '--picture', help = 'the picture e.g. example_pic.jpg')
argparser.add_argument('-c', '--colorized', action = 'store_true', help = "Produce a colorized QR-Code with your picture. Just works when there is a correct '-p' or '--picture'.")
argparser.add_argument('-con', '--contrast', type = float, help = 'A floating point value controlling the enhancement of contrast. Factor 1.0 always returns a copy of the original image, lower factors mean less color (brightness, contrast, etc), and higher values more. There are no restrictions on this value. Default: 1.0')
argparser.add_argument('-bri', '--brightness', type = float, help = 'A floating point value controlling the enhancement of brightness. Factor 1.0 always returns a copy of the original image, lower factors mean less color (brightness, contrast, etc), and higher values more. There are no restrictions on this value. Default: 1.0')
args = argparser.parse_args()

def combine(qr_name, bg_name, colorized, contrast, brightness, save_place):
from PIL import ImageEnhance, ImageFilter

qr = Image.open(qr_name)
qr = qr.convert('RGBA') if colorized else qr

bg0 = Image.open(bg_name).convert('RGBA')
con = contrast if contrast else 1.0
bg0 = ImageEnhance.Contrast(bg0).enhance(con)
bri = brightness if brightness else 1.0
bg0 = ImageEnhance.Brightness(bg0).enhance(bri)

if bg0.size[0] < bg0.size[1]:
bg0 = bg0.resize((qr.size[0]-24, (qr.size[0]-24)*int(bg0.size[1]/bg0.size[0])))
else:
bg0 = bg0.resize(((qr.size[1]-24)*int(bg0.size[0]/bg0.size[1]), qr.size[1]-24))

bg = bg0 if colorized else bg0.convert('1')

aligs = []
if ver > 1:
aloc = alig_location[ver-2]
for a in range(len(aloc)):
for b in range(len(aloc)):
if not ((a==b==0) or (a==len(aloc)-1 and b==0) or (a==0 and b==len(aloc)-1)):
for i in range(3*(aloc[a]-2), 3*(aloc[a]+3)):
for j in range(3*(aloc[b]-2), 3*(aloc[b]+3)):
aligs.append((i,j))

for i in range(qr.size[0]-24):
for j in range(qr.size[1]-24):
if not ((i in (18,19,20)) or (j in (18,19,20)) or (i<24 and j<24) or (i<24 and j>qr.size[1]-49) or (i>qr.size[0]-49 and j<24) or ((i,j) in aligs) or (i%3==1 and j%3==1) or (bg0.getpixel((i,j))[3]==0)):
qr.putpixel((i+12,j+12), bg.getpixel((i,j)))

qr_name = os.path.join(save_place, os.path.splitext(bg_name)[0] + '_qrcode.png')
qr.resize((qr.size[0]*3, qr.size[1]*3)).save(qr_name)
return qr_name

try:
# the default version depends on WORDs and level
# init as 0
ver = args.version if args.version else 0
# the default level is Q
ecl = args.level if args.level else 'H'

if not os.path.exists('temp'):
os.makedirs('temp')
save_place = os.path.abspath('.') if not args.picture else os.path.join(os.path.abspath('.'), 'temp')
try:
ver, qr_name = theqrmodule.get_qrcode(ver, ecl, args.WORDs, save_place)
except TypeError:
qr_name = args.picture = None

if args.picture and args.picture[-4:]=='.gif':
print('it takes a while, please wait for minutes...')

import imageio

im = Image.open(args.picture)
im.save('temp/0.png')
while True:
try:
seq = im.tell()
im.seek(seq + 1)
im.save('temp/%s.png' %(seq+1))
except EOFError:
break

imsname = []
for s in range(seq+1):
bg_name = 'temp/%s.png' % s
imsname.append(combine(qr_name, bg_name, args.colorized, args.contrast, args.brightness, ''))

ims = [imageio.imread(pic) for pic in imsname]
qr_name = os.path.join(os.path.abspath('.'), os.path.splitext(args.picture)[0] + '_qrcode.gif')
imageio.mimsave(qr_name, ims)
elif args.picture:
qr_name = combine(qr_name, args.picture, args.colorized, args.contrast, args.brightness, os.path.abspath('.'))
elif qr_name:
qr = Image.open(qr_name)
qr.resize((qr.size[0]*3, qr.size[1]*3)).save(qr_name)

if qr_name:
print('Succeed! \nCheck out your ' +str(ver) + '-' + str(ecl) + ' QR-code at', qr_name)
except:
raise
finally:
import shutil
if os.path.exists('temp'):
shutil.rmtree('temp')
run()
Loading

0 comments on commit cc12688

Please sign in to comment.