Skip to content

Instantly share code, notes, and snippets.

@Platane
Last active August 29, 2015 14:11
Show Gist options
  • Save Platane/a838cc4cebaf63025de1 to your computer and use it in GitHub Desktop.
Save Platane/a838cc4cebaf63025de1 to your computer and use it in GitHub Desktop.
sort picture
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 )
})
{
"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