市场目前公开可处理图片的有七牛云,阿里云等大厂进行图像处理,应某S3Store 业务需求,自行解决图片处理;这里结合node 的sharp库,很好用
npm 地址:sharp - npm
教程API地址:sharp - High performance Node.js image processing
首先进行图片正则规则匹配
for (const rule of rules) {
const m = pathname.match(rule.pattern);
if (m && rule.process) {
const fn = async function () {
const o = await rule.process.bind(rule)(pathname, m);
if (o.data && o.info && Buffer.isBuffer(o.data)) {
return {
data: o.data.toString('base64'),
info: o.info,
isBase64Encoded: true,
};
}
return {
data: JSON.stringify(o),
info: { format: 'application/json' },
};
};
fn.rule = rule;
return fn;
}
}
里面划分了两个处理文件 基础处理 (模式,宽,高,质量)和高级处理
const sharp = require('sharp');
const createError = require('http-errors');
const JPG = 'jpg';
const JPEG = sharp.format.jpeg.id;
class ImageView {
constructor(image) {
this._image = image;
this._m = 0;
this._w = 0;
this._h = 0;
this._q = 75;
}
m(v) {
this._m = v;
return this;
}
w(v) {
const width = parseInt(v, 10);
this._w = width;
return this;
}
h(v) {
const height = parseInt(v, 10);
this._h = height;
return this;
}
q(v) {
if (Number.isNaN(v)) throw createError(400, 'Invalid input');
this._q = v;
return this;
}
async process() {
const image = this._image;
const metadata = await image.metadata();
if (this._w || this._h) {
const opts = {};
if (this._m === 0) {
opts.fit = sharp.fit.inside;
} else if (this._m === 1) {
opts.fit = sharp.fit.cover;
} else if (this._m === 2) {
opts.fit = sharp.fit.inside;
}
image.resize(this._w, this._h, opts);
}
if (this._q && (JPEG === metadata.format || JPG === metadata.format)) {
image.jpeg({ quality: this._q });
}
return image;
}
}
exports.ImageView2= ImageView;
高级处理js文件
const sharp = require('sharp');
const createError = require('http-errors');
const JPG = 'jpg';
const JPEG = sharp.format.jpeg.id;
class ImageMogr {
constructor(image) {
if (!image) {
throw createError(500, 'Empty image');
}
if (!(image instanceof sharp)) {
throw createError(500, 'Image must be a sharp object');
}
this._image = image;
this._b = false;
this._colorspace = false;
this._q = 75;
this._thumbnail = async () => {};
this._crop = async () => {};
}
q(v) {
if (Number.isNaN(v)) throw createError(400, 'Invalid input');
this._q = v;
return this;
}
b(v) {
if (v) {
this._b = v;
}
return this;
}
colorspace(v) {
if (v) {
this._colorspace = v;
}
return this;
}
thumbnail(v) {
const rules = ['业务方正则集合,用于匹配'];
// eslint-disable-next-line no-restricted-syntax
for (const r of rules) {
const m = v.match(r.pattern);
if (m) {
this._thumbnail = () => r.proc(m);
return this;
}
}
throw createError(400, 'Invalid thumbnail query');
}
crop(widthNumber, heightNumber, gravity) {
const w = parseInt(widthNumber, 10);
if (Number.isNaN(w) || w <= 0) {
throw createError(400, 'Invalid width');
}
const h = parseInt(heightNumber, 10);
if (Number.isNaN(h) || h <= 0) {
throw createError(400, 'Invalid height');
}
if (gravity === 'center') {
this._crop = async () => {
const buffer = await this._image.toBuffer();
const metadata = await sharp(buffer).metadata();
if (metadata.width && metadata.height) {
const x = (metadata.width - w) >> 1;
const y = (metadata.height - h) >> 1;
const region = {
left: x,
top: y,
width: w,
height: h,
};
this._image.extract(region);
} else {
console.warn('Cannot fetch width/height in metadata');
}
};
} else {
throw createError(400, 'Invalid crop gravity');
}
return this;
}
async process() {
const image = this._image;
const metadata = await image.metadata();
if (this._q && (JPEG === metadata.format || JPG === metadata.format)) {
image.jpeg({ quality: this._q });
}
if (this._b) {
image.blur(50);
}
if (this._colorspace) {
image.pipelineColourspace('grey16').toColourspace('srgb');
}
if (this._thumbnail) {
await this._thumbnail();
}
if (this._crop) {
await this._crop();
}
return image;
}
}
exports.ImageMogr = ImageMogr;
图片信息处理
const sharp = require('sharp');
const createError = require('http-errors');
class ImageInfo {
constructor(image) {
if (!image) {
throw createError(500, 'Empty image');
}
if (!(image instanceof sharp)) {
throw createError(500, 'Image must be a sharp object');
}
this._image = image;
}
async process() {
const image = this._image;
const metadata = await image.metadata();
return {
size: metadata.size,
format: metadata.format,
width: metadata.width,
height: metadata.height,
colorModel: metadata.space,
};
}
}