Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ayatokura committed May 21, 2016
0 parents commit c31a5cb
Show file tree
Hide file tree
Showing 19 changed files with 7,432 additions and 0 deletions.
39 changes: 39 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Logs
logs
*.log
npm-debug.log*

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules
jspm_packages

# Optional npm cache directory
.npm

# Optional REPL history
.node_repl_history

public/images
37 changes: 37 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "起動",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/bin/www",
"stopOnEntry": false,
"args": [],
"cwd": "${workspaceRoot}",
"preLaunchTask": null,
"runtimeExecutable": null,
"runtimeArgs": [
"--nolazy"
],
"env": {
"NODE_ENV": "development"
},
"externalConsole": false,
"sourceMaps": false,
"outDir": null
},
{
"name": "アタッチ",
"type": "node",
"request": "attach",
"port": 5858,
"address": "localhost",
"restart": false,
"sourceMaps": false,
"outDir": null,
"localRoot": "${workspaceRoot}",
"remoteRoot": null
}
]
}
69 changes: 69 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

// Expose files available in public/images so they can be viewed in the browser.
app.use('/public/images', express.static('public/images'));

// Use multer middleware to upload a photo to public/images
var multer = require('multer');
app.use(multer({dest: './public/images'}).single('userPhoto'));


app.use('/', routes);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});


module.exports = app;

16 changes: 16 additions & 0 deletions jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=759670
// for the documentation about the jsconfig.json format
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"allowSyntheticDefaultImports": true
},
"exclude": [
"node_modules",
"bower_components",
"jspm_packages",
"tmp",
"temp"
]
}
22 changes: 22 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "Bobble",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "~1.13.2",
"cookie-parser": "~1.3.5",
"debug": "~2.2.0",
"express": "~4.13.1",
"gifencoder": "^1.0.6",
"jade": "~1.11.0",
"jimp": "^0.2.24",
"morgan": "~1.6.1",
"multer": "^1.1.0",
"png-file-stream": "^1.0.0",
"project-oxford": "^1.2.0",
"serve-favicon": "~2.3.0"
}
}
8 changes: 8 additions & 0 deletions public/stylesheets/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}

a {
color: #00B7FF;
}
132 changes: 132 additions & 0 deletions routes/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Bobblehead Generator' });
});

/*test*/

module.exports = router;

// Requcired Dependencies
var fs = require('fs');
var path = require('path');
var oxford = require('project-oxford');
var Jimp = require('jimp');
var pngFileStream = require('png-file-stream');
var GIFEncoder = require('gifencoder');
var age;
var gender;


//一発目のアクセス時のファイル削除処理
// var dirname = './public/images'
// console.log(dirname);
// var RemoveFiles = fs.readdirSync(dirname);
// console.log(RemoveFiles);
// console.log(RemoveFiles.length);
// for (var i = 0; i < RemoveFiles.length; i++) {
// fs.unlink(path.join(dirname, RemoveFiles[i]));
// console.log("successfully deleted :", path.join(dirname, RemoveFiles[i]));
// }

// Handle POST request
router.post('/', function (req, res, next) {
var imgSrc = req.file ? req.file.path : '';
Promise.resolve(imgSrc)
.then(function detectFace(image) {
console.log("TODO: detect face using Oxford API.");
var client = new oxford.Client(process.env.OXFORD_API);
return client.face.detect({
path: image,
returnFaceId: true,
analyzesFaceLandmarks: true,
analyzesAge: true,
analyzesGender: true,
analyzesHeadPose: true,
analyzesSmile: true,
analyzesFacialHair: true,
// analyzeGlasses: true
});
})
.then(function generateBobblePermutations (response) {
var promises = [];
var degrees = [10, 0, -10];

console.log("TODO: generate multiple images with head rotated.");

// debug
age = response[0].faceAttributes.age;
gender = response[0].faceAttributes.gender;
console.log(age);
console.log(gender);
console.log('The Landmarks is:' + response[0].faceAttributes.faceLandmarks);
console.log('The age is: ' + response[0].faceAttributes.age);
console.log('The gender is: ' + response[0].faceAttributes.gender);
console.log('The headpose is: ' + response[0].faceAttributes.headPose);
console.log('The FaceID is: ' + response[0].faceAttributes.faceID);
console.log('The Smile is: ' + response[0].faceAttributes.smile);
console.log('The FacialHair is: ' + response[0].faceAttributes.facialHair);
// console.log('The Glasses is: ' + response[0].faceAttributes.glasses);
//
for (var i = 0; i < degrees.length; i++) {
var outputName = req.file.path + '-' + i + '.png';
promises.push(cropHeadAndPasteRotated(req.file.path,response[0].faceRectangle, degrees[i], outputName))
}
return Promise.all(promises);
})
.then(function generateGif (dimensions) {
return new Promise(function (resolve, reject) {
var encoder = new GIFEncoder(dimensions[0][0], dimensions[0][1]);
pngFileStream(req.file.path + '-?.png')
.pipe(encoder.createWriteStream({ repeat: 0, delay: 500 }))
.pipe(fs.createWriteStream(req.file.path + '.gif'))
.on('finish', function () {
resolve(req.file.path + '.gif');
});
})
}).then(function displayGif(gifLocation) {
res.render('index', { mes1: 'だいたい', mes2: '歳だと思う', mes3:'だと思う', age: age, gender: gender, title: 'Done!', image: gifLocation });
}).then(function() {
// 5 秒後にファイルを削除
setTimeout(function(){
//作成されたファイルを削除処理
// var dirname = path.dirname(req.file.path);
// console.log(dirname);
// var RemoveFiles = fs.readdirSync(path.dirname(req.file.path));
// console.log(RemoveFiles);
// console.log(RemoveFiles.length);
// for (var i = 0; i < RemoveFiles.length; i++) {
// fs.unlink(path.join(dirname, RemoveFiles[i]));
// console.log("successfully deleted :", path.join(dirname, RemoveFiles[i]));
// }
},5000);
});
});

function cropHeadAndPasteRotated(inputFile, faceRectangle, degrees, outputName) {
return new Promise (function (resolve, reject) {
Jimp.read(inputFile).then(function (image) {
// Face detection only captures a small portion of the face,
// so compensate for this by expanding the area appropriately.
var height = faceRectangle['height'];
var top = faceRectangle['top'] - height * 0.5;
height *= 1.6;
var left = faceRectangle['left'];
var width = faceRectangle['width'];
// Crop head, scale up slightly, rotate, and paste on original image
image.crop(left, top, width, height)
.scale(1.05)
.rotate(degrees, function(err, rotated) {
Jimp.read(inputFile).then(function (original) {
original.composite(rotated, left-0.1*width, top-0.05*height)
.write(outputName, function () {
resolve([original.bitmap.width, original.bitmap.height]);
});
});
});
});
});
}
9 changes: 9 additions & 0 deletions routes/users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
var express = require('express');
var router = express.Router();

/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});

module.exports = router;
4 changes: 4 additions & 0 deletions typings/browser.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/// <reference path="browser/ambient/express-serve-static-core/index.d.ts" />
/// <reference path="browser/ambient/express/index.d.ts" />
/// <reference path="browser/ambient/node/index.d.ts" />
/// <reference path="browser/ambient/serve-static/index.d.ts" />
Loading

0 comments on commit c31a5cb

Please sign in to comment.