首先要感谢@fooleap发给我的极为给力的jQuery实现显示图片Exif代码,解决了我十年来 😥 的一个夙愿:显示博客图片Exif(什么是Exif?)信息——以后再也不需要在图片的title属性里人肉输入用了什么设备了!

虽然从来没学过jQuery,但好歹有十多年前可怜的一点js基础,加上百度,一晚上摸索着居然也搞出来了。

注意:以下代码实现的基础是图片托管于Aliyun OSS或Qiniu等。

1、将根据自己需求修订后的jQuery代码yourjscode.js上传至主题下js文件夹:

/* -------------------------------------------------
 * Description: New exif.js file. Just make it neat.
 * Edition:     v1.4
 * Time:        2018/11/18 23:46
 * Author:      blog.fooleap.org & synyan.cn
 * ------------------------------------------------*/
window.$ = jQuery;
$(document).ready(function(){
$('.post-content img[src*="synyan.cn"]').each(function(){
    var _ = this; 
    var $el = $(this); 
    var displayinfo;
    if( _.src.toLowerCase().lastIndexOf('.jpg') )
        var index = _.src.toLowerCase().lastIndexOf('.jpg');
        else if( _.src.toLowerCase().lastIndexOf('.jpeg') )
        var index = _.src.toLowerCase().lastIndexOf('.jpeg');
    else
        return;
    var titleString = _.title;
    var titleCamera = false;
    if (titleString.indexOf("Camera") >= 0) titleCamera = true;
    if( index > -1 ){
        var exifUrl = _.src.slice(0, index)+'.jpg?x-oss-process=image/info';
        $.ajax({
            url: exifUrl,
            success: function (res) {
               var exif = res;
               var parse = function(attr, label){
               return !attr ? '' : ( label ? label + ' ' : '') + attr.value + ' ';
     }
     /* 情况1 */
     if (!!parse(exif.Make) && !!parse(exif.Model) && !!parse(exif.DateTimeOriginal)){
        /* 情况1.1 */
        var imgCameraOne = parse(exif.Model).replace("Canon","");
        var imgCameraOne = parse(exif.Model).replace("HTC","");
        var focalLengthInNumber = Math.round((eval(parse(exif.FocalLength,'')))*100)/100;
        var focalLengthIn35mmFilmOutput;
        var focalLengthIn35mmFilmNumber = eval(parse(exif.FocalLengthIn35mmFilm,''));
        var focalLenghtOutput;
     if (!focalLengthInNumber) {
        focalLenghtOutput = "";
        if (!focalLengthIn35mmFilmNumber)
           focalLengthIn35mmFilmOutput = "";
        else
           focalLengthIn35mmFilmOutput = " eqv " + focalLengthIn35mmFilmNumber + "mm";
      }
      else {
           focalLenghtOutput = "·" + " f=" + focalLengthInNumber + "mm";
           if (focalLengthIn35mmFilmNumber)
              focalLengthIn35mmFilmOutput = " eqv " + focalLengthIn35mmFilmNumber + "mm";
           else {
              focalLengthIn35mmFilmOutput = "";
           }
           if (focalLengthInNumber == focalLengthIn35mmFilmNumber) {
              focalLenghtOutput = "";
              focalLengthIn35mmFilmOutput = "·" + " f=" + focalLengthInNumber + "mm";
           }
           else;
       }
       var content = '<div class="exif-caption" exif-data="'
                   + parse(exif.Make, '')
                   + imgCameraOne
                   + parse(exif.LensModel,'·')
                   + parse(exif.DateTimeOriginal, '·')
                   + focalLenghtOutput
                   + focalLengthIn35mmFilmOutput
                   + '"></div>';
        }
       /* 情况2 */
        else if (!parse(exif.Make) || !parse(exif.Model) || !parse(exif.DateTimeOriginal)) {
             if (titleString && titleCamera) {
                var imgTitle = titleString;
                imgTitle = imgTitle.replace(/(Camera:/i, '');
                imgTitle = imgTitle.replace(/)/i, '');
                if (imgTitle.indexOf("+") >= 0) {
                    var imgTitleString = imgTitle.split("+");
                    var imgCamera = imgTitleString[0];
                    var imgLens = imgTitleString[1];
                    var imgFilm = imgTitleString[2];
                    var imgScanner = imgTitleString[3];
                if (!imgLens){
                    imgTitle = "" + imgCamera;
                }
                else if (!imgFilm) {
                    imgTitle = "" + imgCamera +"·" + imgLens;
                }
                else if (!imgScanner) {
                    imgTitle = "" + imgCamera +"·" + imgLens + "·" + imgFilm;
                }
                else {
                    imgTitle = "" + imgCamera +"·" + imgLens + "·" + imgFilm + "·" + imgScanner;
                }
          }
          else if(imgTitle.indexOf("+") < 0 && titleString.indexOf("Camera:") >=0){
               imgTitle = "" + imgTitle;
          }
          if (exif.DateTimeOriginal) {
               var content = '<div class="exif-caption" exif-data="'
                           + imgTitle
                           + parse(exif.DateTimeOriginal, '·')
                           + '"></div>';
          }
          /* 情况2.1 */
            if (!(exif.DateTimeOriginal)) {
                 /* 情况2.1.1 */
                 if ((exif.DateTime && !exif.DateTimeDigitized)) {
                     var content = '<div class="exif-caption" exif-data="'
                                 + imgTitle 
                                 + parse(exif.DateTime, '·')
                                 + '"></div>';
             }
             else if ((exif.DateTimeDigitized)) {
                 var content = '<div class="exif-caption" exif-data="'
                             + imgTitle
                             + parse(exif.DateTimeDigitized, '·')
                             + '"></div>';
             }
             else {
                 var content = '<div class="exif-caption" exif-data="'
                             + imgTitle
                             + '"></div>';
             }
           }
        }
        /* 情况3 */
        else {
             var content = '<div class="exif-caption" exif-data="'
                         + ' 无Exif信息 '
                         + '"></div>';
        }
      }
      else;
      $(".post-content img").attr({title:""});
      $el.after(content);
      }
      })
     }
   })
})

