【python初学者日记】用PIL批量给HEIC格式的照片,添加拍摄日期、拍摄地点的水印戳

news2024/9/20 6:23:41

【python初学者日记】用PIL批量给HEIC格式的照片,添加拍摄日期、拍摄地点的水印戳

  • 问题合集
    • 1、读取 HEIC 格式照片的拍摄信息
    • 2、将已知坐标转码成具体省市地址的文字信息
    • 3、将文字添加到HEIC格式的照片上
  • 问题解决
    • 一、问题分析
    • 二、代码实现

最近在整理手机相册,发现以前在拍摄的时候,不喜欢给照片带水印,现在想在照片上面打上拍摄时间+地点的水印戳。之前有写过将exl中的内容,添加到照片的功能,所以这次的就简单多了。

问题合集

1、读取 HEIC 格式照片的拍摄信息

2、将已知坐标转码成具体省市地址的文字信息

3、将文字添加到HEIC格式的照片上

问题解决

一、问题分析

1、读取HEIC格式照片的拍摄信息:
现有版本python3.11,用exifread库即可将苹果导出的HEIC格式照片的拍摄信息。
2、将已知坐标转码成具体省市地址的文字信息:
这里我使用的是百度地图调起API,参考说明如图:
在这里插入图片描述传送门: https://lbsyun.baidu.com/index.php?title=uri/api/web
注:此方法无需注册开发者,可以直接使用。
3、将文字添加到HEIC格式的照片上:
这里偷个懒,我之前有写过将exl中的内容,添加到照片的功能,此处稍作修改即可实现功能。

二、代码实现

1、代码如下:

# -*- coding: utf-8 -*-
# 读取图片属性中的拍摄日期,并给图片添加拍摄日期、地点
import datetime
import os

import exifread
import requests
import json

from PIL import Image, ImageDraw, ImageFont, ImageFilter
from pillow_heif import register_heif_opener

register_heif_opener()

# 示例已知经纬度,利用百度地图,输出当前省市等信息
# http://api.map.baidu.com/geocoder?location=30.204891666666665,120.19970833333333&coord_type=gcj02&output=json


my_font = r"C:\Windows\Fonts\SIMYOU.TTF"

startTime_program = datetime.datetime.now()  # 开始时间


# 定义一个换算函数,功能:将输入的度(时)分秒,经过换算,返回度(时)。例如输入[30, 12, 1761/100],返回30.204891666666665
def Conversion(data):
    temp_data = [ele.strip() for ele in (str(data).replace('[', '').replace(']', '').split(','))]
    new_data = eval(temp_data[-1]) / 3600 + int(temp_data[1]) / 60 + int(temp_data[0])
    return new_data


# 在给定的照片中,提取时间戳:仅保留年月日;经纬度:通过在百度api上查找到省市,然后返回”年/月/日 省 市“的值。
def get_stamp(pic):
    # exifread读出的经纬度是列表[度,分,秒],需要转换成单位为度的小数
    # 获取图片拍摄时间
    time = pic['Image DateTime']
    # print(time) # 打印时间戳
    time_stamp = str(time)[0:4] + "/" + str(time)[5:7] + "/" + str(time)[8:10]  # 从拍摄时间中,提取日期
    # print(time_stamp) # 打印新格式的时间戳
    latitude = Conversion(pic['GPS GPSLatitude'])  # 从图片提取纬度并将单位度分秒换算成度
    # print(latitude)  # 打印纬度
    longitude = Conversion(pic['GPS GPSLongitude'])  # 从图片提取经度并将单位度分秒换算成度
    # print(longitude) # 打印经度
    coordinates = str(latitude) + ',' + str(longitude)
    # print(coordinates) # 打印坐标
    query_adStr = "http://api.map.baidu.com/geocoder?location=" + coordinates + "&coord_type=gcj02&output=json"  # 注意此链接,根据百度开发者平台,此处改为以json格式输出,更方便后续解码
    resp = requests.get(query_adStr)  # 向服务器请求数据
    url_text = resp.content.decode()  # 读取源文件字节流,随后将该字节流编码为Unicode编码
    location_data = json.loads(url_text)  # 用于解码 JSON 数据。该函数返回 Python 字段的数据类型
    address = location_data.get('result').get(
        'addressComponent')  # 在代码中找到addressComponent字段,此条可去浏览器粘贴链接查看:http://api.map.baidu.com/geocoder?location=30.204891666666665,120.19970833333333&coord_type=gcj02
    province = address.get('province')  # 从获取的地址信息中,找到省份的值
    city = address.get('city')  # 从获取的地址信息中,找到城市的值
    stamp = str(time_stamp) + '\n' + ' ' + str(province[:-1]) + ' ' + str(city[:-1])  # 将时间戳、地址戳按格式整合
    return stamp  # 返回新戳


