图片压缩工具 | 图片属性详解及读取解析元数据

OPEN-IMAGE-TINY,一个基于 Electron + VUE3 的图片压缩工具,项目开源地址:https://github.com/0604hx/open-image-tiny

ℹ️ 图片信息及属性

基本属性

  1. 格式类型:JPEG、PNG、GIF、WEBP、BMP、TIFF等
  2. 文件大小:以KB、MB等为单位的存储空间占用
  3. 创建/修改日期:文件的元数据时间戳

视觉属性

  1. 尺寸/分辨率

    • 宽度(像素)
    • 高度(像素)
    • PPI/DPI(每英寸像素数,影响打印质量)
  2. 色彩属性

    • 色彩模式:RGB、CMYK、灰度等
    • 色深/位深:8位、16位、24位等
    • 透明度(Alpha通道):PNG支持,JPEG不支持
  3. 质量属性

    • 压缩率(JPEG等有损格式)
    • 噪点/伪影程度

元数据

EXIF/标准元数据

EXIF(Exchangeable Image File Format,可交换图像文件格式)是嵌入在图片文件中的元数据,主要记录拍摄参数、设备信息、时间、位置等数据。以下是常见 EXIF 信息分类:

✅一、拍摄参数类

属性含义
ExposureTime曝光时间(如 1/60 秒)
FNumber光圈值(如 f/2.8)
ISOSpeedRatingsISO 感光度(如 100、400)
FocalLength焦距(如 35mm)
Flash是否使用闪光灯
MeteringMode测光模式
WhiteBalance白平衡设置

✅ 二、时间与位置

属性含义
DateTimeOriginal拍摄时间
CreateDate文件创建时间(不一定等于拍摄)
GPSLatitudeGPS 纬度(如有)
GPSLongitudeGPS 经度(如有)
GPSAltitude海拔

✅ 三、设备信息

属性含义
Make相机/手机制造商(如 Apple)
Model设备型号(如 iPhone 14)
LensModel镜头型号(如 EF 50mm)
Software拍摄时使用的软件版本

✅ 四、图片属性

属性含义
ImageWidth图片宽度
ImageHeight图片高度
Orientation拍摄方向(横竖)
ColorSpace色彩空间(sRGB 等)
Compression压缩方式
Thumbnail缩略图数据(如有)

ICC/色彩管理的核心

ICC(International Color Consortium,国际色彩联盟)元数据是嵌入在图像文件中的色彩管理数据,用于确保不同设备(相机、显示器、打印机)呈现的色彩一致性。

XMP/图像的可扩展元数据

XMP(Extensible Metadata Platform,可扩展元数据平台)是 Adobe 开发的一种标准化元数据格式,用于嵌入到图片、视频、PDF 等文件中。它比 EXIF 更灵活,支持自定义字段和结构化数据。

对比

📌 XMP vs EXIF vs ICC

特性XMPEXIFICC
格式XML 文本二进制数据二进制配置文件
扩展性⭐⭐⭐⭐(可自定义)⭐⭐(固定字段)⭐(固定色彩模型)
主要用途编辑元数据、版权相机参数、时间色彩管理
编辑工具Photoshop、ExifTool相机、ExifToolPhotoshop、ColorSync

📖 用代码读取图片属性

sharp.js 提供 metadata 方法用于读取图片的信息(详见官网文档)。sharp 本身不能直接读取到 EXIF 信息(返回的是 Buffer 对象),需要专门的工具进行解析,如ExifReaderexifrexif-parserexif-js

四个常用库对比图(截止2025年6月)

特性 / 库ExifReaderexifrexif-parserexif-js
✅ 解析精度⭐⭐⭐⭐ 高(专业级)⭐⭐⭐⭐ 高⭐⭐ 中等(基础字段)⭐⭐ 中等(部分支持)
📦 支持格式JPEG, TIFF, WebP 等JPEG, HEIC, TIFF, WebPJPEGJPEG
🌐 平台支持浏览器 + Node.js浏览器 + Node.jsNode.js(专用)浏览器专用
🛠 支持 GPS / IPTC❌(无 GPS/IPTC)✅(部分支持)
🧱 输出结构化对象✅(字段清晰)❌(手动解析)❌(字段杂乱)
⚡ 性能⭐⭐⭐ 中等⭐⭐⭐⭐ 快⭐⭐⭐⭐ 快(轻量)⭐⭐ 慢(同步)
📅 更新活跃✅(持续更新)✅(活跃)⚠ 停止维护(多年)❌(基本弃用)
📦 包体积小(~20KB)非常小(~6KB)

