重绘二维码

这个小软件用来把一张像素很低的二维码图片变成像素很高,而且大小很小的二维码图片。

使用之前需要提前处理小尺寸的二维码图片,不能留边缘,像这样:

只要能确保这张图片被划分成37x37份之后,生成的37x37个采样点,能够准确地落到每一个小方块上就行了。

ch01.py

import os
from PIL import Image, ImageDraw
from const import *
from ch02 import *
from datetime import datetime as datet
import errno


aa = r'D:\0003\1122.jpg'

class CHHUI:
    def __init__(self, path_full):
        self.path_full = path_full
        # 初始化二维列表,用于存储颜色信息
        self.list_ks = [[] for _ in range(37)]
        self.dict_ks = [{} for _ in range(37)]

    # 打开图片
    def open_tu(self):
        print('001')
        # 获取当前工作目录
        self.workpath = os.getcwd()
        print(f'当前脚本工作目录为:{self.workpath}\n')

        # 分离目录和文件名
        self.mulu, self.full_filename = os.path.split(self.path_full)
        print(f"mulu:{self.mulu}")

        # 分离文件名和扩展名
        self.filename, self.extension = os.path.splitext(self.full_filename)
        print(f"文件名:{self.filename}")
        print(f"扩展名:{self.extension}")
        self.original_image = Image.open(self.path_full)
        print('成功打开图片\n')

    # 初始化操作图片
    def initial_tu(self):
        print('002')
        # 转换为灰度图像,以减少计算
        self.gray_image = self.original_image.convert('L')
        # 图片的尺寸
        width, height = self.gray_image.size
        print(f'原图宽高:[{width}, {height}]')
        # 确定间隔,赋值覆盖
        self.aa = width / 37 # 单位小方块的长度
        self.aaa = self.aa/2 # 采样点的偏移量(使落到中心)
        self.bb = height / 37
        self.bbb = self.bb/2
        print(f'采样点水平间隔:{self.aa}\n垂直间隔:{self.bb}')
        print('\n图片已转为灰度图像,采样点已完成初始化\n')

    # 开始对图片采样
    def cai_tu(self):
        print('003')
        color = '-'
        # 遍历图片的每个像素
        for iy in range(37):  # 0-36
            for ix in range(37):  # 0-36
                # 确定采样点
                xy = ((self.aaa+ix*self.aa),(self.bbb+iy*self.bb))
                # .getpixel()方法需要传入一个规范书写的元组,如果传入不带括弧的元祖则会被视为传入了多个位置参数!
                pixel_value = self.gray_image.getpixel(xy) # 从指定像素获取灰度值
                # 灰度值小于230则为黑色
                if pixel_value < YYY:
                    color = 1
                else:
                    color = 0
                self.list_ks[iy].append(color)
                x = xy[0]
                y = xy[1]
                self.dict_ks[iy][ix] = (x, y, pixel_value, color)
        print('已完成37x37个采样点的遍历\n')

    # 打开一个txt文件用于记录采样数据
    def write_tu(self):
        print('004')
        # 定义你想要创建的目录的路径  
        directory_path = os.path.join(self.workpath, 'work')
        
        # 使用os.makedirs()创建目录  
        try:  
            os.makedirs(directory_path)  
            print(f"目录 '{directory_path}' 已成功创建。")  
        except OSError as e:  
            if e.errno == errno.EEXIST:  # 如果目录已存在,则忽略这个错误  
                print(f"目录 '{directory_path}' 已存在。")  
            else:  
                print(f"在创建目录时发生错误: {e}")

        # 创建一个 datetime 对象
        now = datet.now()
        # 使用 strftime 方法将 datetime 对象格式化为字符串
        formatted_date = str(now.strftime("%Y-%m-%d %H-%M-%S"))
        print(formatted_date)

        Txt_1 = os.path.join(directory_path, f'{formatted_date}_c3.txt')
        with open(Txt_1, 'w') as file:
            for row in self.list_ks:
                file.write(' '.join(map(str, row)) + '\n')
                # ' '.join将每行的整数列表转换为由空格分隔的字符串, map(str, row) 将整数列表转换为字符串列表

        Txt_2 = os.path.join(directory_path, f'{formatted_date}_xx3.txt') # os.path.join(self.mulu, 'x3.txt')
        with open(Txt_2, 'w') as file2:
            ii = 0
            for i in range(37):
                for j in range(37):
                    ii = self.dict_ks[i][j]
                    # print(ii)
                    iii = str(ii)
                    file2.write(f'{i}, {j}, {iii}\n')  # 写入文件并添加换行符
        print('写完了\n')

    def draw_new(self):
        print('005')
        img_width = BLOCK_SIZE * 37 + BORDER * 2
        img_height = BLOCK_SIZE * 37 + BORDER * 2

        # 创建一张空白图片,背景色为白色
        self.image = Image.new('RGBA', (img_width, img_height),color=(255, 255, 255, 0))

        # 创建一个可以在给定图片上绘图的对象
        self.draw = ImageDraw.Draw(self.image)
        print(f'将要绘制尺寸{BORDER*2 + BLOCK_SIZE*37}像素的方形图片(含{BORDER}像素的出血边)')

        inf = str(MODE)
        # 解读快速指令,选择模式
        if inf[1] == '1':
            if inf[0] == '1':
                self.fill_color1 = (0, 0, 0, 255) # 黑色-黑色
                print('黑色为黑色')
            else:
                self.fill_color1 = (255, 255, 255, 255) # 白色
                print('黑色为白色')
        else:
            self.fill_color1 = (0, 0, 0, 0) # 黑色-透明
            print('黑色为透明')

        if inf[3] == '1':
            if inf[2] == '0':
                self.fill_color0 = (255, 255, 255, 255) # 原色
                print('白色为白色')
            else:
                self.fill_color0 = (0, 0, 0, 255) # 反相
                print('白色为黑色')
        else:
            self.fill_color0 = (255, 255, 255, 0) # 透明
            print('白色为透明')


        # 遍历列表并绘制矩形
        for j in range(37):
            for i in range(37):
                if self.list_ks[j][i] == 1: # 识别为黑色矩形
                    # 绘制矩形,根据左上角坐标和右下角坐标
                    self.draw.rectangle([(BORDER+i*BLOCK_SIZE,BORDER+j*BLOCK_SIZE),  (BORDER+(1+i)*BLOCK_SIZE, BORDER+(1+j)*BLOCK_SIZE)], fill=self.fill_color1)
                elif self.list_ks[j][i] == 0: # 识别为白色矩形
                    # 绘制矩形,根据左上角坐标和右下角坐标
                    self.draw.rectangle([(BORDER+i*BLOCK_SIZE,BORDER+j*BLOCK_SIZE),  (BORDER+(1+i)*BLOCK_SIZE, BORDER+(1+j)*BLOCK_SIZE)], fill=self.fill_color0)
                else:
                    print('画手犯病了')
                # print(f'{j},{i},{fill_color}') 

        fill_fu = (0, 0, 0, 255)
        # 先画一个矩形做背景板
        self.draw.rectangle([(BORDER+BLOCK_SIZE*14,BORDER+BLOCK_SIZE*14), (BORDER+BLOCK_SIZE*(14+9),BORDER+BLOCK_SIZE*(14+9))], fill=fill_fu)

        # 先对原始的logo形状参数列表“缩放”,以确保尺寸适合新图像
        self.xy = scale_list(WX_LOGO_XY)
        print(self.xy)
        # 绘制logo
        for u in range(7):
            self.draw.ellipse(self.xy[u], fill= (0, 0, 0, WX_LOGO_AP[u]))
        for u in range(7,9):
            self.draw.polygon(self.xy[u], fill= (0, 0, 0, WX_LOGO_AP[u]))

        print('画完了\n')

    def save_new(self):
        print('006')

        # 保存图片
        self.image.save(rf'{self.mulu}\{self.filename}-1.5.png')
        print(f'图像已保存至\n{self.mulu}\{self.filename}-1.5.png\n')

    def work(self):
        self.open_tu()

        self.initial_tu()

        self.cai_tu()

        self.write_tu()

        self.draw_new()

        self.save_new()

cc3 = r'D:\BaiduSyncdisk\Pythonxx\重绘二维码\洛阳店-二维码.jpg'


if __name__ == '__main__':
    print('\n---2024.7.1---\n')
    aa = CHHUI(PATH_CC[2])
    aa.work()

    print('---end---')

ch02.py

from const import *

SCALE = (BLOCK_SIZE*6) / 1000
OFFSET = (BORDER+BLOCK_SIZE*15.5)

def scale_list(input_list):
    print(f"中心logo需要缩放{SCALE}倍\n从{OFFSET}开始")
    # 初始化一个新的列表来存储结果
    result = []
    ii = 0
    # 遍历输入列表中的每个元素
    for item in input_list:
        ii += 1
        # 检查元素是否是列表
        if isinstance(item, list):
            # 如果是列表,则创建一个新的列表,并遍历原始列表中的每个元组(这是由于我们事先知道它的结构)
            new_item = []
            for iuu in item:
                new_iuu = tuple(round(iu * SCALE + OFFSET) for iu in iuu)
                new_item.append(new_iuu)
            # 将新的列表添加到结果列表中
            result.append(new_item)
        elif isinstance(item, tuple):
            # 如果是元组,则创建一个新的元组,并遍历原始元组中的每个元素
            new_item = tuple(round(num * SCALE + OFFSET) for num in item)
            # 将新的元组添加到结果列表中
            result.append(new_item)
        # 每个一级元素会依次被追加到结果中,它们的顺序不会混乱
    return result  


if __name__ == '__main__':
    # 调用函数并打印结果
    scaled_WX_LOGO_XY = scale_list(WX_LOGO_XY)
    print('---运算完成---\n')
    print(scaled_WX_LOGO_XY)
    print('\n---end---')

const.py


BLOCK_SIZE = 40 # 单位尺寸
BORDER = 0 # 出血边

YYY  = 200

PATH_CC = [
r'重绘二维码\海特店1080.jpg',
r'D:\BaiduSyncdisk\Pythonxx\重绘二维码\海特店1080.jpg',
r'..\..\..\BaiduSyncdisk\Pythonxx\重绘二维码\洛阳店.png',
r'\BaiduSyncdisk\Pythonxx\重绘二维码\海特店1080.jpg'
]


PATH_CCC = [
r'重绘二维码\海特店1080.jpg',
r'D:\BaiduSyncdisk\Pythonxx\重绘二维码\海特店1080.jpg',
r'..\..\..\BaiduSyncdisk\Pythonxx\重绘二维码\洛阳店.png',
r'\BaiduSyncdisk\Pythonxx\重绘二维码\海特店1080.jpg'
]

# .. 表示上一级目录。这是一个特殊的路径元素,用于导航到当前目录的父目录。
# \ 是路径分隔符,用于分隔目录和文件名。


MODE = 1100
# 手动选择的模式,可以用于反转黑白、增加透明区域等

# 原始的logo坐标列表
WX_LOGO_XY = [
    (0,92,715,692),
    (376,338,974,896),
    (399,358,1000,870),
    (187,240,283,336),
    (434,240,530,336),
    (566,496,647,577),
    (760,496,841,577),
    [(143,628), (107,738), (240,670)],
    [(796,847), (874,814), (902,906)],
]

WX_LOGO_AP = [
0,
255,
0,
255,
255,
255,
255,
0,
0,
]
'''
WX_LOGO_AP = [
255,
0,
255,
0,
0,
0,
0,
255,
255,
]
'''


if __name__ == "__main__":

    print([i for i in range(10)])

    print(PATH_CCC[2])

    import os  
    print(f'当前脚本工作目录为:{os.getcwd()}\n')


    relative_path = PATH_CCC[2]
    if os.path.exists(relative_path):  
        print("文件存在")  
    else:  
        print("文件不存在")

摸鱼写的,基本功能是完整的,鸡肋功能是不少的。

 使用PS的魔棒和图层蒙版可以直接完成这个任务,但是会出现像素级别的误差。使用Illustrator可以没有像素级别的误差,但是效率很低,很费眼睛。

刚实现基础功能的时候,只写了一百多行。但是最后封装的时候突然多了很多想法,多增加了好几个功能,封装完之后总共三个脚本:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值