Passing 2 stdin arguments to a ImageMagick child_process

↘锁芯ラ 提交于 2020-01-02 07:36:08

问题


I have certain limitations that I won't specify that require me to use ImageMagick as a child-process.

I have multiple base 64 strings of jpg files which I want ImageMagick to process. Specifically I want ImageMagick to join the jpg files together. If I had 2 regular jpg files then from the command line I would use the following format.

node convert in_1.jpg in_2.jpg +append out.jpg

in a js file I would use

var spawn, magicCommands, imagic;
spawn = require('child_process').spawn;
magicCommands = ["in_1.jpg",
                 "in_2.jpg",
                 "+append",
                 "out.jpg"];
imagic = spawn("convert", magicCommands);

Now if I wanted to use 1 stdin buffer the following would work

    var arrow1JpgBase64, arrow2JpgBase64, arrowBuffer1, arrowBuffer2, magicCommands, imagic;

    spawn = require('child_process').spawn;
    exec = require('child_process').exec;

    arrow1JpgBase64 = "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCAAFAAkDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD1/wCFngjxJba78QbWT4reLTLH4pZ2mjt9PLTCSxs5VL+bbSYZUkWPCFUxGu1EHFdz/wAIb4j/AOiseM//AAF0n/5BoooA/9k=";
    arrow2JpgBase64 = "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCAAFAAkDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD1/wCOvgjxJc/Dt7NPit4tMt1q+k20Ty2+nqsLyajbIkoMFtFJuRmDjbIpyo5xmu5/4Q3xH/0Vjxn/AOAuk/8AyDRRQB//2Q==";
    arrowBuffer1 = new Buffer(arrow1JpgBase64, 'base64');
    arrowBuffer2 = new Buffer(arrow2JpgBase64, 'base64');
    magicCommands = ["jpg:",
                     "in_2.jpg",
                     "+append",
                     "out.jpg"];

    imagic = spawn("convert", magicCommands);
    imagic.stdin.write(arrowBuffer1);
    imagic.stdin.end();

    imagic.on('exit', function (code) {
        if (code === 0) {
            exec("open out.jpg");
        } else {
            console.log("error code: " + code);
        }
    }); // end of on exit

So far so good, but I want to use both of the buffers and not just 1 of them. So if I replace the "in_2.jpg", line with "jpg:", then how do I have to change the rest of the script to get it to work?

Thanks


回答1:


As Mark Setchell pointed out in the comments, using ImageMagick's fd: protocol will work.

var spawnOptions = {
      stdio: [
        0, // stdin,
        1, // stdout
        2, // stderr
        'pipe', // arrowBuffer1
        'pipe'  // arrowBuffer2
      ]
};
magic = spawn("convert", magicCommands, spawnOptions);

This opens fd:3 & fd:4 for piping. I'm not failure with the node.js family, but there usually a way to pass a resource in addition to pipe.

For your code

Update the magickCommands variable to read from new fd's, and write directly to new pipes

magicCommands = ["fd:3",
                 "fd:4",
                 "+append",
                 "out.jpg"];

// ...
imagic.stdio[3].write(arrowBuffer1);
imagic.stdio[4].write(arrowBuffer2);
imagic.stdio[3].end();
imagic.stdio[4].end();



回答2:


Not really sure what these "limitations" are, or what we are trying to avoid or work around, but the following technique of streaming multiple files into one may help you:

# Make a red block
convert -size 50x50 xc:red multi.miff

# Make a green block, but APPEND INTO A SINGLE STREAM
convert -size 50x50 xc:lime miff:- >> multi.miff

# Make a blue block, but APPEND INTO A SINGLE STREAM
convert -size 50x50 xc:blue miff:- >> multi.miff

# Tell IM to convert and append multiple images in single stream 
convert multi.miff +append result.png

Also, if you change the last command above to the following, IM will delete the file multi.miff as soon as it has finished with it - i.e. tidy up for you!

convert ephemeral:multi.miff +append result.png


来源:https://stackoverflow.com/questions/33655680/passing-2-stdin-arguments-to-a-imagemagick-child-process

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!