image-size vs imageinfo
Node.js 环境下的图片尺寸检测方案对比
image-sizeimageinfo类似的npm包:

Node.js 环境下的图片尺寸检测方案对比

image-sizeimageinfo 都是用于在 Node.js 环境中读取图片文件尺寸(宽、高)及类型信息的工具库。image-size 是目前社区最广泛采用的方案,支持同步和异步 API,涵盖格式广泛且维护活跃。imageinfo 是一个较老的库,主要通过 Buffer 头部字节分析来识别格式,功能相对单一,目前维护频率较低。两者都旨在避免加载完整图片文件的情况下获取元数据,适用于上传校验、缩略图生成等场景。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
image-size02,225378 kB451 年前MIT
imageinfo059-415 年前-

image-size vs imageinfo: Node.js 图片元数据读取方案深度对比

在 Node.js 后端开发中,处理用户上传的图片时,我们通常需要在不加载完整文件到内存的情况下获取图片的宽高和类型。image-sizeimageinfo 都解决了这个问题,但它们的实现方式、维护状态和适用场景有很大不同。让我们从架构师的角度深入对比这两个库。

📦 核心 API 设计:同步与异步的支持

image-size 提供了非常灵活的 API,同时支持同步和异步调用。这对于处理大量文件流或避免阻塞事件循环非常重要。

// image-size: 支持同步和异步
import sizeOf from 'image-size';
import { promises as fs } from 'fs';

// 同步方式 (适合脚本或小文件)
const dimensions = sizeOf('images/badge.png');
console.log(dimensions.width, dimensions.height);

// 异步方式 (适合高并发服务)
const buffer = await fs.readFile('images/badge.png');
const dimensionsAsync = await sizeOf(buffer);

imageinfo 的 API 设计较为古老,主要专注于同步分析 Buffer 数据。它没有内置的异步文件读取封装,需要开发者自己处理文件 IO。

// imageinfo: 主要同步分析 Buffer
import ImageInfo from 'imageinfo';
import { readFileSync } from 'fs';

// 必须手动读取文件为 Buffer
const buffer = readFileSync('images/badge.png');
const info = ImageInfo.check(buffer);

if (info.format) {
  console.log(info.width, info.height, info.format);
} else {
  console.log('Unknown format');
}

🖼️ 支持的文件格式范围

image-size 支持非常广泛的现代和传统图片格式。这对于处理用户生成内容(UGC)的平台至关重要,因为用户可能上传 WebP 或 HEIC 等格式。

  • 支持格式:BMP, GIF, JPEG, PNG, PSD, TIFF, WebP, SVG, ICO, CUR, etc.
  • 扩展性强,社区经常提交新格式的 Parser。
// image-size: 轻松处理 WebP 等现代格式
const dimensions = sizeOf('images/photo.webp');
// 返回 { width: 800, height: 600, type: 'webp' }

imageinfo 支持的格式相对较少,主要集中在传统的 Web 图片格式上。对于较新的格式支持可能不足或需要额外验证。

  • 支持格式:JPEG, PNG, GIF, BMP, TIFF, PNM 等。
  • 对 WebP 或 SVG 的支持不如 image-size 完善。
// imageinfo: 对某些新格式可能返回未知
const info = ImageInfo.check(webpBuffer);
// 可能返回 { format: undefined } 如果内部未实现该解析器

🛠️ 错误处理与健壮性

image-size 在遇到无法识别的文件或损坏的文件时,会抛出明确的错误。这使得在 Try-Catch 块中处理异常变得非常直观。

// image-size: 明确的错误抛出
try {
  const dimensions = sizeOf('corrupted_file.png');
} catch (e) {
  // 捕获具体的错误信息
  console.error('Invalid image:', e.message);
}

imageinfo 倾向于返回空结果或空字段,而不是抛出异常。这要求开发者在每次调用后都必须手动检查结果的有效性。

// imageinfo: 静默失败,需手动检查
const info = ImageInfo.check(corruptedBuffer);

if (!info.format) {
  // 必须手动判断是否解析成功
  console.warn('Failed to identify image format');
}

🚀 性能与底层实现

image-size 针对性能进行了优化,它只读取文件头部必要的字节。对于大文件,这能显著减少磁盘 I/O 和内存占用。它还支持从流(Stream)中读取数据。

