5

Using nodejs and imagemagick am able to re-size an image and send it to the browser with this.

    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);

The test image is read from the file-system, I want to alter so that test image is a binary string.

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

My plan is to store the binary strings in Mongodb and read them of dynamically.

jamjam
  • 3,171
  • 7
  • 34
  • 39

3 Answers3

5

Take a look at the node module node-imagemagick. There is the following example on the module's page to resize and image and write it to a file...

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')
});

You can alter this code to do the following...

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);

Ps. Haven't run the code above yet. Will try do it shortly, but it should give you an idea of how to asynchronously resize and stream a file.

Split Your Infinity
  • 4,159
  • 1
  • 21
  • 19
  • 1
    Thanks or you answer. But this is not what want to do. I never want read anything from the file-system. – jamjam Jul 22 '12 at 10:30
3

Since you are using spawn() to invoke the ImageMagick command line convert, the normal approach is to write intermediate files to a temp directory where they will get cleaned up either immediately after use or as a scheduled/cron job.

If you want to avoid writing the file to convert, one option to try is base64 encoding your images and using the inline format. This is similar to how images are encoded in some HTML emails or web pages.

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

NOTE: There is a limit on the size of command-line options you can pass .. Imagemagick docs suggest 5000 bytes. Base64-encoded strings are larger than the original (Wikipedia suggests a rough guide of 137% larger) which could be very limiting unless you're showing thumbnails.

Another ImageMagick format option is ephemeral:

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

If you want to avoid the I/O passing altogether, you would need a Node.js module that directly integrates a low-level library like ImageMagick or GD rather than wrapping command line tools.

Stennie
  • 63,885
  • 14
  • 149
  • 175
0

What have you tried so far? You can use GridFS to store the image data and retrieve as a stream from there.. This in C#..Not sure if this helps..

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;
}

You can now use the stream returned by ShowPhoto.

Florian Margaine
  • 58,730
  • 15
  • 91
  • 116
Aafreen Sheikh
  • 4,949
  • 6
  • 33
  • 43
  • Am afraid I don't understand c#. I know about GridFs which am not going use as my images can easily be stored in regular document. Anyway I will figure out how to read from Mongodb later but now I just need to read from a string. My problem is that I don't know how to pass a binary string instead of a filename to imagemagick. – jamjam Jul 22 '12 at 10:36
  • 1
    Either there has to be a way to pass a binary string to imagemagick or you may write this stream to a temp file and then use that file's name to pass to imagemagick..There's no compulsion about using GridFS..It's just good for images. But if your images are few and you have a dedicated collection in MongoDB storing only image binaries, then fine..use normal documents..Logic essentially remains the same. Instead of database.GridFS.FindOne, you write database.MyCollection.FindOne. – Aafreen Sheikh Jul 22 '12 at 10:45
  • The temp thing is what am trying to avoid, see this http://stackoverflow.com/questions/1295618/have-gd-get-image-from-binary-string . Bottom line what I am trying to do, is possible in PHP. – jamjam Jul 22 '12 at 10:53
  • 1
    Now I am afraid I don't understand imagemagick at all but it seems the answer in the link you mentioned also creates a temp image variable and then destroys it. – Aafreen Sheikh Jul 22 '12 at 11:17
  • Oops. I did notice that. I am going the temp route for now. – jamjam Jul 22 '12 at 11:23