在项目中我选用exifr库。

元数据展示/VUE

<template>
    <n-scrollbar :style="{ maxHeight: height }">
        <n-table size="small" :bordered="false" striped>
            <thead>
                <tr>
                    <th width="200px">属性名</th>
                    <th></th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="(value, key) in data">
                    <td>
                        <n-tooltip>
                            <template #trigger>{{ key }}</template>
                            {{ getCNName(key) }}
                        </n-tooltip>
                    </td>
                    <td>{{ value }}</td>
                </tr>
            </tbody>
        </n-table>
    </n-scrollbar>
</template>

<script setup>
    import { NTable, NTooltip, NScrollbar } from 'naive-ui'

    const props = defineProps({
        data:{type:Object},
        height:{type: String, default: "500px" }
    })

    const cnNames = (()=>{
        const names = {
            CompositeImage : "合成图像",
            OffsetTimeOriginal: "拍摄原始日期时区",
            OffsetTimeDigitized: "拍摄原始日期时区",
            FocalLenIn35mmFilm:"描述数码相机或镜头在模拟35mm胶片时的焦距效果",
            PhotographicSensitivity:"相机灵敏度",
            LensMake:"镜头制造商",
            LensSpecification: "镜头规格",
            ISO: "感光度设置",
            ExposureCompensation:"曝光补偿",
            FocalLengthIn35mmFormat: "镜头焦距在35mm全画幅相机上的等效值‌",
            LensInfo: "镜头信息",
            OffsetTime: "时区偏移量",

            "ExifVersion": "Exif 版本",
            "FlashPixVersion": "FlashPix 版本",
            "ColorSpace": "色域、色彩空间",
            "PixelXDimension": "图像的有效宽度",
            "PixelYDimension": "图像的有效高度",
            "ComponentsConfiguration": "图像构造",
            "CompressedBitsPerPixel": "压缩时每像素色彩位",
            "MakerNote": "制造商设置的信息",
            "UserComment": "用户评论",
            "RelatedSoundFile": "关联的声音文件",
            "DateTimeOriginal": "创建时间",
            "DateTimeDigitized": "数字化创建时间",
            "SubsecTime": "日期时间(秒)",
            "SubSecTimeOriginal": "原始日期时间(秒)",
            "SubsecTimeDigitized": "原始日期时间数字化(秒)",
            "ExposureTime": "曝光时间",
            "FNumber": "光圈值",
            "ExposureProgram": "曝光程序",
            "SpectralSensitivity": "光谱灵敏度",
            "ISOSpeedRatings": "感光度",
            "OECF": "光电转换功能",
            "ShutterSpeedValue": "快门速度",
            "ApertureValue": "镜头光圈",
            "BrightnessValue": "亮度",
            "ExposureBiasValue": "曝光补偿",
            "MaxApertureValue": "最大光圈",
            "SubjectDistance": "物距",
            "MeteringMode": "测光方式",
            "Lightsource": "光源",
            "Flash": "闪光灯",
            "SubjectArea": "主体区域",
            "FocalLength": "焦距",
            "FlashEnergy": "闪光灯强度",
            "SpatialFrequencyResponse": "空间频率反应",
            "FocalPlaneXResolution": "焦距平面X轴解析度",
            "FocalPlaneYResolution": "焦距平面Y轴解析度",
            "FocalPlaneResolutionUnit": "焦距平面解析度单位",
            "SubjectLocation": "主体位置",
            "ExposureIndex": "曝光指数",
            "SensingMethod": "图像传感器类型",
            "FileSource": "源文件",
            "SceneType": "场景类型(1 == 直接拍摄)",
            "CFAPattern": "CFA 模式",
            "CustomRendered": "自定义图像处理",
            "ExposureMode": "曝光模式",
            "WhiteBalance": "白平衡(1 == 自动,2 == 手动)",
            "DigitalZoomRation": "数字变焦",
            "FocalLengthIn35mmFilm": "35毫米胶片焦距",
            "SceneCaptureType": "场景拍摄类型",
            "GainControl": "场景控制",
            "Contrast": "对比度",
            "Saturation": "饱和度",
            "Sharpness": "锐度",
            "DeviceSettingDescription": "设备设定描述",
            "SubjectDistanceRange": "主体距离范围",
            "InteroperabilityIFDPointer": "",
            "ImageUniqueID": "图像唯一ID",
            "ImageWidth": "图像宽度",
            "ExifImageWidth" : "图像宽度",
            "ImageHeight": "图像高度",
            "ExifImageHeight": "图像高度",
            "BitsPerSample": "比特采样率",
            "Compression": "压缩方法",
            "PhotometricInterpretation": "像素合成",
            "Orientation": "拍摄方向",
            "SamplesPerPixel": "像素数",
            "PlanarConfiguration": "数据排列",
            "YCbCrSubSampling": "色相抽样比率",
            "YCbCrPositioning": "色相配置",
            "XResolution": "X方向分辨率",
            "YResolution": "Y方向分辨率",
            "ResolutionUnit": "分辨率单位",
            "StripOffsets": "图像资料位置",
            "RowsPerStrip": "每带行数",
            "StripByteCounts": "每压缩带比特数",
            "JPEGInterchangeFormat": "JPEG SOI 偏移量",
            "JPEGInterchangeFormatLength": "JPEG 比特数",
            "TransferFunction": "转移功能",
            "WhitePoint": "白点色度",
            "PrimaryChromaticities": "主要色度",
            "YCbCrCoefficients": "颜色空间转换矩阵系数",
            "ReferenceBlackWhite": "黑白参照值",
            "DateTime": "日期和时间",
            "ImageDescription": "图像描述、来源",
            "Make": "相机/手机制造商(如 Apple)",
            "Model": "设备型号",
            "Software": "拍摄时使用的软件(手机系统)版本",
            "Artist": "作者",
            "Copyright": "版权信息",
            "GPSVersionID": "GPS 版本",
            "GPSLatitudeRef": "南北纬",
            "GPSLatitude": "纬度",
            "GPSLongitudeRef": "东西经",
            "GPSLongitude": "经度",
            "GPSAltitudeRef": "海拔参照值",
            "GPSAltitude": "海拔",
            "GPSTimeStamp": "GPS 时间戳",
            "GPSSatellites": "测量的卫星",
            "GPSStatus": "接收器状态",
            "GPSMeasureMode": "测量模式",
            "GPSDOP": "测量精度",
            "GPSSpeedRef": "速度单位",
            "GPSSpeed": "GPS 接收器速度",
            "GPSTrackRef": "移动方位参照",
            "GPSTrack": "移动方位",
            "GPSImgDirectionRef": "图像方位参照",
            "GPSImgDirection": "图像方位",
            "GPSMapDatum": "地理测量资料",
            "GPSDestLatitudeRef": "目标纬度参照",
            "GPSDestLatitude": "目标纬度",
            "GPSDestLongitudeRef": "目标经度参照",
            "GPSDestLongitude": "目标经度",
            "GPSDestBearingRef": "目标方位参照",
            "GPSDestBearing": "目标方位",
            "GPSDestDistanceRef": "目标距离参照",
            "GPSDestDistance": "目标距离",
            "GPSProcessingMethod": "GPS 处理方法名",
            "GPSAreaInformation": "GPS 区功能变数名",
            "GPSDateStamp": "GPS 日期",
            "GPSDifferential": "GPS 修正"
        }

        return Object.fromEntries(Object.keys(names).map(key=>[key.toLowerCase(), names[key]]))
    })();

    const getCNName = (key="")=> cnNames[key.toLowerCase()] || key
</script>

效果演示

✍️ 修改图片属性(规划ING)

未来有需要再加上(可以通过 sharp.js 写入 metadata )😄。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

集成显卡

码字不易,需要您的鼓励😄

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值