# 定义在已给地址批量读图的信息,并存到数组里,并返回数组.修正:改为字典方式输出,即文件路径名:stamp
def pics_add_stamps(path):
    stamps = {}
    for each_pic in os.listdir(path):
        if os.path.splitext(each_pic)[1] == '.heic':
            each_pic_Path = path + "\\" + each_pic
            pic_data = exifread.process_file(open(each_pic_Path, 'rb'))
            temp_stamp = get_stamp(pic_data)
            stamp_key = each_pic_Path
            stamp_data = temp_stamp
            stamps[stamp_key] = stamp_data
    return stamps


# 读照片,并将提取到的时间位置信息,加到照片上,并存到新的文件夹
def deal_pic_1by1(pic, text, pic_newPath):
    # 打开初始图片
    image = Image.open(pic)
    # 设置字体
    size = 100  # 定义字体大小
    font = ImageFont.truetype(my_font, size)  # 设置字体的格式、大小
    # 创建Draw对象:
    draw = ImageDraw.Draw(image)
    # 计算文字要放置的位置:image.size:像素(宽,高);image.size[0]是指照片的宽,即距离左边最大水平距离;image.size[1]是指照片的高,即距离上边最大垂直距离
    site_x = image.size[0] - 650  # 距离左边水平距离:650像素(自定义,可根据自己喜好调整)
    site_y = image.size[1] - 320  # 距离上边垂直距离:320像素(自定义,可根据自己喜好调整)
    site = (site_x, site_y)  # 距离左上角距离

    # 输出文字(可以连续写入):
    draw.text(site, text, font=font, fill='#fff')  # 设置放置位置、文本内容、字体、颜色
    # 模糊并保存:
    image.filter(ImageFilter.BLUR)

    namePath = os.path.basename(pic)

    if not os.path.exists(pic_newPath):  # 判断存放图片的文件夹是否存在
        os.makedirs(pic_newPath)  # 若图片文件夹不存在就创建
    # 两种方式保存:
    # image.save(pic_newPath + "/" + namePath)  # 以默认的图片格式来存储:保留原图所有信息,但是会压缩文件大小,文件保存时间和原图拍摄保存的时间一致
    image.save(pic_newPath + "/" + namePath,
               "PNG")  # 缺省原图大部分信息,如拍照时间地点等,生成新的图片,由于save不能直接将heic转换为其他格式,所以保存的格式仍然是和原图一样,heic


if __name__ == "__main__":

    pic_path = r"F:\qin_ipad_pic"  # 待处理的图片所在路径
    pic_path_new = f"F:\\qin_ipad_pic\\qin_ipad_pic-NEW"  # 处理好的图片要保存的路径

    n = 0
    i = 1
    # 将pic_path路径下的heic照片提取信息,返回值保存到pic_stamps,类型是字典{图片1路径:图片1时间戳+地点戳;图片2路径:图片2时间戳+地点戳,...}
    pic_stamps = pics_add_stamps(pic_path)
    # print("pic_stamps的类型是:", type(pic_stamps))
    for item in pic_stamps:
        data = pic_stamps.get(item)  # dict.get(item)
        deal_pic_1by1(item, data, pic_path_new)
        n += 1

    print('共有{}个HEIC文件'.format(n))

endTime_program = datetime.datetime.now()  # 结束时间
print('本次处理照片一共用了:%0.2f秒' % (endTime_program - startTime_program).seconds)

