Lambdaで画像に描画する

Lambdaからのjava呼び出しで描画系が使えることが確認できたので、Lambda内で画像に描画してみます。

Lambdaコード

Lambda Functionは、先日のエントリとほぼ一緒です。Java実行後に、/tmpに生成された画像をS3に吐きだす部分を追加しています。

var aws = require('aws-sdk');
var fs = require('fs');
var javaBucket = "lambda-java";
var javaBucketRegion = "us-west-2";
var mainClass = "GraphicsTest";

exports.handler = function(event, context) {
  loadAllFiles(function() {
    var spawn = require('child_process').spawn;
    var child = spawn('java', [ "-cp", "/tmp:/tmp/*", mainClass,
        JSON.stringify(event,null,2) ]);
    child.stdout.on('data', function(data) {  console.log("stdout:" + data);  });
    child.stderr.on('data', function(data) {  console.log("stderr:" + data);  });
    child.on('close', function(code) {  var s3 = new aws.S3({  params : {
          Bucket : javaBucket,   Key : "result.jpg"   }
      });
      var body = fs.readFileSync('/tmp/result.jpg');
      s3.putObject({ Body : body  }, function(err) {
        if (err) {   context.done("ERROR", err);
        } else {  context.done(null, 'put result');    }
      });
    });
  });
};
function loadAllFiles(callback) {
  var s3 = new aws.S3({  region : javaBucketRegion });
  s3.listObjects({   Bucket : javaBucket
  }, function(err, data) {  if (err) {
      throw err;  } else {
      var cb = createCounter(data.Contents.length, callback);
      for (var i = 0; i < data.Contents.length; i++) {
        loadObject(cb, data.Contents[i].Key);
      }
    }
  });
}
function loadObject(callback, key) {
  var s3 = new aws.S3({  region : javaBucketRegion });
  s3.getObject({  Bucket : javaBucket,  Key : key
  }, function(err, data) {  
    if (err) {   throw err; } else {
      console.log("load:" + key);
      fs.writeFileSync('/tmp/' + key, data.Body);
      callback();
    }
  });
}
function createCounter(length, callback) {
  var counter = 0;
  return function() {
    if (++counter == length) {
      callback();
    }
  }
}

Javaコード

画像に描画を行うコードになります。作った画像は、/tmp/result.jpgに吐きだします。jarファイルには、ipaフォントと、元になる画像を入れておきます。
画像は、手元にあるイケメン画像を選びました。


import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

public class GraphicsTest {

  public static void main(String[] args) throws Exception {
    Font font = Font.createFont(Font.TRUETYPE_FONT,
        GraphicsTest.class.getResourceAsStream("/ipagp.ttf"));
    GraphicsEnvironment ge = GraphicsEnvironment
        .getLocalGraphicsEnvironment();
    ge.registerFont(font);
    
    BufferedImage img = ImageIO.read(GraphicsTest.class
        .getResourceAsStream("m2o.jpg"));

    Graphics2D g2 = (Graphics2D) img.getGraphics();
    g2.setFont(new Font("IPAPGothic", Font.BOLD, 35));
    g2.setPaint(Color.black);
    g2.fillRect(150, 100, 150, 20);
    g2.setPaint(Color.white);
    g2.drawString("HPCチョットデキル", 60, 300);
    ImageIO.write(img, "png", new File("/tmp/result.jpg"));
    System.out.println("draw end");
  }
}


描画した結果です。



日本語描画もOKですね。Cognito+S3+Lambdaで、脳内メーカーぐらいならEC2レスで作れそうです。
次はOpenCVを動かしてみたいと思います。


なお、以下実行ログです。メモリ利用量が73MB、実行時間が9.8秒でした。

Logs
----
START RequestId: 1646081e-75c6-11e4-ae89-2105a6e34bc3
2014-11-26T23:44:08.875Z	1646081e-75c6-11e4-ae89-2105a6e34bc3	load:result.jpg
2014-11-26T23:44:09.515Z	1646081e-75c6-11e4-ae89-2105a6e34bc3	load:eval.jar
2014-11-26T23:44:16.774Z	1646081e-75c6-11e4-ae89-2105a6e34bc3	stdout:draw end

END RequestId: 1646081e-75c6-11e4-ae89-2105a6e34bc3
REPORT RequestId: 1646081e-75c6-11e4-ae89-2105a6e34bc3	Duration: 9759.41 ms	Billed Duration: 9800 ms 	Memory Size: 256 MB	Max Memory Used: 73 MB	

Message
-------
put result