// image-size: 支持流式读取,无需加载整个文件
import { createReadStream } from 'fs';
import sizeOf from 'image-size';

const stream = createReadStream('images/large_photo.jpg');
const dimensions = sizeOf(stream); 
// 内部只读取头部字节后自动关闭流

imageinfo 需要传入完整的 Buffer 或者至少是包含头部信息的 Buffer。虽然它也只分析头部字节,但它没有内置的文件流处理逻辑,开发者需要自己控制读取多少字节。

// imageinfo: 需要手动管理 Buffer 切片
import { open, read, close } from 'fs';

// 开发者需自己打开文件,读取前几十字节,再传给 imageinfo
const buffer = Buffer.alloc(100);
// ... 手动读取逻辑 ...
const info = ImageInfo.check(buffer);

🤝 共同点:基础功能重叠

尽管有上述差异,这两个库在核心目标上是一致的。

1. 📏 无需解码完整图片

两者都通过读取文件魔数(Magic Numbers)和头部元数据来获取尺寸,避免了昂贵的解码过程。

// 两者都只需几十字节即可获取 100MB 图片的尺寸
// image-size
sizeOf('huge_image.tiff'); 
// imageinfo
ImageInfo.check(hugeBuffer);

2. 🔍 返回基础元数据

两者都主要返回宽、高和格式类型,不包含 EXIF 方向、GPS 位置等深度元数据(这些需要 exif-reader 等库)。

// image-size 返回
// { width: 100, height: 100, type: 'png' }

// imageinfo 返回
// { width: 100, height: 100, format: 'PNG' }

3. 📦 纯 JavaScript 实现

两者都不依赖原生模块(如 C++ bindings),这意味着它们在无服务器环境(Serverless)或浏览器端(通过 Polyfill)更容易部署和运行。

// 两者都可以通过 Webpack/Rollup 轻松打包进前端或 Serverless 函数
// 无需编译原生依赖

📊 总结对比表

特性image-sizeimageinfo
维护状态✅ 活跃维护,社区贡献多⚠️ 更新缓慢,维护频率低
API 风格🔄 支持同步、异步、Stream🛑 主要同步,需手动处理 Buffer
格式支持🎨 广泛 (含 WebP, HEIC, SVG)📼 传统格式为主 (JPEG, PNG, GIF)
错误处理⚠️ 抛出异常 (Try-Catch)🤷 返回空值 (手动检查)
流支持✅ 内置支持 Stream❌ 需手动实现流读取
类型定义✅ 内置 TypeScript 支持⚠️ 需安装 @types 或自行定义

💡 架构师建议

image-size 就像是现代工具箱里的瑞士军刀 🔪——它考虑到了异步 IO、流处理和各种边缘情况。对于任何新的 Node.js 项目,尤其是涉及文件上传服务的场景,它是首选。它的异步支持意味着你的服务器不会因为读取大图片头部而阻塞。

imageinfo 更像是一个老式的螺丝刀 🪛——它能完成基本任务,但在处理现代复杂场景时显得力不从心。除非你有非常特殊的理由(比如极致的体积优化且只处理旧格式),否则在 2024 年的技术栈中,我们更推荐 image-size

最终建议:在构建微服务或 Serverless 函数处理图片时,选择 image-size 能减少大量的样板代码(Boilerplate),特别是在处理流和错误边界时。它的维护活跃度也意味着安全漏洞能更快被修复。

如何选择: image-size vs imageinfo

  • image-size:

    如果你的项目需要稳定的长期支持、广泛的图片格式兼容性(包括 WebP, HEIC, SVG 等),或者需要异步读取文件流的能力,请选择 image-size。它是目前的事实标准,API 设计更符合现代 Node.js 开发习惯,且社区生态丰富,遇到问题的解决成本更低。

  • imageinfo:

    仅在你的项目是遗留系统且已经深度依赖 imageinfo,或者你只需要极其简单的 Buffer 头部字节分析且不希望引入稍大一点的依赖时,才考虑保留 imageinfo。对于新架构设计,通常不建议首选此库,因为其更新频率和功能扩展性不如 image-size

image-size的README

image-size

Build Status Package Version Downloads

Fast, lightweight NodeJS package to get dimensions of any image file or buffer.

