前端获取图片exif流信息

本文涉及的产品
可视分析地图(DataV-Atlas),3 个项目,100M 存储空间
简介: 如果你是为了获取 exif 解析后的信息,那么你可以看这篇 前端获取图片exif信息,通过 exif-js 来获取的。看到这里你要懵了,我为什么又要写一遍。emmmm...因为我需求变了,直接拿到 exif 部分的数据,然后 base64 提交。测试地址

什么是 exif



可交换图像文件格式(英语:Exchangeable image file format,官方简称 Exif),是专门为 数码相机 的照片设定的,可以记录数码照片的属性信息和拍摄数据。

exif 格式规则


Exif 信息以 0xFFE1 作为开头标记,后两个字节表示 Exif 信息的长度。所以 Exif 信息最大为64 kb,而内部采用 TIFF 格式。


基于这样的规则,那其实我要获取 exif 信息的串就很简单了。


伪代码实现,反正跑不起来


// 获取开始标记
ffe1_idx = blob.indexOf('ffe1');
// 截取后两个字节,用来当长度
exifLength = blob.slice(ffe1_idx, ffe1_idx + 2)
// 截取出exif
exif = blob.slice(ffe1_idx, ffe1_idx + exifLength)
// exif 处理成 base64
btoa(exif)


实现获取 exif 并 base64 编码



我是基于 exif.js,使用了他内部的错误控制。


判断类型


因为 exif 是用于记录数码照片的属性信息和拍摄数据,所以需要是 JPEG

if ((dataView.getUint8(0) != 0xFF) || 
        (dataView.getUint8(1) != 0xD8)) {
    console.log("Not a valid JPEG");
    return { 
        state: 1001, 
        message: 'not a valid jpeg' 
    };
}


查找 Exif 的标志位


bVbGIYO.webp.jpg


前面我们介绍了 Exif 信息以 0xFFE1 作为开头标记。

所以我们直接找这个信息


bVbGIYY.webp.jpg


将 arrayBuffer 数据以 Uint8 解析并展示 Array.from(new Uint8Array(temp1)).map(v=>[v, v.toString(16).padStart(2, '0'), String.fromCharCode(v)])

var offset = 2, //头两位是类型标记所以跳过
    length = file.byteLength, //文件长度
    marker;