2、在Single.php头部插入:

<script src="<?phpecho get_stylesheet_directory_uri() ?>/js/yourjscode.js"></script>

3、添加css代码(从@fooleap的博客扒下来的,同样也是修订了一番,最终符合WordPress的贴图规范,再次感谢@fooleap):

/* exif css */
.post-content .wp-caption .exif-caption:before{
    max-width: 100%;
    text-align: center;
    margin: 0 auto;
    content: attr(exif-data);
    display: block;
    position: absolute !important;
    top: 20px;
    left: 25px;
    right: 25px;
    background-color: black;
    color: white;
    font-size: 12px;
    line-height: 25px;
    height: 25px;
    overflow: hidden;
    opacity: 0;
    transition: opacity .5s;
    -webkit-transition: opacity .5s;
}
.wp-caption:hover .exif-caption[exif-data]:before {
    opacity: .7;
}

4、Aliyun开通“跨域访问”。

大功告成! 😉

鼠标移到图片上显示Exif信息
鼠标移到图片上显示Exif信息

昨晚做得匆忙,开会抽空之余继续优化了一下代码:

  • 删掉了无用的几行代码。
  • 以前人肉输入的title属性也没浪费,加入判断语句,如果Exif为空或不全,则取出title标签中的部分文字,嵌入显示完整信息。
无Exif的胶片引入title信息
无Exif的胶片引入title信息

发现存量图片显示Exif存在各种bug,原代码越改越多越糊涂,改到后来已经不知道到底在写什么了。

于是静下心来列了一张代码结构表:

情况1:
正常Exif(标准是Make/Model/DateTimeOriginal/FNumber同时存在)。
	情况1.1:
	若Make为Canon/HTC,Model中去除一个重复的Canon/HTC字样。

情况2:
有Exif但Exif不全(标准是Make/Model/DateTimeOriginal/FNumber有一个不存在),或无Exif,以人工输入的title="(Camera:Make & Model + [LensModel] + [Film] + [Scanner])"通过分割+号代替Make/Model/LensModel并添上其它属性。
	情况2.1:
	若DateTimeOriginal不存在,则以DateTime显示修改时间。
		情况2.1.1:
		若DateTime不存在,则不显示修改时间。
		情况2.1.2:
		若DateTimeDigitalized存在,则以DateTimeDigitalized显示图片时间。
情况3:
无Exif,无title,提示无Exif信息。

按照代码结构表重写一遍,清爽整洁多了。精简后的代码已更新至代码1。


针对2018年11月写的关于不具有Exif的图片(如:胶片扫描件)添加title属性并获取数据的方法,经过一年半来的实践,认为并不好……

以前人肉输入的title属性也没浪费,加入判断语句,如果Exif为空或不全,则取出title标签中的部分文字,嵌入显示完整信息。

尤其是WordPress将后台编辑器更新为古腾堡后,如果更新区块则会导致原有title全部遗失。另外今后也许第三方会出新的Exif解析工具,人肉添加title并后期调用的原始方法在实现了自己的历史价值后,应该丢入垃圾堆。推荐直接利用批量改图工具,为不具有原始Exif属性的图片添加Exif以达到一劳永逸的目的。相关改图工具包括(推荐度以数字排序):

