python2.7 + wxpython +zbar 实现二维码的生成、嵌入和提取

python2.7 + wxpython +zbar 实现二维码的生成、嵌入和提取


2018年7月25日23:40:43 【原创】
目录:python 编程博客 索引

1. 运行环境

最近打算用 python 写一个工具打算实现二维码的生成、嵌入和读取功能。

但是搭建环境问题确实难住了我

通过查阅各种资料,发现 zbar 模块不支持 python3,只好使用 python2 来实现

但是还有一个问题就是 python2.6 和 python 2.7 是不同的

网上有一种说法是 zbar 最高支持 python2.6,但是我仍然在国外的网站发现了 zbar-0.10.win32-py2.7_2.msi,可以支持 python2.7

通过实践,python2.6 及其所配套的 zbar-0.10.win32-py2.6.exe 在 为 win7 32位的环境中跑不起来

最终还是选择使用 python2.7 和 zbar-0.10.win32-py2.7_2.msi

在这里,实现环境算是很简单了,只需要下载了 python2.7 和 zbar-0.10.win32-py2.7_2.msi 即可

另外我的环境使用了 wxpython 图形化模块,安装方法也很简单

pip install wxpython
pip install pyinstaller

wxpython 已经更新到版本 4.0 了,在这里的小软件中的环境是可以兼容使用的

打包成文件

pyinstaller -F -w -i C:\Users\John\Desktop\pythonworkV4.0\icon.ico C:\Users\John\Desktop\pythonworkV4.0\setup.py

另外,为了方便大家使用 zbar 环境,我把使用到的虚拟机环境上传到百度云网盘中

以上环境所使用到的工具都在这里
链接:https://pan.baidu.com/s/1t4xUub250SjLJ2WRc32HLg 提取码:n922

有问题可以留言或者私聊我QQ 781670201。
有代做毕业设计软件的可以联系,不贵。我写过的部分毕业设计在博客链接中有。


2. 功能简介

  1. 功能

    1. 自定义二维码信息内容
    2. 将信息生成二维码
    3. 将二维码嵌入到某个图片的右下角
    4. 在图片上提取二维码信息并输出到主界面
  2. 主界面

    在这里插入图片描述

  3. 代码下载

    python2.7 + wxpython +zbar 实现二维码的生成、嵌入和提取

3. 程序代码

# coding:UTF-8
import wx
import zbar
from PIL import Image

'''
pil处理图片,验证,处理 
大小,格式 过滤 
压缩,截图,转换 
     
图片库最好用Pillow 
还有一个测试图片test.jpg, 一个log图片,一个字体文件 
'''

#图片的基本参数获取  
try:  
    from PIL import Image, ImageDraw, ImageFont, ImageEnhance  
except ImportError:  
    import Image, ImageDraw, ImageFont, ImageEnhance
import qrcode
import os

wildcard1 = u" w图像文件 (*.png)|*.bmp|"    \
           "All files (*.*)|*.*"


global img

fileDir = os.getcwd()

class MultiTextFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, u"基于二维码的数字水印嵌入及提取工具",size=(600, 400))
        #wx.Frame.__init__(self,image,parent = None,id = -1, pos = wx.DefaultPosition,title = u"隐藏信息的图片为:",size=(800,600))
        panel = wx.Panel(self, -1)
        font = wx.Font(12, wx.ROMAN, wx.NORMAL, wx.BOLD, False)
        font.SetPointSize(14)

        font2 = wx.Font(12, wx.ROMAN, wx.NORMAL, wx.BOLD, False)
        
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add((-1, 15))
        hbox1 = wx.BoxSizer(wx.HORIZONTAL)

        # st1
        st1 = wx.StaticText(panel, label=u'待隐藏水印')
        st1.SetFont(font2)
        hbox1.Add(st1, flag=wx.RIGHT, border=10)
        self.tc = wx.TextCtrl(panel, size=(400,80),style=wx.TE_MULTILINE | wx.TE_RICH2) # wx.HSCROLL 不自动换行
        self.tc.SetFont(font)
        hbox1.Add(self.tc, proportion=1, flag=wx.EXPAND)
        vbox.Add(hbox1, proportion=1, flag=wx.LEFT | wx.RIGHT | wx.EXPAND, border=10)

        vbox.Add((-1, 15))

        hbox3 = wx.BoxSizer(wx.HORIZONTAL)

        # st2
        st2 = wx.StaticText(panel, label=u'提取二维码')
        st2.SetFont(font2)
        hbox3.Add(st2,flag=wx.RIGHT, border=10)
        self.tc2 = wx.TextCtrl(panel, size=(400,80),style=wx.TE_MULTILINE | wx.TE_RICH2 | wx.TE_READONLY) # wx.HSCROLL 不自动换行
        self.tc2.SetFont(font)
        hbox3.Add(self.tc2, proportion=1, flag=wx.EXPAND)
        vbox.Add(hbox3, proportion=1, flag=wx.LEFT | wx.RIGHT | wx.EXPAND,border=10)

        vbox.Add((-1, 20))

        hbox5 = wx.BoxSizer(wx.HORIZONTAL)

        # btn1
        btn1 = wx.Button(panel, label=u'生成二维码', size=(120, 30))
        btn1.SetFont(font)
        hbox5.Add(btn1)

        # btn2
        btn2 = wx.Button(panel, label=u'添加水印', size=(120, 30))
        btn2.SetFont(font)
        hbox5.Add(btn2, flag=wx.LEFT | wx.BOTTOM, border=50)

        # btn3
        btn3 = wx.Button(panel, label=u'提取二维码信息', size=(150, 30))
        btn3.SetFont(font)
        hbox5.Add(btn3, flag=wx.LEFT | wx.BOTTOM, border=50)
        
        vbox.Add(hbox5, flag=wx.ALIGN_CENTER_HORIZONTAL  | wx.RIGHT, border=10)

        panel.SetSizer(vbox)

        self.Bind(wx.EVT_BUTTON, self.creat_logo, btn1)
        self.Bind(wx.EVT_BUTTON, self.logo_watermark, btn2)
        self.Bind(wx.EVT_BUTTON, self.put_message, btn3)
        self.b = 0


    def creat_logo(self, event):
        qr = qrcode.QRCode(
          version=7,
          error_correction=qrcode.constants.ERROR_CORRECT_L,
          box_size=3,
          border=4
        )
        #global messages
        #self.tc.Clear()
        self.tc2.Clear()
        tc1data = self.tc.GetValue()
        qr.add_data(tc1data)
        qr.make(fit=True)
        
        img = qr.make_image()

        if tc1data == '':
            self.messagedata = '文本框内容不可以为空'
            dlg = wx.MessageDialog(self, self.messagedata, caption='提示:', style = wx.OK|wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            return
        
        else:
            with wx.FileDialog(self, "保存文件", defaultDir=os.getcwd(),defaultFile="QR_code.png", wildcard=wildcard1,
                           style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as fileDialog:
                if fileDialog.ShowModal() == wx.ID_CANCEL:
                    return     # the user changed their mind

                # save the current contents in the file
                global pathname
                pathname = fileDialog.GetPath()
                img.save(pathname)
                
                image = wx.Image(pathname,wx.BITMAP_TYPE_PNG) 
                self.frame3 = Frame2(image)
                self.frame3.Show()
                #self.SetTopWindow(self.frame)
                return True
                        

    def logo_watermark(self, event):  
        ''''' 
        添加一个图片水印,原理就是合并图层,用png比较好 
        '''
        with wx.FileDialog(self, "打开二维码文件", defaultDir=os.getcwd(), defaultFile="QR_code.png", wildcard=wildcard1,
                           style=wx.FD_OPEN) as fileDialog_logo:
                if fileDialog_logo.ShowModal() == wx.ID_CANCEL:
                    return     # the user changed their mind
                logo_path = fileDialog_logo.GetPath()

                
        with wx.FileDialog(self, "打开载体文件", defaultDir=os.getcwd(), defaultFile="gaomin.png", wildcard=wildcard1,
                           style=wx.FD_OPEN) as fileDialog:
                if fileDialog.ShowModal() == wx.ID_CANCEL:
                    return     # the user changed their mind

                
                # save the current contents in the file
                pathname2 = fileDialog.GetPath()

                im = Image.open(pathname2)  # 打开载体

                baseim = im
                baseim = Image.open(pathname2)  # 打开载体
                logoim = Image.open(logo_path)  
                bw, bh = baseim.size  
                lw, lh = logoim.size
                baseim.paste(logoim, (bw-lw, bh-lh))
                
                with wx.FileDialog(self, "保存隐藏信息的文件", defaultDir=os.getcwd(), defaultFile="secret.png", wildcard=wildcard1,
                           style=wx.FD_SAVE) as fileDialog2:
                    if fileDialog2.ShowModal() == wx.ID_CANCEL:
                        return     # the user changed their mind

                    # save the current contents in the file
                    pathname3 = fileDialog2.GetPath()



                    baseim.save(pathname3, 'png')  
                    #print(u'logo水印组合成功')

                    image3 = wx.Image(pathname3,wx.BITMAP_TYPE_PNG)
                    #wx.StaticBitmap(self,-1,wx.BitmapFromImage(image3))
                    w = image3.GetWidth()
                    h = image3.GetHeight()
                    image3.Rescale(w/2,h/2) #修改显示大小
                    
                    self.frame3 = Frame3(image3)
                    self.frame3.Show()
                    #self.SetTopWindow(self.frame)
                    return True

    #水印提取 
    def put_message(self, event):
    '''
    先按照一个比例对图片剪裁,然后再压缩到指定尺寸 
    一个图片 16:5 ,压缩为 2:1 并且宽为200,就要先把图片裁剪成 10:5,然后在等比压缩 
    '''
		qua=95
		# (im, dst_w, dst_h, qua=95):  
		with wx.FileDialog(self, "打开待提取信息的图像文件", defaultDir=os.getcwd(), defaultFile="secret.png", wildcard=wildcard1,
						   style=wx.FD_OPEN) as fileDialog:
			if fileDialog.ShowModal() == wx.ID_CANCEL:
				return     # the user changed their mind
		# save the current contents in the file
			pathname4 = fileDialog.GetPath()
			im = Image.open(pathname4)  #image 对象  
			ori_w,ori_h = im.size  
			x,y = 159, 159
			#裁剪  
			box = (ori_w-x,ori_h-y,ori_w,ori_h)
			#所包围的图像,crop方法与php中的imagecopy方法大为不一样  
			newIm = im.crop(box)
			print(u"提取完成")
			'''
			with wx.FileDialog(self, "保存提取的二维码的文件", defaultFile="QR_code.png", wildcard=wildcard1,
						   style=wx.FD_SAVE) as fileDialog2:
				if fileDialog2.ShowModal() == wx.ID_CANCEL:
					return     # the user changed their mind

				# save the current contents in the file
				pathname5 = fileDialog2.GetPath()
			
				newIm.save(pathname5, 'PNG')  
				print("old size  %s  %s"%(ori_w, ori_h))  
				print(u"提取完成")  
			'''
			# 二维码识别
			scanner = zbar.ImageScanner()
			scanner.parse_config('enable')
			#img = Image.open(pathname5).convert('L')
			img = newIm.convert('L')
			w, h = img.size
			zimg = zbar.Image(w, h, 'Y800', img.tobytes())
			# 判断是二维码
			raw = img.tobytes()
			a_bytes = raw[1:10].encode('hex')
			# print a_bytes
			if a_bytes == 'ffffffffffffffffff':
				dlg = wx.MessageDialog(self, u"二维码水印信息提取成功", u"提示", wx.OK | wx.ICON_INFORMATION)
				dlg.ShowModal()
				dlg.Destroy()
				scanner.scan(zimg)
				for s in zimg:
					# print s.type,s.data
					print u'提取的二维码水印信息为:%s' % s.data
					self.tc2.Clear()
					self.tc2.AppendText(s.data)
					'''
					image = wx.Image(pathname5,wx.BITMAP_TYPE_PNG) 
					self.frame3 = Frame2(image)
					self.frame3.Show()
					'''
			else:
				print u"图像中未保存二维码水印信息"
				dlg = wx.MessageDialog(self, u"图像中未保存二维码水印信息", u"提示", wx.OK | wx.ICON_ERROR)
				dlg.ShowModal()
				dlg.Destroy()


class Frame2(wx.Frame):
    def __init__(self,image,parent = None,id = -1, pos = wx.DefaultPosition,title = u"二维码图片为:",size=(400,400)):
        #显示图片
        tmp = image.ConvertToBitmap() 
        size = tmp.GetWidth(),tmp.GetHeight()
        wx.Frame.__init__(self,parent,id,title,pos,(400,400))
        self.bmp = wx.StaticBitmap(parent=self, bitmap=tmp)

class Frame3(wx.Frame):
    def __init__(self,image,parent = None,id = -1, pos = wx.DefaultPosition,title = u"隐藏信息的图片为:",size=(800,600)):
        #显示图片
        tmp = image.ConvertToBitmap() 
        size = tmp.GetWidth(),tmp.GetHeight()
        wx.Frame.__init__(self,parent,id,title,pos,(800,600))
        self.bmp = wx.StaticBitmap(parent=self, bitmap=tmp)



class MyApp(wx.App):
    def __init__(self):
        # 重构__init__方法,将错误信息重定位到文件中;
        # 默认redirect=True,输出到StdOut或StdError;
        # 为防止程序因错误一闪而过无法捕捉信息,可在
        # 控制台中使用python -i example.py来运行程序。
        wx.App.__init__(self, redirect=False, filename=r"./IO.txt")

    def OnInit(self):
        frame = MultiTextFrame()
        frame.Show(True)
        return True



def main():
    app = MyApp()
    app.MainLoop()


if __name__ == "__main__":
    main()
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值