2、运行结果如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/13494.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网站SEO优化有哪些要点?

1、网站关键词优化 对于网站关键词,每一个站长朋友应该很熟悉了,所谓的关键词就是对网站的一种简单而又综合性的描述,网站关键词分析也叫做关键词定位。seo教程认为网站关键词分析是进行SEO优化的最重要的一环。关键词分析首先要做的就是根据…

Go语言入门【6】切片

切片 在go语言中,切片是对数组的抽象,数组在声明时指定了长度之后就不可再进行改变,在特定场景下数组就不适用,所以就有了切片类型,切片就是“动态数组”,和数组相比,切片的长度是不固定的&…

mybatis逆向工程的实现

在本地创建一个test数据库,并在test数据库中创建一个student表;表中的数据如下: 创建表: DROP TABLE IF EXISTS student; CREATE TABLE student ( studentID int NOT NULL AUTO_INCREMENT, StudnetName varchar(20) CHARACTER SET…

Linux 之 Ubuntu 下安装配置ARM交叉编译器(工具链)的简单整理

Linux 之 Ubuntu 下安装配置ARM交叉编译器(工具链)的简单整理 目录 Linux 之 Ubuntu 下安装配置ARM交叉编译器(工具链)的简单整理 一、简单介绍 二、下载 arm 交叉编译安装工具包,并安装到虚拟机中 一、简单介绍 Linux/Ubuntu 开发的一些知识整理,方…

微服务基础设施选型

微服务基础设施架构 全貌 优先级 微服务框架模式 核心 服务注册、服务发现、服务路由 模式1-嵌入SDK 优点 架构简单,天然支持高性能、高可用维护简答,无需维护独立的Proxy节点 缺点 应用侵入,需要集成SDK,并联动升级多语言重…

强化学习 Lesson2 学习笔记

Lesson2-1 MDP、Q表格 一、强化学习MDP四元组<S,A,P,R> S:state 状态A:action 动作R:reward 奖励 r[st,at]P:probability 状态转移概率 p[st1,rt|st,at] 强化学习是一系列决策的过程,通过当前的环境状态和收到的奖励来决定下一次执行的动作 ​ Model-based: P函数和R函…

零售业迎来全新发展,这个技术少不了

零售业在创新方面比较频繁&#xff0c;创新是推动零售业发展的动力&#xff0c;这可以让零售业具有了外在的生命力和内在的动力。创新要求零售商从内部建立机制&#xff0c;以创新的心态经营管理。 现在&#xff0c;零售商陷入泥潭。其中一个原因是&#xff0c;他们失去了创新能…

Docker详解(一)

文章目录参考资料一、Docker基本概念二、Docker安装1. 卸载旧版本2. 使用 Docker 仓库进行安装设置仓库安装 Docker Engine-Community卸载 Docker安装Docker CE 环境三、Docker命令1. Docker容器运行流程2. 镜像命令docker images 查看所有本地主机上的镜像docker search 搜索镜…

后端自学两个小时前端,究竟能做出什么东西?

又来给大家更文了&#xff0c;今天是微服务网关实战的第六篇。 今天的内容比较偏前端一点&#xff0c;主要是给大家换换口味&#xff0c;毕竟学一个东西学久了就想学点新东西休息一点&#xff0c;俗称换换脑子。 其实早就想学学前端看了&#xff0c;不过碍于工作繁忙&#xf…

冒泡排序和数据结构和算法可视化网站(及其一点小优化)

目录 一、冒泡排序的原理 二、动图演示原理 三、代码实现&#xff1a; 四、优化后的冒泡排序 五、算法演示网站 一、冒泡排序的原理 冒泡排序就是两两交换&#xff0c;第一趟排序可以得到最大值&#xff0c;那么第二趟排序就不用再比较最大值了&#xff0c;同样是两两交换…

电商后台管理系统(基于SSM + Vue + Restful + jquery + axios)

1.项目架构 2.config配置 JdbcConfig public class JdbcConfig {Value("${jdbc.driver}")private String driver;Value("${jdbc.url}")private String url;Value("${jdbc.username}")private String username;Value("${jdbc.password}&qu…

Spring——五大类注解和方法注解详解

文章目录1.Spring的创建2.Spring对象的存储3.将 Bean 对象通过配置文件注册到 Spring 当中4.从 Spring 中将 bean 对象读取出来并使用4.1 先得到 Spring 上下文对象4.2 再通过上下文对象提供的方法获取需要使用的baen对象4.3 使用bean对象[可选步骤]4.4 获取 getBean 的更多方法…

易基因技术推介|m1A RNA甲基化测序(MeRIP-seq/m1A-seq)

N1-甲基腺苷&#xff08;N1-methyladenosine&#xff0c;m1A&#xff09;是一种普遍存在于真核生物tRNA、rRNA和mRNA且可逆的转录后RNA修饰。基于高通量测序技术最新研究揭示m1A RNA修饰在基因调控和生物过程中的关键作用&#xff1a;对RNA稳定性和翻译起始等过程有着重要调节作…

Mybatis+Spring+SpringMVC及SSM整合

文章目录一、Mybatis&#xff08;一&#xff09;Mybatis简介1、Mybatis历史2、Mybatis特性3、Mybatis下载4、和其它持久化层技术对比&#xff08;二&#xff09;搭建Mybatis1、MySQL不同版本的注意事项2、创建Maven工程1、引入依赖3、创建MyBatis的核心配置文件3.1、核心配置文…

WRF进阶:WRF中Noah-MP地面方案中雪反照率的计算

Noah-MP简介 Noah-MP是以Noah-LSM为基础发展的一种多层模型&#xff0c;相对于Noah-LSM&#xff0c;它对于下垫面的冠层、土壤、积雪有了更多的拓展。 Noah-MP允许3层雪&#xff0c;对于雪的模拟有了极大的提升&#xff0c;同时&#xff0c;Polar-WRF中对Noah LSM和Noah MP中海…

IIS 部署HTTP 转 HTTPS完整版

1,准备SSL证书&#xff0c;阿里云有1年免费证书 免费证书有 20个&#xff0c;每年用一个就行 审核通过后下载 下载文件包含证书文件和密码 2.安装重定向模块 如果IIS上默认有安装Web平台安装程序&#xff0c;我们可以使用平台自动安装URL Rewrite重写工具&#xff0c;也可以…

Tomcat日志分割

使用cronolog日志切分工具 RPM包下载方法&#xff1a;在 rpmfind.net 上搜索cronolog选择对应RPM包复制下载链接即可 下载安装 cronolog yum install https://rpmfind.net/linux/epel/7/x86_64/Packages/c/cronolog-1.6.2-14.el7.x86_64.rpm -y验证是否安装成功及安装位置 使…

《安卓逆向》Magisk的编译踩坑记录-安装方法-分享魔改后的Magisk过root检测方法

为什么: 1.体验下如何编译面具源码 2.魔改面具-绕过更深的root检测 1.ubuntu 虚拟机下载地址 http://mirrors.aliyun.com/ubuntu-releases/20.04/github:https://github.com/topjohnwu/Magisk 编译根据这篇文章做好前缀下代码工作 https://zhuanlan.zhihu.com/p/385255256编…

图片1920x1080分辨率怎么调 ?图片如何修改分辨率?

图片是我们日常生活中经常需要使用到的东西&#xff0c;但是在使用图片时我们会遇到需要调图片分辨率的情况&#xff0c;有很多小伙伴对于图片分辨率这个概念并不了解&#xff0c;今天就来为大家具体介绍一下图片1920x1080怎么调以及怎么给图片修改分辨率&#xff0c;下面一起来…

美食杰项目 -- 首页(一)

目录前言&#xff1a;具体实现思路&#xff1a;步骤&#xff1a;1. 展示美食杰项目首页效果2. 引入 element-ui3. 头部代码4. 首页内容总代码5. 轮播图代码6. 已发布菜品内容代码7. 加载图片页面代码总结&#xff1a;前言&#xff1a; 本文给大家讲解&#xff0c;美食杰项目中…