使用 GraphicsMagick 方法取决于 CollectionFS 的维度

Use GraphicsMagick methods depends on dimensions with CollectionFS

我正在寻找一种工作方式来根据图像大小在 CollectionFS transformWrite 函数中使用 GM 方法。 GM 中实现了一个大小方法,但它是异步工​​作的,因此似乎无法使用。

我尝试了以下方法:

gm(readStream, fileObj.name()).size(function(err, dimensions){
    if (err) {
        console.log('err with getting size:');
        console.log(err);
    }
    console.log('Result of media_size:');
    console.log(dimensions);
    // here do smth depends on the dimensions ...

    gm(readStream, fileObj.name()).resize('1200', '630').stream().pipe(writeStream);


});

当我在 CollectionFS 函数中使用上面的代码片段时,出现此错误:

错误:gm().stream() 或 gm().write() 具有不可读流。

这似乎是我使用异步函数的问题 - 当删除异步函数时,上传工作正常,但我无法访问上传图像的尺寸。

在刚访问 fileObjreadStreamwriteStream 时,是否有同步获取图像尺寸的解决方案?

编辑:

感谢 Jasper 对 wrapAsync 的提示。我测试了它并使用了这段代码:

var imgsize;
var img = gm(readStream, fileObj.name());
imgsize = Meteor.wrapAsync(img.size, img);
console.log('call wrapAsync:');
var result;
try {
    result = imgsize();
} catch (e) {
    console.log('Error:');
    console.log(e)
}
console.log('((after imgsize()))');

当查看 console.logs 时,脚本在 "call wrapAsync" 之后停止 - 也没有错误返回,因此很难判断问题出在哪里。我还尝试使用 NPM 包 "imagesize" 和 Meteor.wrapAsync(imagesize); 然后 imgsize(readStream) 导致相同的结果: "call wrapAsync:".

之后没有控制台日志

问题的核心不是 gm().size() 的异步行为,而是你两次使用 readStream 的事实。首先你用它来获取图像的大小,它清空 readStream。然后您尝试再次使用它来调整大小,但因为它已经结束,您会收到一条错误消息,告诉您流不可读。

我在 gm 包的底部找到了解决方案 streams documenation:

GOTCHA: when working with input streams and any 'identify' operation (size, format, etc), you must pass "{bufferStream: true}" if you also need to convert (write() or stream()) the image afterwards NOTE: this buffers the readStream in memory!

基于此和下面的小示例,我们可以将您的代码更改为:

gm(readStream, fileObj.name()).size({ bufferStream: true }, function(err, dimensions){
    if (err) {
        console.log('err with getting size:');
        console.log(err);
    }
    console.log('Result of media_size:');
    console.log(dimensions);
    // here do smth depends on the dimensions ...

    this.resize('1200', '630').stream().pipe(writeStream);
});

在回调内部,this 指的是您正在处理的图像,您可以使用它来继续您的链。

我在一个小示例流星应用程序中对此进行了测试,它有效!