while (offset < length) {
    if (dataView.getUint8(offset) != 0xFF) {
        if (debug) console.log("Not a valid marker at offset " + offset + ", found: " + dataView.getUint8(offset));
        return { state: 1002, message: 'not a valid marker, something is wrong' };
    }
    marker = dataView.getUint8(offset + 1);
    if (debug) console.log(marker);
    if (marker == 225) {
        if (debug) console.log("Found 0xFFE1 marker");
        return readEXIFData(
            dataView, // 数据源
            offset + 4 //跳过 0xffe1 和 长度位
    } else {
        offset += 2 + dataView.getUint16(offset + 2);
    }
}


解析 exif


function readEXIFData(file, start) {
    // 判断是不是 exif 信息,开头应该是字符串 Exif
    if (getStringFromDB(file, start, 4) != "Exif") {
        if (debug) console.log("Not valid EXIF data! " + getStringFromDB(file, start, 4));
        return { state: 1003, message: "Not valid EXIF data! " + getStringFromDB(file, start, 4) };
    }
    // 判断是大数结尾还是小数结尾。
    var bigEnd,
        tiffOffset = start + 6;
    if (file.getUint16(tiffOffset) == 0x4949) {
        bigEnd = false;
    } else if (file.getUint16(tiffOffset) == 0x4D4D) {
        bigEnd = true;
    } else {
        if (debug) console.log("Not valid TIFF data! (no 0x4949 or 0x4D4D)");
        return { state: 1004, message: "Not valid TIFF data! (no 0x4949 or 0x4D4D)" };
    }
    if (file.getUint16(tiffOffset + 2, !bigEnd) != 0x002A) {
        if (debug) console.log("Not valid TIFF data! (no 0x002A)");
        return { state: 1005, message: "Not valid TIFF data! (no 0x002A)" };
    }
    var firstIFDOffset = file.getUint32(tiffOffset + 4, !bigEnd);
    if (firstIFDOffset < 0x00000008) {
        if (debug) console.log("Not valid TIFF data! (First offset less than 8)", file.getUint32(tiffOffset + 4, !bigEnd));
        return { state: 1006, message: "Not valid TIFF data! (First offset less than 8)" };
    }
    // 截取,这里代码讲道理还是可以优化的。
    var _start = tiffOffset - 10;
    var _end = parseInt(Array.from(new Uint8Array(file.buffer.slice(start-2,start))).map(v=>v.toString(16)).join(''), 16)+start-2
    return {
        state: 1000,
        data: btoa(Array.from(new Uint8Array(file.buffer.slice(_start, _end))).map(v => String.fromCharCode(v)).join(''))
    }
}


bVbGIZC.webp.jpg

相关实践学习
DataV Board用户界面概览
本实验带领用户熟悉DataV Board这款可视化产品的用户界面
阿里云实时数仓实战 - 项目介绍及架构设计
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3&nbsp;)前置知识要求 &nbsp; 课程大纲 第一章&nbsp;了解数据仓库概念 初步了解数据仓库是干什么的 第二章&nbsp;按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章&nbsp;数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章&nbsp;采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章&nbsp;用户行为数据仓库 严格按照企业的标准开发 第六章&nbsp;搭建业务数仓理论基础和对表的分类同步 第七章&nbsp;业务数仓的搭建&nbsp; 业务行为数仓效果图&nbsp;&nbsp;
相关文章
|
3月前
|
前端开发
后端返回图片二进制流,前端转base64
本文介绍了如何将后端返回的图片二进制流转换为Base64格式,以便在前端使用。通过在axios请求中设置`responseType`为`arraybuffer`,然后使用`btoa`和`Uint8Array`进行转换。
343 5
|
2月前
|
存储 前端开发 JavaScript
🚀前端轻松实现网页内容转换:一键复制、保存图片及生成 Markdown
在现代前端开发中,提升用户的交互体验至关重要。本文将详细介绍如何使用 HTML2Canvas 和 Turndown 两个强大的 JavaScript 库,实现将网页选中文本转化为图片并保存或复制到剪贴板,或将内容转换为 Markdown 格式。文章包含核心代码实现、技术细节和功能拓展方向,为开发者提供了一个轻量级的解决方案,提升用户体验。
186 68
|
2月前
|
人工智能 前端开发 JavaScript
拿下奇怪的前端报错(一):报错信息是一个看不懂的数字数组Buffer(475) [Uint8Array],让AI大模型帮忙解析
本文介绍了前端开发中遇到的奇怪报错问题,特别是当错误信息不明确时的处理方法。作者分享了自己通过还原代码、试错等方式解决问题的经验,并以一个Vue3+TypeScript项目的构建失败为例,详细解析了如何从错误信息中定位问题,最终通过解读错误信息中的ASCII码找到了具体的错误文件。文章强调了基础知识的重要性,并鼓励读者遇到类似问题时不要慌张,耐心分析。
|
2月前
|
JavaScript 前端开发 Python
django接收前端vue传输的formData图片数据
django接收前端vue传输的formData图片数据
63 4
|
2月前
|
前端开发 小程序 Java
java基础:map遍历使用;java使用 Patten 和Matches 进行正则匹配;后端传到前端展示图片三种情况,并保存到手机
这篇文章介绍了Java中Map的遍历方法、使用Pattern和matches进行正则表达式匹配,以及后端向前端传输图片并保存到手机的三种情况。
27 1
|
2月前
|
前端开发 JavaScript 编译器
不走弯路,纯前端如何把图片导出成视频!
【10月更文挑战第3天】不走弯路,纯前端如何把图片导出成视频!
75 3
|
2月前
|
JavaScript 前端开发 编译器
吐血整理:纯前端如何实现批量dom转图片,并下载成压缩包
【10月更文挑战第2天】吐血整理:纯前端如何实现批量dom转图片,并下载成压缩包
61 2
|
3月前
|
前端开发 数据安全/隐私保护
【前端web入门第二天】03 表单-下拉菜单 文本域 label标签 按钮 【附注册信息综合案例】
本文档详细介绍了HTML表单的多种元素及其用法,包括下拉菜单(`&lt;select&gt;` 和 `&lt;option&gt;`)、文本域(`&lt;textarea&gt;`)、标签解释(`&lt;label&gt;`)、各类按钮(`&lt;button&gt;`)及表单重置功能、无语义布局标签(`&lt;div&gt;` 和 `&lt;span&gt;`)以及字符实体的应用。此外,还提供了一个完整的注册信息表单案例,涵盖个人信息、教育经历和工作经历等部分,展示了如何综合运用上述元素构建实用的表单。
【前端web入门第二天】03 表单-下拉菜单 文本域 label标签 按钮 【附注册信息综合案例】
|
3月前
|
前端开发
前端之图片操作
前端之图片操作
|
3月前
|
前端开发 JavaScript
node接收前端上传的图片,单文件、多文件同name、多文件不同name
本文介绍了在Node.js中使用multer模块接收前端上传的图片,包括单文件上传、多文件上传(同name和不同name)以及任意类型文件上传的方法。
102 0