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 re

def 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 None

        return stdout.strip()

    except FileNotFoundError:
        print("ExifTool is not installed or not found in the system path.")
        return None

def 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 = None
    for item in exif_data:
        if b'Content Identifier' in item:
            content_identifier = item.split(b':')[-1].strip()
            break
    assert content_identifier is not None
    assert 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 = None
    for 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()
            break
    assert media_group_uuid is not None
    assert 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_files


if __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.JPG

DECIMAL       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.JPG

DECIMAL       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.JPG
    0 image files updated
    1 image files unchanged

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解决vue版本不一致导致不能正常编译

解决vue版本不一致导致不能正常编译 异常现象分析原因解决方案 异常现象 项目原本运行无异常&#xff0c;但安装了一个el-table-infinite-scroll的插件后&#xff0c;编译报错&#xff0c;截图如下 分析原因 vue版本与compile版本不一致&#xff0c;应该统一起来&#xff0…

网创教程:WordPress插件网创自动采集并发布

网创教程&#xff1a;WordPress插件网创自动采集并发布 使用插件注意事项&#xff1a; 如果遇到404错误&#xff0c;请先检查并调整网站的伪静态设置&#xff0c;这是最常见的问题。需要定制化服务&#xff0c;请随时联系我。 本次更新内容 我们进行了多项更新和优化&#x…

1.存储部分

1.Flash Memory--闪速存储器&#xff08;注&#xff1a;U盘&#xff0c;SD卡就是闪存&#xff09;在EEPROM基础上发展而来的&#xff0c;断电后也能保存信息&#xff0c;且可进行多次 快速擦除重写。注意&#xff1a;由于闪存需要先擦除再写入&#xff0c;因此闪存写的速度要比…

ssm141餐厅点菜管理系统+vue

餐厅点菜管理系统的设计与实现 摘 要 网络技术和计算机技术发展至今&#xff0c;已经拥有了深厚的理论基础&#xff0c;并在现实中进行了充分运用&#xff0c;尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代&#xff0c;所以对于信息的宣传和管…

Unity-Sprite Atlas+UGUI系统的运行原理

每日一句&#xff1a;别听世俗耳语&#xff0c;看自己的风景就好 目录 SA的原理&#xff1a; SA的优点&#xff1a; SA的缺点&#xff1a; DrawCall是什么&#xff1f; 批处理是什么&#xff1f; 我们先了解一下UGUI系统的运行原理吧&#xff01; 提到图集优化&#xff0…

性能测试--线程的监控

1.线程的状态 1.1.线程的5种状态 java的线程总共有5种状态&#xff0c;如下&#xff1a; * 新建&#xff1a;new 【新建之后不启用都是new】* 运行&#xff1a;runnable* 等待&#xff1a;waitting(无限期等待),timed waitting(限期等待)* 阻塞&#xff1a;blocked* 结束&am…

C++ 求 f(x) = sin x / x 的函数极限

Python&#xff1a; import sympy from sympy import oo #注意无究符号表示形式为两个小定字母o import numpy as np x sympy.Symbol(x) #注意Symbol首字母大写f sympy.sin(x) / x # 定义极限表达式lim sympy.limit(f,x,oo) print(lim)输出&#xff1a; 0 C #include…

计网(部分在session学习章)

TCP/UDP TCP:面向连接,先三次握手建立连接,可靠传输。 UDP:无连接,不可靠,传递的快。 TCP可靠传输 1.分块编号传输; 2.校验和,校验首部和数据的检验和,检测数据在传输中的变化; 3.丢弃重复数据; 4.流量控制,TCP 利⽤滑动窗⼝实现流量控制。TCP的拥塞控制采⽤…

数据可视化第9天(利用wordcloud和jieba分析蝙蝠侠评论的关键字)

数据可以在这里下载 https://github.com/harkbox/DataAnalyseStudy WordCloud wordcloud可以很方便的生成词云图&#xff0c;方便的提供可视化可以直接使用pip install wordcloud进行安装如果使用的是Anaconda,可以使用conda install进行安装 下面看一个简单的例子 txt &qu…