Key Features

  • Zero dependencies
  • Supports all major image formats
  • Works with both files and buffers
  • Minimal memory footprint - reads only image headers
  • ESM and CommonJS support
  • TypeScript types included

Supported formats

  • BMP
  • CUR
  • DDS
  • GIF
  • HEIC (HEIF, AVCI, AVIF)
  • ICNS
  • ICO
  • J2C
  • JPEG-2000 (JP2)
  • JPEG
  • JPEG-XL
  • KTX (1 and 2)
  • PNG
  • PNM (PAM, PBM, PFM, PGM, PPM)
  • PSD
  • SVG
  • TGA
  • TIFF
  • WebP

Installation

npm install image-size
# or
yarn add image-size
# or
pnpm add image-size

Usage

Passing in a Buffer/Uint8Array

Best for streams, network requests, or when you already have the image data in memory.

import { imageSize } from 'image-size'
// or
const { imageSize } = require('image-size')

const dimensions = imageSize(buffer)
console.log(dimensions.width, dimensions.height)

Reading from a file

Best for local files. Returns a promise.

import { imageSizeFromFile } from 'image-size/fromFile'
// or
const { imageSizeFromFile } = require('image-size/fromFile')

const dimensions = await imageSizeFromFile('photos/image.jpg')
console.log(dimensions.width, dimensions.height)

Note: Reading from files has a default concurrency limit of 100 To change this limit, you can call the setConcurrency function like this:

import { setConcurrency } from 'image-size/fromFile'
// or
const { setConcurrency } = require('image-size/fromFile')
setConcurrency(123456)

Reading from a file Syncronously (not recommended) ⚠️

v1.x of this library had a sync API, that internally used sync file reads.

This isn't recommended because this blocks the node.js main thread, which reduces the performance, and prevents this library from being used concurrently.

However if you still need to use this package syncronously, you can read the file syncronously into a buffer, and then pass the buffer to this library.

import { readFileSync } from 'node:fs'
import { imageSize } from 'image-size'

const buffer = readFileSync('photos/image.jpg')
const dimensions = imageSize(buffer)
console.log(dimensions.width, dimensions.height)

3. Command Line

Useful for quick checks.

npx image-size image1.jpg image2.png

Multi-size

If the target file/buffer is an HEIF, an ICO, or a CUR file, the width and height will be the ones of the largest image in the set.

An additional images array is available and returns the dimensions of all the available images

import { imageSizeFromFile } from 'image-size/fromFile'
// or
const { imageSizeFromFile } = require('image-size/fromFile')

const { images } = await imageSizeFromFile('images/multi-size.ico')
for (const dimensions of images) {
  console.log(dimensions.width, dimensions.height)
}

Using a URL

import url from 'node:url'
import http from 'node:http'
import { imageSize } from 'image-size'

const imgUrl = 'http://my-amazing-website.com/image.jpeg'
const options = url.parse(imgUrl)

http.get(options, function (response) {
  const chunks = []
  response
    .on('data', function (chunk) {
      chunks.push(chunk)
    })
    .on('end', function () {
      const buffer = Buffer.concat(chunks)
      console.log(imageSize(buffer))
    })
})

Disabling certain image types

import { disableTypes } from 'image-size'
// or
const { disableTypes } = require('image-size')

disableTypes(['tiff', 'ico'])

JPEG image orientation

If the orientation is present in the JPEG EXIF metadata, it will be returned by the function. The orientation value is a number between 1 and 8 representing a type of orientation.

import { imageSizeFromFile } from 'image-size/fromFile'
// or
const { imageSizeFromFile } = require('image-size/fromFile')

const { width, height, orientation } = await imageSizeFromFile('images/photo.jpeg')
console.log(width, height, orientation)

Limitations

  1. Partial File Reading

    • Only reads image headers, not full files
    • Some corrupted images might still report dimensions
  2. SVG Limitations

    • Only supports pixel dimensions and viewBox
    • Percentage values not supported
  3. File Access

    • Reading from files has a default concurrency limit of 100
    • Can be adjusted using setConcurrency()
  4. Buffer Requirements

    • Some formats (like TIFF) require the full header in buffer
    • Streaming partial buffers may not work for all formats

License

MIT

Credits

not a direct port, but an attempt to have something like dabble's imagesize as a node module.

Contributors