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处理文本文件实现生成指定格式文件的方法
Jul 31 Python
Python字符和字符值(ASCII或Unicode码值)转换方法
May 21 Python
Python的条件表达式和lambda表达式实例
Jan 31 Python
python批量下载抖音视频
Jun 17 Python
python的debug实用工具 pdb详解
Jul 12 Python
详解pandas DataFrame的查询方法(loc,iloc,at,iat,ix的用法和区别)
Aug 02 Python
python实现的config文件读写功能示例
Sep 24 Python
django admin 添加自定义链接方式
Mar 11 Python
Python基于数列实现购物车程序过程详解
Jun 09 Python
python中entry用法讲解
Dec 04 Python
python中的unittest框架实例详解
Feb 05 Python
Python函数中的不定长参数相关知识总结
Jun 24 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
mysql下创建字段并设置主键的php代码
2010/05/16 PHP
获取PHP警告错误信息的解决方法
2013/06/03 PHP
Yii实现多数据库主从读写分离的方法
2014/12/29 PHP
总结的一些PHP开发中的tips(必看篇)
2017/03/24 PHP
PHP实现用户登录的案例代码
2018/05/10 PHP
JavaScript中常见陷阱小结
2010/04/27 Javascript
从零开始学习jQuery (十) jQueryUI常用功能实战
2011/02/23 Javascript
50个比较实用jQuery代码段
2011/09/18 Javascript
利用JS延迟加载百度分享代码,提高网页速度
2013/07/01 Javascript
JavaScript中Cookie操作实例
2015/01/09 Javascript
JS自定义对象实现Java中Map对象功能的方法
2015/01/20 Javascript
理解javascript正则表达式
2016/03/08 Javascript
js实现页面跳转的几种方法小结
2016/05/16 Javascript
以WordPress为例讲解jQuery美化页面Title的方法
2016/05/23 Javascript
javascript实现blob加密视频源地址的方法
2019/08/08 Javascript
JS实现移动端在线签协议功能
2019/08/22 Javascript
深入理解 ES6中的 Reflect用法
2020/07/18 Javascript
Nodejs 微信小程序消息推送的实现
2021/01/20 NodeJs
windows下添加Python环境变量的方法汇总
2018/05/14 Python
将tensorflow的ckpt模型存储为npy的实例
2018/07/09 Python
python 实现倒排索引的方法
2018/12/25 Python
Python 实现子类获取父类的类成员方法
2019/01/11 Python
Tensorflow获取张量Tensor的具体维数实例
2020/01/19 Python
TensorFlow Saver:保存和读取模型参数.ckpt实例
2020/02/10 Python
Python模拟伯努利试验和二项分布代码实例
2020/05/27 Python
Pycharm配置lua编译环境过程图解
2020/11/28 Python
美国创意之家:BulbHead
2017/07/12 全球购物
捷克体育用品购物网站:D-sport
2017/12/28 全球购物
丽笙酒店官方网站:Radisson Hotels
2019/05/07 全球购物
俄罗斯第一家篮球店:StreetBall
2020/07/30 全球购物
mysql_pconnect()和mysql_connect()有什么区别
2012/05/25 面试题
六一亲子活动总结
2014/07/01 职场文书
小学教师师德师风自我评价
2015/03/04 职场文书
2016年大学校运会广播稿件
2015/12/21 职场文书
2016三严三实专题教育活动心得体会
2016/01/06 职场文书
互联网的下一个风口:新的独角兽将诞生
2019/08/02 职场文书