土豆不好吃

使用 Cloudflare Worker获取图片元数据

文章目录[显示]
这篇文章在 2024年10月05日23:31:04 更新了哦~

WebP Cloud 提供一个接口,可以用于获取图片的元数据,比如长宽、大小、色彩空间以及blurhash。这部分计算,尤其是blurhash其实还是略有压力的,我们就想能不能把这部分功能放到回源请求上。

对于 Azure Function来说,这必然不是问题,因为他几乎就是一个完整的NodeJS环境,可以用sharp的;但是对于Workers,由于他是V8,只支持NodeJS最基本的一些API,最多带上Wasm,这样用sharp就变成了几乎不可能的事情,因为要调用libvips。

最终经过了我的艰苦探索,发现一个名为 @cf-wasm/photon 的库,可以用来获取图片基础信息。首先需要 import

import { PhotonImage, SamplingFilter, resize } from '@cf-wasm/photon';

用起来也还行,首先我们需要通过 fetch获取图片,得到一个response,可以从这里拿到 ArrayBuffer

const response = await fetch(url)
const buffer = await response.arrayBuffer();

然后PhotonImage 需要Uint8Array,那先转换一下

const inputBytes = new Uint8Array(buffer);

然后加载图片

const inputImage = PhotonImage.new_from_byteslice(inputBytes);

宽高可以用 inputImage.get_width()inputImage.get_height()

色彩空间可以用 inputImage.get_image_data().colorSpace

文件大小直接 buffer.length就行

计算 blurhash建议先调整图片大小,毕竟 Worker有执行时间限制

const resized = resize(inputImage, 32, 32, SamplingFilter.Nearest);

然后计算

const blur = encode(resized.get_raw_pixels(), resized.get_width(), resized.get_height(), 4, 4);

至于图片格式,那只能靠magic header了,比如使用如下ChatGPT给我的神奇代码

function getImageFormatFromArrayBuffer(arrayBuffer) {
	const uint8Array = new Uint8Array(arrayBuffer);

	// Check for PNG (first 8 bytes: 89 50 4E 47 0D 0A 1A 0A)
	if (
		uint8Array[0] === 0x89 &&
		uint8Array[1] === 0x50 &&
		uint8Array[2] === 0x4e &&
		uint8Array[3] === 0x47 &&
		uint8Array[4] === 0x0d &&
		uint8Array[5] === 0x0a &&
		uint8Array[6] === 0x1a &&
		uint8Array[7] === 0x0a
	) {
		return 'png';
	}

	// Check for JPEG (first 3 bytes: FF D8 FF)
	if (uint8Array[0] === 0xff && uint8Array[1] === 0xd8 && uint8Array[2] === 0xff) {
		return 'jpeg';
	}

	// Check for GIF (first 6 bytes: GIF87a or GIF89a)
	if (
		uint8Array[0] === 0x47 &&
		uint8Array[1] === 0x49 &&
		uint8Array[2] === 0x46 &&
		uint8Array[3] === 0x38 &&
		(uint8Array[4] === 0x37 || uint8Array[4] === 0x39) &&
		uint8Array[5] === 0x61
	) {
		return 'gif';
	}

	// Check for BMP (first 2 bytes: 42 4D)
	if (uint8Array[0] === 0x42 && uint8Array[1] === 0x4d) {
		return 'bmp';
	}

	// Check for WebP (first 4 bytes: 52 49 46 46 and "WEBP" in bytes 8-11)
	if (
		uint8Array[0] === 0x52 &&
		uint8Array[1] === 0x49 &&
		uint8Array[2] === 0x46 &&
		uint8Array[3] === 0x46 &&
		uint8Array[8] === 0x57 &&
		uint8Array[9] === 0x45 &&
		uint8Array[10] === 0x42 &&
		uint8Array[11] === 0x50
	) {
		return 'webp';
	}

	return 'Unknown format';
}

部署

npm install @cf-wasm/photon
npm install blurhash
wrangler deploy 

就可以了。wrangler会自动打包,把依赖和wasm也一起上传上去

Azure Function

如果你使用的是Azure Function,那么事情就简单多了,直接安装并使用 sharp 就行。需要注意的一点是,Azure Function可以选择运行的环境是Linux还是Windows。所以本地也要安装好正确的sharp然后才可以部署。

npm install --cpu=x64 --os=linux sharp

详情可以参考Cross-platform

最终结果

需要注意 Workers 有内存限制,小心图片太大直接报错

原来是打算把 Worker和Function 用同一套代码库的,但是由于 Worker的限制,即使不同情况下使用不同的import,Worker还是没法兼容 Function🫠

所以只能分开两个分支了。

Cloudflare Workers 太弱智了,害我失去了人生中宝贵的三个小时


文章版权归原作者所有丨本站默认采用CC-BY-NC-SA 4.0协议进行授权|
转载必须包含本声明,并以超链接形式注明原作者和本文原始地址:
https://dmesg.app/worker-image-metadata.html
退出移动版