iPhone实况照片从Windows资源管理器复制的JPG+MOV无法正常还原到iPhone

背景:

之前使用的iPhone 15 Pro,使用的Windows资源管理器当中复制导出的实况照片,复制出来的格式例如IMG_0001.JPG, IMG_0001.MOV。之后手机就卖掉了。现在使用的iPhone 14 Pro Max,想要导回之前备份的实况照片。尝试使用爱思助手导入,虽然文件名都一样,但是仍然会报错:

是不是非常可恶?

但是使用爱思助手导出实况照片、出来的也是JPG+MOV。再重新导回去,发现一切正常。这么说一定是可以导入的,肯定是哪里出了问题。

咨询了爱思助手的客服,完全不理。没办法,只好自己研究咯。


解决方法:

读取MOV的EXIF信息

exiftool -a -u -g1 IMG_4676.MOV > IMG_4676.MOV.TXT

---- Keys ----字段下面的Content Identifier键值,就是JPG需要被修改成的Media Group UUID。也就是说,实际上,他们是依据这个uuid来判断视频和照片的关联。发现爱思助手导出的JPG和MOV正好也是对应的。所以实际上,针对资源管理器复制出来的,我们只要读取MOV的这个键值,把我们从JPG当中的Media Group UUID修改成一样的即可!

# MOV
Content Identifier              : E2523D1E-7C8A-423B-A8DB-53C8A073457F# JPG
Media Group UUID                : E2523D1E-7C8A-423B-A8DB-53C8A073457F

修改JPG当中的Media Group UUID

利用010Editor,打开文件,

直接把我原始照片里面的UUID替换掉。保存,即可导入成功。

这个UUID在文件中是明文TEXT存储的,在批量处理的情况下我们可以直接写一个脚本,利用exiftool读取出来MOV文件的Content Identifier,读取JPG的Media Group UUID,然后字节流模式打开JPG,在文件当中直接执行替换即可。

批量处理代码

Windows平台,下载exiftool:

https://exiftool.org/index.html

 

下载这个stand-alone的windows版本 。

下载下来的zip里面就是一个exe文件,重命名为exiftool.exe即可。

创建下面的python文件,把exe和这个python文件放到一个目录下面。

这个代码会将成对的JPG+MOV都拷贝到一个新的文件夹里面去。这样在原始文件夹里面的文件都是需要单独导入成静态照片和普通视频的。方便导入。在爱思助手里面就直接选择程序生成的LivePhoto文件夹。

建议在运行此代码之前,把资料先备份一份,以防万一。毕竟数据无价,谨慎操作。

