如何将缓冲区传递给 node.js 中的 imagemin 模块?
how to pass a buffer to imagemin module in node.js?
在旧版本的 imagemin 中,我能够像这样向模块传递缓冲区:
new ImageMinify()
.src(StreamOrBuffer)
.use(ImageMinify.jpegtran({progressive: true}))
在当前版本的 imagemin 中没有 src 函数,调用该模块将产生一个 promise。
我找不到如何在较新版本的 imagemin 中获得相同的结果
是否可以完成或取消支持?
我从 github 存储库中得到了答案。我在这里发布答案以防其他人遇到同样的问题:
您可以使用 imagemin.buffer 提供缓冲区。从未支持流。
这是一个函数:
- 使用 sharp
在给定尺寸内调整图像大小
- 使用带有缓冲区的 imagemin 来压缩图像(它将流转换为缓冲区)
- 保存缓冲区
我没有找到使imagemin 兼容stream with style 的好方法,所以它使用临时可写流来存储缓冲区。
/**
* It:
* 1. Resize the image directly from a GCP read stream to a 500x500 keeping the aspect ratio
* 2. Create a temp Writable stream to transform it to buffer
* 3. Compress the image using 'imagemin'
* 4. Save it to GCP back
* 5. Delete original image
*
* @param filePath
* @param width
* @param height
*/
const resize = async (
bucket: Bucket,
filePath: string,
width: number,
height: number
): Promise<[File, string]> => {
const ext = path.extname(filePath)
const fileName = path.basename(filePath, ext)
const [imageMetadata] = await bucket.file(filePath).getMetadata()
const metadata = {
contentType: imageMetadata.contentType,
predefinedAcl: 'publicRead',
}
const newFileName = `${fileName}_${width}x${height}${ext}`
const thumbFilePath = path.join(path.dirname(filePath), newFileName)
const outputFile = bucket.file(thumbFilePath)
const bufferData: any[] = []
const tempWritableStream = new stream.Writable()
tempWritableStream._write = function(chunk, encoding, done) {
bufferData.push(chunk)
done()
}
const pipeline = sharp()
bucket
.file(filePath)
.createReadStream()
.pipe(pipeline)
pipeline
.resize(width, height, { fit: 'inside' })
.jpeg({ progressive: true, force: false })
.png({ progressive: true, force: false })
.pipe(tempWritableStream)
return await new Promise((resolve, reject) =>
tempWritableStream
.on('finish', async () => {
const transformedBuffer = await minimizeImageFromBufferArray(
bufferData
)
await saveImage(transformedBuffer, outputFile, metadata)
await bucket.file(filePath).delete()
resolve([outputFile, newFileName])
})
.on('error', reject)
)
}
在旧版本的 imagemin 中,我能够像这样向模块传递缓冲区:
new ImageMinify()
.src(StreamOrBuffer)
.use(ImageMinify.jpegtran({progressive: true}))
在当前版本的 imagemin 中没有 src 函数,调用该模块将产生一个 promise。
我找不到如何在较新版本的 imagemin 中获得相同的结果
是否可以完成或取消支持?
我从 github 存储库中得到了答案。我在这里发布答案以防其他人遇到同样的问题:
您可以使用 imagemin.buffer 提供缓冲区。从未支持流。
这是一个函数:
- 使用 sharp
在给定尺寸内调整图像大小
- 使用带有缓冲区的 imagemin 来压缩图像(它将流转换为缓冲区)
- 保存缓冲区
我没有找到使imagemin 兼容stream with style 的好方法,所以它使用临时可写流来存储缓冲区。
/**
* It:
* 1. Resize the image directly from a GCP read stream to a 500x500 keeping the aspect ratio
* 2. Create a temp Writable stream to transform it to buffer
* 3. Compress the image using 'imagemin'
* 4. Save it to GCP back
* 5. Delete original image
*
* @param filePath
* @param width
* @param height
*/
const resize = async (
bucket: Bucket,
filePath: string,
width: number,
height: number
): Promise<[File, string]> => {
const ext = path.extname(filePath)
const fileName = path.basename(filePath, ext)
const [imageMetadata] = await bucket.file(filePath).getMetadata()
const metadata = {
contentType: imageMetadata.contentType,
predefinedAcl: 'publicRead',
}
const newFileName = `${fileName}_${width}x${height}${ext}`
const thumbFilePath = path.join(path.dirname(filePath), newFileName)
const outputFile = bucket.file(thumbFilePath)
const bufferData: any[] = []
const tempWritableStream = new stream.Writable()
tempWritableStream._write = function(chunk, encoding, done) {
bufferData.push(chunk)
done()
}
const pipeline = sharp()
bucket
.file(filePath)
.createReadStream()
.pipe(pipeline)
pipeline
.resize(width, height, { fit: 'inside' })
.jpeg({ progressive: true, force: false })
.png({ progressive: true, force: false })
.pipe(tempWritableStream)
return await new Promise((resolve, reject) =>
tempWritableStream
.on('finish', async () => {
const transformedBuffer = await minimizeImageFromBufferArray(
bufferData
)
await saveImage(transformedBuffer, outputFile, metadata)
await bucket.file(filePath).delete()
resolve([outputFile, newFileName])
})
.on('error', reject)
)
}