Mac:

  1. ImageExifEditor
  2. Exif Editor for Mac

Windows:

  1. Photos Exif Editor
  2. ExifTool
  3. PowerExif
  4. ExifDateEdit

Ubuntu:

  1. jhead库
  2. libexif库

(为啥没有封装好的软件包?都用Linux了还要啥interface…… )


因佳能、部分索尼相机所拍照片exif不带exif.FocalLengthIn35mmFilm(等效35mm焦距)标签,故自己测算传感器大小转换为35mm胶片factor后人工计算等效焦距,并代码如下:

/* 如果相机无等效35mm但可计算等效 */
/* 开始 */
var specialCameras = [
	"Canon EOS M200 1.6",
	"Canon PowerShot G7 X Mark III 2.7272",
	"Canon PowerShot G5 X Mark II 2.7272",
	"Canon PowerShot Pro1 3.94",
	"Canon PowerShot A70 6.4815",
	"SONY DSC-T9 6.0"
];
var exifModel = parse(exif.Model).toString();
function factor(n) {
	for (var i in specialCameras) {
		if (specialCameras[i].search(n) != -1) {
			var str = specialCameras[i];
			var spstr = str.split(" ");
			var c = spstr[spstr.length-1];
			return c;
			};
	}
}
focalLengthIn35mmFilmNumber = Math.round(eval(focalLengthInNumber * factor(exifModel)));
focalLengthIn35mmFilmOutput = " eqv " + focalLengthIn35mmFilmNumber + "mm";
if(!focalLengthIn35mmFilmNumber)
	focalLengthIn35mmFilmOutput = '';
/* 结束 */

共有 31 条评论

  1. typecho模板

    陕西

    膜拜大佬,看到这个就想起来QQ空间可以读取图片信息感觉很牛掰

    六年前 Google Chrome 68 · Windows 7

    回复

    • S

      江苏

      @typecho模板 我也是站在巨人的肩膀上。 😳

      六年前 Google Chrome 71 · Mac OS X 10.14

      回复

  2. 枫叶

    福建

    多谢老虎最后的代码结构表,给了我一个思路。哈哈~多谢多谢。 😐 😐 😐

    六年前 Google Chrome 72 · Windows 10

    回复

    • S

      江苏

      @枫叶 不客气,好代码共享。

      六年前 Google Chrome 73 · Mac OS X 10.14

      回复

  3. 天才书剑

    陕西

    本地测试了一下 一切都是按照教程所说,JS也加载了,但是已经不能弹出来EXIF层了。

    另外我的图片后缀是这样的,好像不太一样
    .jpg?x-oss-process=image%2Fformat,webp

    三年前 Google Chrome 97 · Windows 10

    回复

    • S

      江苏

      @天才书剑 js里的相关代码要根据自己的模板相应调一下的。可能涉及的点也比较多,我看你网站挂了,也没法帮你查原因。

      三年前 Safari 15 · Mac OS X 10.15

      回复

  4. Justin

    日本

    不明觉厉…… 我找到了一个比较傻瓜的方法,对小白用户或许会更友好些:只需要安装一个名为 Meow Lightbox 的 WordPress 插件,就可以实现在灯箱界面显示照片EXIF信息;唯一的不足需要手动点击图片进入灯箱模式才能看到。

    示例:https://zblogs.top/fujifilm-x-s10-first-photo-experience-test-sample/

    两年前 Google Chrome 110 · Mac OS X 10.15

    回复

    • S

      江苏

      @Justin 插件当然可以,也比较直观,就是自定义不容易。

      两年前 Microsoft Edge 110 · Windows 10

      回复

  5. K

    重庆

    S大哥,老虎大哥,空了可不可以帮我新主题改改本文这个需求,请你喝茶~~~

    我发现九个月前搞过这个,当时部分页面搞好了,但是新的页面都不行,可以显示的文章比如:

    https://www.shephe.com/2020/11/%e7%a7%8b/

    不能显示的比如:https://www.shephe.com/2022/03/%e6%b5%8b%e8%af%95%e6%96%87%e7%ab%a0%e5%bd%a2%e5%bc%8f%e4%b8%ba%e5%9b%be%e5%ba%93/

    我希望实现所有正文图片(单图和相册)、portfolio图片及相册有exif的都显示,没有的显示个无exif之类(现在的代码没有exif信息的会提示400)

    我的代码在:https://www.shephe.com/wp-content/themes/impeka/js/extra-plugins.js?ver=0.1

    九个月前 Google Chrome 122 · Windows 10

    回复

       

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注