import subprocess
import os
import shutil
from collections import defaultdict
import redef get_exif_data(file_path):try:process = subprocess.Popen(['exiftool', '-a', '-u', '-g1', file_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)stdout, stderr = process.communicate()if process.returncode != 0:print(f"Error: {stderr.strip()}")return Nonereturn stdout.strip()except FileNotFoundError:print("ExifTool is not installed or not found in the system path.")return Nonedef replace_uuid_in_jpg(jpg_file_path, old_uuid, new_uuid):with open(jpg_file_path, 'rb+') as jpg_file:file_content = jpg_file.read()updated_content = file_content.replace(old_uuid, new_uuid)jpg_file.seek(0)jpg_file.write(updated_content)jpg_file.truncate()def fix_jpg_for_ios_import(jpg_file_path, mov_file_path):exif_data = get_exif_data(mov_file_path).split(b'\n')content_identifier = Nonefor item in exif_data:if b'Content Identifier' in item:content_identifier = item.split(b':')[-1].strip()breakassert content_identifier is not Noneassert re.match(r'[0-9A-F]{8}(-[0-9A-F]{4}){3}-[0-9A-F]{12}', content_identifier.decode().upper())print(b'    ' + mov_file_path.encode() + b' | ' + content_identifier)exif_data = get_exif_data(jpg_file_path).split(b'\n')media_group_uuid = Nonefor item in exif_data:if b'Media Group UUID' in item or b'Content Identifier' in item:media_group_uuid = item.split(b':')[-1].strip()breakassert media_group_uuid is not Noneassert re.match(r'[0-9A-F]{8}(-[0-9A-F]{4}){3}-[0-9A-F]{12}', media_group_uuid.decode().upper())print(b'    ' + jpg_file_path.encode() + b' | ' + media_group_uuid)replace_uuid_in_jpg(jpg_file_path, media_group_uuid, content_identifier)def get_matching_files(directory):# 字典用于存储文件名前缀及其对应的后缀file_dict = defaultdict(set)for filename in os.listdir(directory):name, ext = os.path.splitext(filename)ext = ext.upper()# 只处理JPG和MOV文件if ext in {'.JPG', '.MOV'}:file_dict[name].add(ext)# 找到同时具有JPG和MOV后缀的文件名前缀matching_files = [name for name, exts in file_dict.items() if {'.JPG', '.MOV'} <= exts]return matching_filesif __name__ == '__main__':jpg_mov_path = 'I:/iPhone15Pro/202310__'file_prefixes = get_matching_files(jpg_mov_path)if not os.path.exists(os.path.join(jpg_mov_path, "LivePhoto")):os.mkdir(os.path.join(jpg_mov_path, "LivePhoto"))for file_prefix in file_prefixes:dst_jpg_path = os.path.join(jpg_mov_path, "LivePhoto", f"{file_prefix}.JPG")dst_mov_path = os.path.join(jpg_mov_path, "LivePhoto", f"{file_prefix}.MOV")shutil.move(os.path.join(jpg_mov_path, f"{file_prefix}.JPG"), dst_jpg_path)shutil.move(os.path.join(jpg_mov_path, f"{file_prefix}.MOV"), dst_mov_path)fix_jpg_for_ios_import(dst_jpg_path, dst_mov_path)

尝试过的方法

先用手上的iPhone 14 Pro Max随便拍两张照片,一个通过爱思导出,一个通过Windows资源管理器复制。对比一下出来的文件

很明显这两个文件大小差距很大。

MOV的话,文件大小一样,算了一下md5也一样。说明问题不在MOV上,JPG有问题。

先启动WSL,用binwalk,foremost看一下:

binwalk IMG_4676.JPGDECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             JPEG image data, JFIF standard 1.01
34            0x22            TIFF image data, big-endian, offset of first image directory: 8
2828          0xB0C           TIFF image data, big-endian, offset of first image directory: 8
2214234       0x21C95A        TIFF image data, big-endian, offset of first image directory: 8
binwalk 2024_05_22_12_44_IMG_4676.JPGDECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             JPEG image data, JFIF standard 1.01
30            0x1E            TIFF image data, big-endian, offset of first image directory: 8

foremost解出来两张图片。一张是全彩的正常图片(00000000.jpg),携带大量有效metadata(例如拍摄机型、时间、GPS等)。另一张点开直接看到的是灰度图像,没有看到有效的metadata。

修改文件名对应MOV,导入00000000.jpg也失败。

那么就用exiftool看一下。

exiftool -a -u -g1 IMG_4676.JPG > IMG_4676_bad.TXT
exiftool -a -u -g1 2024_05_22_12_44_IMG_4676.JPG > 2024_05_22_12_44_IMG_4676.JPG.TXT

使用Beyond Compare对比一下哪里出问题了。

存在大量不同。尤其是MP系列字段。因为本身存在2张照片

先不管MPF0字段。先尝试直接利用exiftool复制爱思助手导出图片的exif信息,直接覆盖过去:

exiftool -TagsFromFile 2024_05_22_12_44_IMG_4676.JPG -all:all IMG_4676.JPG

直接成功了!

说明只需要修改这里面不同的EXIF信息即可修复导入! 

尝试单独修改了几个项目,导入,无果。最终把目光看向了Apple字段下面的Media Group UUID

但是这个项目还不太好改,询问GPT,下面这个方法不好用。

exiftool -Apple:MediaGroupUUID="E2523D1E-7C8A-423B-A8DB-53C8A073457F" IMG_4676.JPG
Warning: [minor] Maker notes could not be parsed - IMG_4676.JPG0 image files updated1 image files unchanged

 尝试了其他的命令行修改的方法也不行。只能从文件实际内容去修改。

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

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

相关文章

Java18新特性

Java 18引入了若干新特性&#xff0c;以增强语言的功能性和性能。具体如下&#xff1a; 服务提供者接口&#xff08;Service Provider Interfaces, SPI&#xff09;&#xff1a;允许开发者为Java模块系统定义服务加载机制&#xff0c;从而能够更灵活地发现和加载服务实现。简单…

supOS NEO科技普惠!永久免费!亿元补贴

数字化转型正在全球蓬勃发展&#xff0c;工业操作系统进入大规模推广期&#xff01; 如果您正在被预算不足、技术团队不强、数字化投入产出比等问题困扰&#xff0c;supOS NEO是您最好的选择。 “让supOS走进万千工厂、千行百业&#xff01;让全世界每个工厂都能用得上supOS&am…

MM模块学习三 (创建采购申请)

采购信息记录比较特殊既是主数据又是货源 注&#xff1a;发票校验是指把供应商提供的发票做到系统里面产生一张应付凭证。 1.决定采购需求 采购需求可以手工创建&#xff08;ME51N&#xff09;&#xff0c;也可以自动产生&#xff08;比如&#xff1a;MRP&#xff0c;以及比如…

Java——内部类

1.什么是内部类 在一个类的里面再定义一个类&#xff0c;新定义的这个类就是内部类 举例&#xff1a;在Outer类的里面定义一个Inter类 class Outer{class Inter{} } 在这里Outer叫外部类&#xff0c;Inter叫内部类 内部类的应用场景 定义一个汽车类&#xff1a; 属性&#xf…

CTFshow之文件上传web入门151关-161关解密。包教包会!!!!

这段时间一直在搞文件上传相关的知识&#xff0c;正好把ctf的题目做做写写给自字做个总结&#xff01; 不过有一个确定就是所有的测试全部是黑盒测试&#xff0c;无法从代码层面和大家解释&#xff0c;我找个时间把upload-labs靶场做一做给大家讲讲白盒的代码审计 一、实验准…

2024-5-23 石群电路-14

2024-5-23&#xff0c;星期四&#xff0c;22:20&#xff0c;天气&#xff1a;晴&#xff0c;心情&#xff1a;晴。今天没有什么重要的事情发生&#xff0c;心情一如既往的平静&#xff0c;距离返校假期还有两天~~~。 今天观看了石群老师电路基础课程的第23/24个视频&#xff0…

Flutter 中的 AnimatedThere 小部件:全面指南

Flutter 中的 AnimatedThere 小部件&#xff1a;全面指南 在Flutter中&#xff0c;动画是增强用户体验的强大工具。虽然Flutter没有一个名为AnimatedThere的官方小部件&#xff0c;但我们可以根据常见的动画模式来构建一个类似的自定义动画效果。本文将指导您如何使用Flutter的…

Python 安装 ONNX Runtime (ORT)

1. Python 安装 ONNX Runtime 安装cpu版的 onnx runtime&#xff1a; pip install onnxruntime 安装gpu版的 onnx runtime&#xff08;cuda 11.x&#xff09;&#xff1a;(默认安装适用于cuda 11.8 的onnx runtime) pip install onnxruntime-gpu 安装gpu版的 onnx runtime…

真实案例分享,终端pc直接telnet不到出口路由器。

1、背景信息 我终端pc的网卡地址获取的网关是在核心交换机上&#xff0c;在核心交换机上telnet出口路由器可以实现。 所有终端网段都不能telnet出口路由器&#xff0c;客户希望能用最小的影响方式进行解决。 2、现有配置信息 终端的无线和有线分别在两个网段中&#xff0c;…

【课后练习分享】Java用户注册界面设计和求三角形面积的图形界面程序

目录 java编程题&#xff08;每日一练&#xff09;&#xff1a; 问题一的答案代码如下&#xff1a; 问题一的运行截图如下&#xff1a; 问题二的答案代码如下&#xff1a; 问题二的运行截图如下&#xff1a; java编程题&#xff08;每日一练&#xff09;&#xff1a; 1.…

大数据量MySQL的分页查询优化

目录 造数据查看耗时优化方案总结 造数据 我用MySQL存储过程生成了100多万条数据&#xff0c;存储过程如下。 DELIMITER $$ USE test$$ DROP PROCEDURE IF EXISTS proc_user$$CREATE PROCEDURE proc_user() BEGINDECLARE i INT DEFAULT 1;WHILE i < 1000000 DOINSERT INT…

【安装笔记(目录)】

安装笔记-系列文章目录 第一章 Windows 工具 [1001] Optimizer &#xff1a;一款高级配置实用工具&#xff0c;旨在增强你在Windows上的隐私和安全性。 [1002] WSL2&#xff1a;适用于 Linux 的 Windows 子系统 (WSL) 可让开发人员直接在 Windows 上按原样运行 GNU/Linux 环境…

力扣226.翻转二叉树101.对称二叉树

解决二叉树的问题&#xff0c;经常要习惯从递归角度思考 左子树/右子树是否具备某属性、是否属于什么类型&#xff08;和题目要求的判断当前树是否xxx一样&#xff09;&#xff1b; 对左/右子树进行什么操作&#xff08;和题目要求的对当前树的操作一样&#xff09;。 226.翻转…

提权方式及原理汇总

一、Linux提权 1、SUID提权 SUID&#xff08;设置用户ID&#xff09;是赋予文件的一种权限&#xff0c;它会出现在文件拥有者权限的执行位上&#xff0c;具有这种权限的文件会在其执行时&#xff0c;使调用者暂时获得该文件拥有者的权限。 为可执行文件添加suid权限的目的是简…

解决SpringBoot使用@Transactional进行RestTemplate远程调用导致查询数据记录为null的bug

开启事务过程中&#xff0c;如果远程调用查询当前已经开启但没有提交的事务&#xff0c;就会查不到数据。 示例代码 import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.transaction.annotation.Transactional; import o…

二叉树求解大小操作详解

目录 一、求所有结点个数 1.1 递归思路 1.2 递归分支图 1.3 递归栈帧图 1.4 C语言实现 二、求叶子结点个数 2.1 递归思路 2.2 递归分支图 2.3 递归栈帧图 2.4 C语言实现 三、求第K层的结点个数 3.1 递归思路 3.2 递归分支图 3.3 递归栈帧图 3.4 C语言实现 四、求…

【python】使用函数名而不加括号是什么情况?

使用函数名而不加括号通常是为了表示对函数本身的引用&#xff0c;而不是调用函数。这种用法通常出现在下面这几种情况&#xff1a; 作为回调函数传递&#xff1a;将函数名作为参数传递给其他函数&#xff0c;以便在需要时调用该函数。例如&#xff0c;在事件处理程序或高阶函数…

冯喜运:5.24现货黄金趋势解读,黄金原油行情分析及操作建议

【黄金消息面分析】&#xff1a;美国劳工部公布的最新数据显示&#xff0c;截至5月18日的一周内&#xff0c;首次申请失业救济人数下降至21.5万人&#xff0c;创下自去年9月以来的最大降幅。数据公布后&#xff0c;现货黄金短线下挫6美元&#xff0c;报2362.71美元/盎司。这表明…

2024受欢迎的便签app是哪个

在繁忙的工作和生活中&#xff0c;便签app成为了我们不可或缺的小助手。2024年&#xff0c;随着人们对高效工作和生活品质的追求&#xff0c;选择一款功能强大且用户友好的便签app显得尤为重要。在众多选择中&#xff0c;敬业签以其出色的记录与提醒功能&#xff0c;脱颖而出&a…

前端发版如何告知用户

在具体项目场景中&#xff0c;前端发版后&#xff0c;用户不手动刷新&#xff0c;则感知不到更新&#xff1b;经常会出现&#xff1a;前端更新了某个功能&#xff0c;导致旧功能使用出现问题&#xff0c;而被用户提单&#xff1b; 关于这个问题有多种解决方式&#xff1a; We…