Python读取图片属性信息的实现方法


Posted in Python onSeptember 11, 2016

本文是利用Python脚本读取图片信息,有几个说明如下:

     1、没有实现错误处理

     2、没有读取所有信息,大概只有 GPS 信息、图片分辨率、图片像素、设备商、拍摄设备等

     3、简单修改后应该能实现暴力修改图片的 GPS 信息

     4、但对于本身没有 GPS 信息的图片,实现则非常复杂,需要仔细计算每个描述符的偏移量

脚本运行后,读取结果如下

Python读取图片属性信息的实现方法
脚本读取的信息

这里和 Windows 属性查看器读到的内容完全一致

Python读取图片属性信息的实现方法
图片信息1

Python读取图片属性信息的实现方法
图片信息2

源码如下

# -*- coding:utf-8 -*-
import binascii

class ParseMethod(object):
  @staticmethod
  def parse_default(f, count, offset):
    pass

  @staticmethod
  def parse_latitude(f, count, offset):
    old_pos = f.tell()
    f.seek(12 + offset)

    latitude = [0,0,0]
    for i in xrange(count):
      byte = f.read(4)
      numerator = byte.encode('hex')

      byte = f.read(4)
      denominator = byte.encode('hex')

      latitude[i] = float(int(numerator, 16)) / int(denominator, 16)


    print 'Latitude:\t%.2f %.2f\' %.2f\"' % (latitude[0], latitude[1], latitude[2])
    f.seek(old_pos)  


  @staticmethod
  def parse_longtitude(f, count, offset):
    old_pos = f.tell()
    f.seek(12 + offset)

    longtitude = [0,0,0]
    for i in xrange(count):
      byte = f.read(4)
      numerator = byte.encode('hex')

      byte = f.read(4)
      denominator = byte.encode('hex')

      longtitude[i] = float(int(numerator, 16)) / int(denominator, 16)


    print 'Longtitude:\t%.2f %.2f\' %.2f\"' % (longtitude[0], longtitude[1], longtitude[2])
    f.seek(old_pos) 

  @staticmethod
  def parse_make(f, count, offset):
    old_pos = f.tell()
    f.seek(12 + offset)
    byte = f.read(count)
    a = byte.encode('hex')
    print 'Make:\t\t' + binascii.a2b_hex(a)
    f.seek(old_pos) 

  @staticmethod
  def parse_model(f, count, offset):
    old_pos = f.tell()
    f.seek(12 + offset)
    byte = f.read(count)
    a = byte.encode('hex')
    print 'Model:\t\t' + binascii.a2b_hex(a)
    f.seek(old_pos)     

  @staticmethod
  def parse_datetime(f, count, offset):
    old_pos = f.tell()
    f.seek(12 + offset)
    byte = f.read(count)
    a = byte.encode('hex')
    print 'DateTime:\t' + binascii.a2b_hex(a)
    f.seek(old_pos)

  # rational data type, 05
  @staticmethod
  def parse_xresolution(f, count, offset):
    old_pos = f.tell()
    f.seek(12 + offset)

    byte = f.read(4)
    numerator = byte.encode('hex')
    byte = f.read(4)
    denominator = byte.encode('hex')
    xre = int(numerator, 16) / int(denominator, 16)

    print 'XResolution:\t' + str(xre) + ' dpi'
    f.seek(old_pos)

  @staticmethod
  def parse_yresolution(f, count, offset):
    old_pos = f.tell()
    f.seek(12 + offset)

    byte = f.read(4)
    numerator = byte.encode('hex')
    byte = f.read(4)
    denominator = byte.encode('hex')
    xre = int(numerator, 16) / int(denominator, 16)

    print 'YResolution:\t' + str(xre) + ' dpi'
    f.seek(old_pos)

  @staticmethod
  def parse_exif_ifd(f, count, offset):
    old_pos = f.tell()
    f.seek(12 + offset)

    byte = f.read(2)
    a = byte.encode('hex')    
    exif_ifd_number = int(a, 16)

    for i in xrange(exif_ifd_number):
      byte = f.read(2)
      tag_id = byte.encode('hex')
      #print tag_id,

      byte = f.read(2)
      type_n = byte.encode('hex')
      #print type_n,

      byte = f.read(4)
      count = byte.encode('hex')
      #print count,

      byte = f.read(4)
      value_offset = byte.encode('hex')
      #print value_offset

      value_offset = int(value_offset, 16)
      EXIF_IFD_DICT.get(tag_id, ParseMethod.parse_default)(f, count, value_offset)

    f.seek(old_pos)  

  @staticmethod
  def parse_x_pixel(f, count, value):
    print 'X Pixels:\t' + str(value)

  @staticmethod
  def parse_y_pixel(f, count, value):
    print 'y Pixels:\t' + str(value)

  @staticmethod
  def parse_gps_ifd(f, count, offset):
    old_pos = f.tell()    
    f.seek(12 + offset)
    byte = f.read(2)
    a = byte.encode('hex')  
    gps_ifd_number = int(a, 16)

    for i in xrange(gps_ifd_number):
      byte = f.read(2)
      tag_id = byte.encode('hex')
      #print tag_id,

      byte = f.read(2)
      type_n = byte.encode('hex')
      #print type_n,

      byte = f.read(4)
      count = byte.encode('hex')
      #print count,

      byte = f.read(4)
      value_offset = byte.encode('hex')
      #print value_offset

      count = int(count, 16)
      value_offset = int(value_offset, 16)
      GPS_IFD_DICT.get(tag_id, ParseMethod.parse_default)(f, count, value_offset)

    f.seek(old_pos) 

