【问题标题】:Resizing images with Nodejs and Imagemagick使用 Nodejs 和 Imagemagick 调整图像大小
【发布时间】:2012-07-22 10:06:26
【问题描述】:

使用 nodejs 和 imagemagick 可以重新调整图像大小并将其发送到浏览器。

    var http = require('http'),
        spawn = require('child_process').spawn;

    http.createServer(function(req, res) {

        var image = 'test.jpg';
        var convert = spawn('convert', [image, '-resize', '100x100', '-']);

        convert.stdout.pipe(res);
        convert.stderr.pipe(process.stderr);

    }).listen(8080);

测试图像是从文件系统中读取的,我想改变测试图像是二进制字符串。

var image = 'some long binray string representing an image.......';

我的计划是将二进制字符串存储在 Mongodb 中并动态读取它们。

【问题讨论】:

    标签: node.js mongodb imagemagick


    【解决方案1】:

    看看节点模块node-imagemagick。模块页面上有以下示例,用于调整大小和图像并将其写入文件...

    var fs = require('fs');
    im.resize({
      srcData: fs.readFileSync('kittens.jpg', 'binary'),
      width:   256
    }, function(err, stdout, stderr){
      if (err) throw err
      fs.writeFileSync('kittens-resized.jpg', stdout, 'binary');
      console.log('resized kittens.jpg to fit within 256x256px')
    });
    

    您可以更改此代码以执行以下操作...

    var mime = require('mime')   // Get mime type based on file extension. use "npm install mime"
      , fs = require('fs')
      , util = require('util')
      , http = require('http')
      , im = require('imagemagick');
    
    http.createServer(function (req, res) {
        var filePath = 'test.jpg';
    
        fs.stat(filePath, function (err, stat) {
            if (err) { throw err; }
    
            fs.readFile(filePath, 'binary', function (err, data) {
                if (err) { throw err; }
    
                im.resize({
                    srcData: data,
                    width: 256
                }, function (err, stdout, stderr) {
                    if (err) { throw err; }
    
                    res.writeHead(200, {
                        'Content-Type': mime.lookup(filePath),
                        'Content-Length': stat.size
                    });
    
                    var readStream = fs.createReadStream(filePath);
    
                    return util.pump(readStream, res);
                });
            });
        });
    }).listen(8080);
    

    附言。还没有运行上面的代码。很快就会尝试这样做,但它应该让您了解如何异步调整文件大小和流式传输文件。

    【讨论】:

    • 谢谢或者你回答。但这不是想要做的。我从不想从文件系统中读取任何内容。
    【解决方案2】:

    由于您使用spawn() 来调用ImageMagick 命令行convert,因此通常的方法是将中间文件写入临时目录,在使用后它们将立即被清理或作为计划/cron 作业。

    如果您想避免写入要转换的文件,可以尝试的一种选择是对图像进行 base64 编码并使用inline format。这类似于图像在某些 HTML 电子邮件或网页中的编码方式。

     inline:{base64_file|data:base64_data}
     Inline images let you read an image defined in a special base64 encoding.
    

    注意:您可以传递的命令行选项的大小是有限制的。Imagemagick 文档建议 5000 字节。 Base64 编码的字符串比原始字符串大(维基百科建议使用137% larger 的粗略指南),除非您显示缩略图,否则这可能非常有限。

    另一个 ImageMagick 格式选项是ephemeral:

     ephemeral:{image_file}
     Read and then Delete this image file.
    

    如果您想完全避免 I/O 传递,您需要一个直接集成 ImageMagick 或 GD 等低级库的 Node.js 模块,而不是包装命令行工具。

    【讨论】:

      【解决方案3】:

      到目前为止,您尝试过什么?您可以使用 GridFS 存储图像数据并从那里作为流检索。这在 C# 中。不确定这是否有帮助..

      public static void UploadPhoto(string name)
      {
          var server = MongoServer.Create("mongodb://localhost:27017");
          var database = server.GetDatabase("MyDB");
          string fileName = name;
          using (var fs = new FileStream(fileName, FileMode.Open))
          {
              var gridFsInfo = database.GridFS.Upload(fs, fileName);
              var fileId = gridFsInfo.Id;
              //ShowPhoto(filename);
          }
      }
      
      public static Stream ShowPhoto(string name)
      {
          var server = MongoServer.Create("mongodb://localhost:27017");
          var database = server.GetDatabase("MyDB");
          var file = database.GridFS.FindOne(Query.EQ("filename",name));
          var stream = file.OpenRead())
          var bytes = new byte[stream.Length];
          stream.Read(bytes,0,(int)stream.Length);
          return stream;
      }
      

      您现在可以使用 ShowPhoto 返回的流。

      【讨论】:

      • 恐怕我不懂c#。我知道不会使用的 GridF,因为我的图像可以很容易地存储在常规文档中。无论如何,我稍后会弄清楚如何从 Mongodb 中读取,但现在我只需要从字符串中读取。我的问题是我不知道如何将二进制字符串而不是文件名传递给 imagemagick。
      • 要么必须有一种方法将二进制字符串传递给 imagemagick,要么你可以将此流写入临时文件,然后使用该文件的名称传递给 imagemagick。使用 GridFS 没有强制要求..这对图像有好处。但是,如果您的图像很少,并且您在 MongoDB 中有一个仅存储图像二进制文件的专用集合,那么很好..使用普通文档..逻辑基本上保持不变。您编写 database.MyCollection.FindOne,而不是 database.GridFS.FindOne。
      • 临时的事情是我试图避免的,见stackoverflow.com/questions/1295618/…。底线是我想要做的,在 PHP 中是可能的。
      • 现在恐怕我根本不懂imagemagick,但您提到的链接中的答案似乎也创建了一个临时图像变量,然后将其销毁。
      • 糟糕。我确实注意到了。我现在走临时路线。
      猜你喜欢
      • 2014-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-05
      • 2011-03-11
      • 1970-01-01
      相关资源
      最近更新 更多