在linux下的ROS中下载超级终端Terminator ROS开发得力助手

在一般我们运行机器人包时要打开三个终端来运行&#xff0c;关闭时还要一个一个关闭&#xff08;ctrlc&#xff09;过于麻烦 现在下载用了terminator后&#xff0c;就支持一键关闭多个终端了&#xff0c;很方便&#xff0c;具体操作如下&#xff1a; sudo apt install termin…

第十三期Big Demo Day聚焦Web3前沿,FaceN.AI项目路演揭幕创新技术

第十三期Big Demo Day活动即将于2024年5月28日在香港数码港的CyberArena隆重举行。FaceN.AI将亮相本次Big Demo Day&#xff0c;参与精彩的项目路演&#xff0c;展示其在跨链去中心化数字身份、On-chain to Off-chain数据应用、DIDFi探索以及元宇宙与AIGC人格化发展等领域的领先…

Gb 2024-05-22开源项目日报Top10

根据Github Trendings的统计,今日(2024-05-22统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目3非开发语言项目2Jupyter Notebook项目2Rust项目2JavaScript项目1Lua项目1编程面试大学:成为软件工程师的全面学习计划 创建周期:2…

talib 安装

这里写自定义目录标题 talib 安装出错 talib 安装出错 https://github.com/cgohlke/talib-build/releases 这里找到轮子 直接装。

BUUCTF [GUET-CTF2019]zips 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 得到的 flag 请包上 flag{} 提交。 密文&#xff1a; 得到一个attachment.zip文件 解题思路&#xff1a; 1、解压attachment.zip&#xff0c;得到222.zip文件。尝试解压需要密码&#xff0c;使用Ziperello爆破密码…

java连接ldap实现查询

文章目录 一、项目背景二、准备工作三、验证结果四、易错点讲解易错点1&#xff1a;java: 无法访问org.springframework.ldap.core.LdapTemplate易错点2&#xff1a;java: 无法访问org.springframework.context.ConfigurableApplicationContext易错点3&#xff1a;[LDAP: error…

WGCAT工单系统如何配置通知

WGCAT工单系统可以配置邮件通知 只要配置了邮件通知&#xff0c;那么一旦我们账号有新的工单需要处理&#xff0c;就会接受到邮件通知 除了邮件之外&#xff0c;还可以配置其他方式的通知&#xff0c;比如微信钉钉短信等方式&#xff0c;参考如下 https://www.wgstart.com/wgc…

RDD介绍

RDD设计背景 在实际应用中,存在许多迭代式计算,这些应用场景的共同之处是 : 不同计算阶段之间会重用中间结果,即一个阶段的输出结果会作为下一个阶段的输入. 而目前的MapReduce框架都是把中间结果写入到HDFS中,带来了大量的数据复制、磁盘IO和序列化开销; 如果能将结果保存在内…

Docker安装、入门及VSCode链接(地平线OE docker镜像)

最近在地平线的SDK X3上做开发&#xff0c;有高手做了一些编译方法的对比&#xff1a; [X3容器应用开发探索-0]开篇&#xff1a;从裸机编译到交叉编译 X86 Qemu for Hobot X3 PI(AARCH64) vs Hobot X3 PI 这里想借助Docker编译提速&#xff0c;做个笔记&#xff1a; 目录 一、…

算法刷题笔记 高精度乘法(C++实现)

文章目录 题目描述解题思路解题代码 题目描述 给定两个非负整数&#xff08;不含前导0&#xff09;A和B&#xff0c;请你计算 AB的值。 输入格式 共两行&#xff0c;第一行包含整数 A&#xff0c;第二行包含整数 B。 输出格式 共一行&#xff0c;包含AB的值。 数据范围 …

最新文章合集

GitHub宝藏项目&#xff1a;每天一个&#xff0c;让你的技术库增值不停&#xff01; STORM、SuperMemory、Awesome Chinese LLM、AI写作助手、资料搜集、文章生成、视角问题引导、模拟对话策略、内容导入、浏览器插件、资源库、开源微调模型 开发者必看&#xff1a;Linux终端…