IFD_dict = {
  '010f' : ParseMethod.parse_make ,
  '0110' : ParseMethod.parse_model ,
  '0132' : ParseMethod.parse_datetime ,
  '011a' : ParseMethod.parse_xresolution ,
  '011b' : ParseMethod.parse_yresolution ,
  '8769' : ParseMethod.parse_exif_ifd ,
  '8825' : ParseMethod.parse_gps_ifd
}

EXIF_IFD_DICT = {
  'a002' : ParseMethod.parse_x_pixel ,
  'a003' : ParseMethod.parse_y_pixel
}

GPS_IFD_DICT = {
  '0002' : ParseMethod.parse_latitude ,
  '0004' : ParseMethod.parse_longtitude
}


with open('image.jpg', 'rb') as f:
  byte = f.read(2)
  a = byte.encode('hex')
  print 'SOI Marker:\t' + a

  byte = f.read(2)
  a = byte.encode('hex')
  print 'APP1 Marker:\t' + a

  byte = f.read(2)
  a = byte.encode('hex')
  print 'APP1 Length:\t' + str(int(a, 16)) + ' .Dec'

  byte = f.read(4)
  a = byte.encode('hex')
  print 'Identifier:\t' + binascii.a2b_hex(a)

  byte = f.read(2)
  a = byte.encode('hex')
  print 'Pad:\t\t' + a 

  print 

  print 'Begin to print Header.... '
  print 'APP1 Body: '

  byte = f.read(2)
  a = byte.encode('hex')
  print 'Byte Order:\t' + a  

  byte = f.read(2)
  a = byte.encode('hex')
  print '42:\t\t' + a 

  byte = f.read(4)
  a = byte.encode('hex')
  print '0th IFD Offset:\t' + a 

  print 'Finish print Header'

  print 'Begin to print 0th IFD....'
  print
  #print 'Total: ',
  byte = f.read(2)
  a = byte.encode('hex')
  interoperability_number = int(a, 16)
  #print interoperability_number


  for i in xrange(interoperability_number):
    byte = f.read(2)
    tag_id = byte.encode('hex')
    #print tag_id,

    byte = f.read(2)
    type_n = byte.encode('hex')
    #print type_n,

    byte = f.read(4)
    count = byte.encode('hex')
    #print count,

    byte = f.read(4)
    value_offset = byte.encode('hex')
    #print value_offset

    count = int(count, 16)
    value_offset = int(value_offset, 16)

    # simulate switch
    IFD_dict.get(tag_id, ParseMethod.parse_default)(f, count, value_offset)


  print
  print 'Finish print 0th IFD....'

总结

利用Python读取图片属性信息的实现方法到这就基本结束了,大家都学会了吗?希望这篇文章对大家的学习或者工作带来一定的帮助,

