Last active
August 29, 2015 14:11
-
-
Save Platane/a838cc4cebaf63025de1 to your computer and use it in GitHub Desktop.
sort picture
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var ExifImage = require('exif').ExifImage | |
, sizeOf = require('image-size') | |
, fs = require('fs') | |
, Promise = require("Promise") | |
var cp = function( src , dst ){ | |
return new Promise(function(resolve, reject){ | |
var contentBuffer = fs.readFileSync(src) | |
fs.writeFile( dst, contentBuffer, resolve ) | |
}) | |
} | |
// TODO make it race condition safe | |
var safe_cp = function( src , dst ){ | |
var dir_frag = dst.split('/').slice(0,-1) | |
var path = dir_frag.shift() | |
while( dir_frag.length ){ | |
path += '/'+dir_frag.shift() | |
if( !fs.existsSync( path ) ) | |
fs.mkdirSync( path ) | |
} | |
return cp( src , dst ) | |
} | |
var isImage = function( path ){ | |
return !!path.match(/\.(jpg|jpeg|png|gif|bmp)$/) | |
} | |
var analyseFile = (function(){ | |
var Analyzer = { | |
sizeFinished : false, | |
exifFinished : false, | |
dim : null, | |
analyse : function( path, resolve, reject ){ | |
if ( !isImage(path) ){ | |
analyserPool.push( this ) | |
return resolve( false ) | |
} | |
this.path = path | |
this.resolve = resolve | |
this.reject = reject | |
this.sizeFinished = this.exifFinished = false | |
try{ | |
sizeOf( path, this.sizeCb ); | |
new ExifImage({ image : path }, this.exifCb ); | |
}catch(err){ | |
console.log(err) | |
} | |
}, | |
sizeCb : function( err, dim ){ | |
this.sizeFinished = true | |
if( err ) | |
this.handleErr( 'size', err ); | |
else | |
this.dim = dim; | |
this.checkFinish(); | |
}, | |
exifCb : function( err, exif ){ | |
this.exifFinished = true | |
if( err ) | |
this.handleErr( 'exif', err ); | |
else | |
this.exif = exif; | |
this.checkFinish(); | |
}, | |
checkFinish : function(){ | |
if( this.exifFinished && this.sizeFinished ){ | |
if( this.dim && this.dim.width > 400 && this.dim.height > 400 ){ | |
var exif = (this.exif||{}).exif||{} | |
var m,l,date = exif.CreateDate || exif.DateTimeOriginal; | |
if( date && (m=date.match(/(\d\d\d\d):(\d\d):(\d\d)/)) ){ | |
l = m[1]+'-'+m[2]+'-'+m[3] | |
} else if( this.dim.width == 640 && this.dim.height == 480 ){ | |
l = 'no-date 640x480' | |
} else { | |
l = 'no-date' | |
} | |
var that = this | |
return safe_cp( this.path, (DST_FOLDER||'.')+'/'+l+'/'+this.path.split('/').slice(-1)[0] ) | |
.then( function(){ | |
analyserPool.push( that ) | |
}) | |
.then( that.resolve.bind( null, true ) ) | |
} else { | |
this.resolve( false ) | |
analyserPool.push( this ) | |
} | |
} | |
}, | |
handleErr : function( type , err){ | |
//this.resolve( err ) | |
} | |
} | |
var analyserPool = []; | |
var getAnalyser = function(){ | |
if( analyserPool.length ) | |
return analyserPool.shift() | |
var a = Object.create( Analyzer ) | |
a.exifCb = a.exifCb.bind( a ) | |
a.sizeCb = a.sizeCb.bind( a ) | |
return a | |
} | |
return function( path ){ | |
return new Promise(function(resolve, reject){ | |
getAnalyser().analyse( path , resolve , reject ) | |
}) | |
} | |
})() | |
var run = function( path ){ | |
var stats = { | |
folders: 0, | |
files: 0, | |
match: 0 | |
} | |
var find_files = function(){ | |
if( !open_folders.length ) | |
return | |
var base = open_folders.shift(), fullPath | |
var items = fs.readdirSync( base ) | |
for( var i=items.length;i--;) | |
if( fs.statSync( fullPath = base+'/'+items[i] ).isDirectory() ) | |
open_folders.push( fullPath ) | |
else | |
open_files.push( fullPath ) | |
} | |
var analyse_files = function( x ){ | |
// no file to treat | |
if( !open_files.length ) | |
return Promise.resolve( x ) | |
var ps = [] | |
var batch = open_files.splice(0,FILE_BATCH) | |
while( batch.length ) | |
ps.push( analyseFile( batch.shift() ) ) | |
return Promise.all( ps.concat(x||[]) ) | |
.then( analyse_files ) | |
} | |
var open_folders = [ path ], | |
open_files = [] | |
var cycle = function( x ){ | |
return new Promise(function(resolve, reject){ | |
stats.match += (x||[]).filter(function(u){ return u }).length | |
if( !open_folders.length ){ | |
console.log(stats) | |
return resolve( stats ) | |
} | |
find_files() | |
stats.folders += 1 | |
stats.files += open_files.length | |
console.log(stats) | |
analyse_files() | |
.then( cycle ) | |
}) | |
} | |
return cycle() | |
} | |
var SRC_FOLDER = './rec', | |
DST_FOLDER = './dst', | |
FILE_BATCH = 20 | |
run( SRC_FOLDER ) | |
.then( console.log.bind( console ) ) | |
.then( null, function( err ){ | |
console.log( 'err '+ err ) | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "picture-sort", | |
"version": "0.2.0", | |
"author": "Platane <[email protected]>", | |
"dependencies": { | |
"exif" : "*", | |
"image-size" : "*", | |
"promise" : "*", | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment