仿小米水印v0.1

查看 70|回复 6
作者:cgl556   
[table][tr][td]

蓝奏云:https://wwi.lanzoup.com/i8qo30xn2kqf
自己写的,把图片或者戴图片的文件夹拖进去就行了,但是
[color=]图片一定要带信息
(时间、拍摄数据、相机名字(地理位置,可有可无))不戴是会报错的(我没写,所以会什么效果都没有)微信传的原图其实也会把图片信息去掉的(所以如果是微信传图到电脑,不要用“图片”传,用文件传(点了+号向右划就能看到了))
watermark文件夹里面的logo可以改,名字替换就好了
---就花了几个小时,不太完善,因为赶着找实习。短期内应该就没时间优化了---比如拖进去,在执行的时候做没有效果,完成的时候也没有做效果,如果图片信息不完整也没警告。。
效果图如下

开源了 有大佬的有兴趣的话可以优化(不知道能不能放,如果不能请删了)下面是命令行版代码
[Python] 纯文本查看 复制代码# By:仰晨
# 文件名:批量加大水印
# 时 间:2023/5/10 18:43
from PIL import Image, ImageDraw, ImageFont, ImageOps
import piexif
import os
def add_watermark(jpg_file, camera_name=None, black=False, is_img=False, place="在宇宙一颗蔚蓝的星球上", logo='yc.png'):
    """
    添加水印
    :param logo: 默认相机的logo
    :param place: 当照片里面读取不到照片的时候就用这个值代替,默认值“在宇宙一颗蔚蓝的星球上"
    :param camera_name: 相机名字 因为有一些相机名字不是正常的手机名字,这时可以传入自定义
    :param black: 如果想水印背景是黑色 就填true  默认false
    :param is_img: 如果是单张图片就填True,默认False
    :param jpg_file: 每张图片的路径
    :return: 无(图片直接到本地)
    """
    background_color = (255, 255, 255) if not black else (0, 0, 0)
    fill_color = (0, 0, 0) if not black else (255, 255, 255)
    small_text_color = (134, 134, 134)if not black else (255, 255, 255)
    # 读取图片和EXIF信息
    image_path = os.path.join(jpg_file[0], jpg_file[1])
    image = Image.open(image_path)
    exif_data = image.info.get("exif")
    data = piexif.load(exif_data)
    # 根据方向信息旋转图片
    orientation = data["0th"].get(piexif.ImageIFD.Orientation)
    if orientation is not None and orientation != 1:
        print(orientation)
        image = ImageOps.exif_transpose(image)
    # 获取图片尺寸
    width, height = image.size
    # 计算新图片高度 长度+11.5%
    new_height = int(height * 1.115)    # 还原竖屏
    # new_height = int(height * 1.156)  # 还原横屏
    # 创建新的白色背景画布
    canvas = Image.new("RGB", (width, new_height), background_color)
    # 将原始图片粘贴到新画布上
    canvas.paste(image, (0, 0))
    # 获取新画布的宽高
    canvas_width, canvas_height = canvas.size
    # 添加文字
    def add_text(text, size, x, y, font=r"C:\Windows\Fonts\msyh.ttc", fill=fill_color, old_x=False):
        """
        :param text: 要添加的文字
        :param size: 文字大小:按图片高的比例1很小,10和图片水印一样大
        :param x: 文字在水印的位置,0在最左边 10在最右边
        :param y: 文字在水印的位置,0在最上面 10在最下面
        :param fill: 文字颜色 可接收参数格式:(255, 0, 0)# 红色、'#0000FF80'# 半透明蓝色、'black'、# 黑色、(128, 128, 128) # 中灰色
        :param old_x: 如果是True 表示传入的值是上次返回的,可以直接用的
        :param font:字体文件路径:
                    默认微软雅黑细体C:\Windows\Fonts\msyhl.ttc,
                    微软雅黑常规:C:\Windows\Fonts\msyh.ttc
                    机型和拍摄参数用微软雅黑粗体
                    黑体C:\Windows\Fonts\simhei.ttf是小米默认的但是间距很宽
        :return:x的值
        """
        draw = ImageDraw.Draw(canvas)
        text = text
        size = int(height * 0.01 * size)
        font = ImageFont.truetype(font, size=size)  # 请确保你有正确的字体文件路径"arial.ttf", size=20
        # textbbox() 方法返回一个包括文本四个顶点坐标的元组: (左侧x坐标,  顶部y坐标,  右侧x坐标,  底部y坐标)
        _, _, text_width, text_height = draw.textbbox((x, y), text, font=font)
        if not old_x:
            x = (width - text_width) * 0.1 * x
        y = height + ((new_height - height) - text_height) * 0.1 * y
        draw.text((x, y), text, fill=fill, font=font)
        return x
    # 加一竖
    def add_line(x):
        """
        给水印图片和文字之间的分割线
        :param x: 已经计算好的要贴在目标图片的x轴的坐标
        :return:
        """
        # 创建一个10*240,颜色为#ddd的新图像 # 直接计算b_img缩放后的高度
        line_width, line_height = int(canvas_height * 0.05 / 30), int(canvas_height * 0.04)
        line_img_color = (211, 211, 211) if not black else (51, 51, 51)
        line_img = Image.new("RGB", (line_width, line_height), color=line_img_color)
        # 粘贴b_img到a_img右下角
        location = (int(x - line_img.size[0] * 6), int(canvas_height * 0.97 - line_img.size[1]))
        canvas.paste(im=line_img, box=location)
    def add_logo(x):
        b_img = Image.open(r"watermark/"+logo)
        # 计算b_img缩放后的高度 和 调整b_img大小
        new_b_height = int(canvas_height * 0.045)
        b_img = b_img.resize((int(b_img.width * new_b_height / b_img.height), new_b_height))
        # 粘贴b_img到a_img右下角
        location = (int(x - b_img.size[0] - b_img.size[0] * 0.5), int(canvas_height * 0.974 - b_img.size[1]))
        try:
            canvas.paste(im=b_img, box=location, mask=b_img)  # 参数“mask”来确保透明通道被正确应用,没有该参数透明就会变成黑色
        except ValueError:
            canvas.paste(im=b_img, box=location)  # 有些水印没有透明通道
    try:
        # 获取快门速度or曝光时间
        shutter_speed_value = data["Exif"][piexif.ExifIFD.ExposureTime]
        shutter_speed = f"1/{round(float(shutter_speed_value[1]) / float(shutter_speed_value[0]))}"
        # 获取光圈值
        aperture_value = data['Exif'][piexif.ExifIFD.FNumber]
        aperture_fstop = aperture_value[0] / aperture_value[1]
        aperture = f'f/{aperture_fstop:.2f}'
        # 获取 ISO 感光度
        iso = "IOS" + str(data["Exif"][piexif.ExifIFD.ISOSpeedRatings])
        def get_gps():
            """
            获取拍摄位置
            :return: 如果有就返回gps位置,没有就写字
            """
            try:
                gps_N = data['GPS'][2]
                gps_N = f"{gps_N[0][0] / gps_N[0][1]:02.0f}°{int(gps_N[1][0] / gps_N[1][1])}\'{int(gps_N[2][0] / gps_N[2][1])}\"N"
                gps_E = data['GPS'][4]
                gps_E = f"{gps_E[0][0] / gps_E[0][1]:02.0f}°{int(gps_E[1][0] / gps_E[1][1])}\'{int(gps_E[2][0] / gps_E[2][1])}\"E"
                return f"{gps_N}  {gps_E}"
            except KeyError:
                return place
        # 机型
        x_value = add_text(data["0th"][piexif.ImageIFD.Model].decode('utf-8') if camera_name is None else camera_name,
                           size=2.1, x=0.35, y=3, font=r"C:\Windows\Fonts\msyhbd.ttc")
        # 拍摄时间
        add_text(data["0th"][piexif.ImageIFD.DateTime].decode('utf-8'), size=1.55, x=x_value, fill=small_text_color,
                 old_x=True, y=6.5)
        # 拍摄参数
        x_value = add_text(f"{aperture} {shutter_speed} {iso}", size=2.1, x=9.5, y=3.2,
                           font=r"C:\Windows\Fonts\msyhbd.ttc")
        # 拍摄位置
        add_text(get_gps(), size=1.55, x=x_value, fill=small_text_color, old_x=True, y=6.7)
        # 分割线
        add_line(x_value)
        # logo
        add_logo(x_value)
    except KeyError:
        print(jpg_file[1] + "获取的参数不全")
        return
    # 如果方向标记非1,则调整图像
    if orientation != 1:
        # 根据方向标记旋转或翻转图像
        if orientation == 2:
            canvas = canvas.transpose(Image.FLIP_LEFT_RIGHT)
        elif orientation == 3:
            # 上下翻转
            canvas = canvas.rotate(180)
        elif orientation == 4:
            canvas = canvas.transpose(Image.FLIP_TOP_BOTTOM)
        elif orientation == 5:
            canvas = canvas.rotate(-90).transpose(Image.FLIP_LEFT_RIGHT)
        elif orientation == 6:
            # 旋转
            canvas = canvas.transpose(Image.ROTATE_90)
        elif orientation == 7:
            canvas = canvas.rotate(90).transpose(Image.FLIP_LEFT_RIGHT)
        elif orientation == 8:
            canvas = canvas.rotate(90)
    # 保存图片(保留EXIF信息)
    if is_img:  # 如果是单张图片
        canvas.save(os.path.join(jpg_file[0], jpg_file[1].replace('.jpg', '-加水印.jpg')), "JPEG", exif=exif_data)
    else:
        canvas.save(os.path.join(jpg_file[0] + "加水印", jpg_file[1]), "JPEG", exif=exif_data)
if __name__ == '__main__':
    folder_path = input('请输入jpg图片或文件夹路径')
    # 是否是文件夹
    if os.path.isdir(folder_path):
        # 要新建文件夹?
        if not os.path.isdir(folder_path + "加水印"):
            os.mkdir(folder_path + "加水印")
        # 拿到文件夹下面的jpg文件直接调用方法
        [add_watermark([folder_path, f]) for f in os.listdir(folder_path) if f.endswith('.jpg')]
    # 是否是单个文件
    elif os.path.isfile(folder_path) and folder_path.endswith('.jpg'):  #
        add_watermark([os.path.dirname(folder_path), os.path.basename(folder_path)], is_img=True)  # , black=True, camera_name="Mi 11 Pro"
    else:
        print('路径有误')

水印, 图片

fineetec   

不折腾了,唉
玉龙山泉   

这个干嘛用?
Brenda   

等会去试试
freedover   

有创意的小应用
358234200   

嗯嗯,你给一人发一部13U吧
odinchu   

666,强制徕卡
您需要登录后才可以回帖 登录 | 立即注册