Python 相关文章推荐
python访问sqlserver示例
Feb 10 Python
python实现文件快照加密保护的方法
Jun 30 Python
Python AES加密实例解析
Jan 18 Python
python实现音乐下载器
Apr 15 Python
python斐波那契数列的计算方法
Sep 27 Python
对Python中创建进程的两种方式以及进程池详解
Jan 14 Python
基于pytorch中的Sequential用法说明
Jun 24 Python
用opencv给图片换背景色的示例代码
Jul 08 Python
Python实现自动整理文件的脚本
Dec 17 Python
python实现视频压缩功能
Dec 18 Python
解决tensorflow模型压缩的问题_踩坑无数,总算搞定
Mar 02 Python
python 爬取天气网卫星图片
Jun 07 Python
python开发环境PyScripter中文乱码问题解决方案
Sep 11 #Python
基于asyncio 异步协程框架实现收集B站直播弹幕
Sep 11 #Python
asyncio 的 coroutine对象 与 Future对象使用指南
Sep 11 #Python
Python中使用asyncio 封装文件读写
Sep 11 #Python
Python 如何访问外围作用域中的变量
Sep 11 #Python
Python优化技巧之利用ctypes提高执行速度
Sep 11 #Python
Python 中的with关键字使用详解
Sep 11 #Python
You might like
探讨php中header的用法详解
2013/06/07 PHP
PHP list() 将数组中的值赋给变量的简单实例
2016/06/13 PHP
thinkPHP简单导入和使用阿里云OSSsdk的方法
2017/03/15 PHP
利用PHP访问MySql数据库的逻辑操作以及增删改查的实例讲解
2017/08/30 PHP
javascript 播放器 控制
2007/01/22 Javascript
关于js拖拽上传 [一个拖拽上传修改头像的流程]
2011/07/13 Javascript
使用js实现雪花飘落效果
2013/08/26 Javascript
使用typeof判断function是否存在于上下文
2014/08/14 Javascript
微信小程序 location API实例详解
2016/10/02 Javascript
js学习总结之DOM2兼容处理顺序问题的解决方法
2017/07/27 Javascript
jquery中有哪些api jQuery主要API
2017/11/20 jQuery
Vue 实现拖动滑块验证功能(只有css+js没有后台验证步骤)
2018/08/24 Javascript
JQuery获取可视区尺寸和文档尺寸及制作悬浮菜单示例
2019/05/14 jQuery
JS实现选项卡效果的代码实例
2019/05/20 Javascript
Node爬取大批量文件的方法示例
2019/06/28 Javascript
JavaScript命令模式原理与用法实例详解
2020/03/10 Javascript
[01:19:35]DOTA2上海特级锦标赛主赛事日 - 3 败者组第三轮#2Fnatic VS OG第二局
2016/03/05 DOTA
python实现360皮肤按钮控件示例
2014/02/21 Python
python实现查找excel里某一列重复数据并且剔除后打印的方法
2015/05/26 Python
Python3中简单的文件操作及两个简单小实例分享
2017/06/18 Python
Scrapy爬虫实例讲解_校花网
2017/10/23 Python
Python随机生成均匀分布在三角形内或者任意多边形内的点
2017/12/14 Python
Python cookbook(数据结构与算法)同时对数据做转换和换算处理操作示例
2018/03/23 Python
python 获取页面表格数据存放到csv中的方法
2018/12/26 Python
Python将列表中的元素转化为数字并排序的示例
2019/12/25 Python
python 的numpy库中的mean()函数用法介绍
2020/03/03 Python
一篇文章教你用python画动态爱心表白
2020/11/22 Python
多重CSS背景动画实现方法示例
2014/04/04 HTML / CSS
运行时异常与一般异常有何异同?
2014/01/05 面试题
如何判断计算机可能已经中马
2013/03/22 面试题
影视制作岗位职责
2013/12/04 职场文书
《乡愁》教学反思
2014/02/18 职场文书
关于运动会的口号
2014/06/07 职场文书
公司年会晚会开幕词
2019/04/02 职场文书
2019暑假学生安全口号
2019/06/27 职场文书
MySQL 8.0 Online DDL快速加列的相关总结
2021/06/02 MySQL