1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-01-26 05:27:35 +02:00

implementing exif/image metadata reading

This commit is contained in:
Braun Patrik 2016-05-12 18:24:26 +02:00
parent c66a9b49f3
commit 33347dfd0c
14 changed files with 175 additions and 26 deletions

View File

@ -1,9 +1,17 @@
import * as fs from "fs";
import * as path from "path";
import * as mime from "mime";
import * as sizeOf from "image-size";
import * as iptc from "node-iptc";
import * as exif_parser from "exif-parser";
import {Directory} from "../../common/entities/Directory";
import {Photo} from "../../common/entities/Photo";
import {
Photo,
PhotoMetadata,
ImageSize,
CameraMetadata,
PositionMetaData,
GPSMetadata
} from "../../common/entities/Photo";
export class DiskManager {
public static scanDirectory(relativeDirectoryName, cb:(error:any, result:Directory) => void) {
@ -14,6 +22,7 @@ export class DiskManager {
let directory = new Directory(1, directoryName, directoryParent, new Date(), [], []);
let promises:Array< Promise<any> > = [];
fs.readdir(absoluteDirectoryName, function (err, list) {
if (err) {
@ -29,12 +38,19 @@ export class DiskManager {
}
if (DiskManager.isImage(fullFilePath)) {
let dimensions = sizeOf(fullFilePath);
directory.photos.push(new Photo(1, file, directory, dimensions.width, dimensions.height));
let promise = DiskManager.loadPhotoMetadata(fullFilePath).then((photoMetadata)=> {
directory.photos.push(new Photo(1, file, directory, photoMetadata));
});
promises.push(promise);
}
}
Promise.all(promises).then(()=> {
return cb(err, directory);
});
});
}
@ -60,4 +76,51 @@ export class DiskManager {
return false;
}
private static loadPhotoMetadata(fullPath):Promise<PhotoMetadata> {
return new Promise<PhotoMetadata>((resolve:(metadata:PhotoMetadata)=>void, reject) => {
fs.readFile(fullPath, function (err, data) {
if (err) {
reject(err);
} else {
let exif = exif_parser.create(data).parse();
let iptcData = iptc(data);
let imageSize:ImageSize = {width: exif.imageSize.width, height: exif.imageSize.height};
let cameraData:CameraMetadata = {
ISO: exif.tags.ISO,
model: exif.tags.Modeol,
maker: exif.tags.Make,
fStop: exif.tags.FNumber,
exposure: exif.tags.ExposureTime,
focalLength: exif.tags.FocalLength,
lens: exif.tags.LensModel,
};
let GPS:GPSMetadata = {
latitude: exif.tags.GPSLatitude,
longitude: exif.tags.GPSLongitude,
altitude: exif.tags.GPSAltitude
};
let positionData:PositionMetaData = {
GPSData: GPS,
country: iptcData.country_or_primary_location_name,
state: iptcData.province_or_state,
city: iptcData.city
};
let keywords:[string] = iptcData.keywords;
let creationDate:Date = iptcData.date_time;
let metadata:PhotoMetadata = new PhotoMetadata(keywords, cameraData, positionData, imageSize, creationDate);
resolve(metadata);
}
});
});
}
}

15
backend/model/exif.d.ts vendored Normal file
View File

@ -0,0 +1,15 @@
declare module "node-iptc" {
function e(data):any;
module e {
}
export = e;
}
declare module "exif-parser" {
export function create(data):any;
}

View File

@ -16,6 +16,7 @@ export class MongoGalleryManager implements IGalleryManager {
let directoryName = path.basename(relativeDirectoryName);
let directoryParent = path.join(path.dirname(relativeDirectoryName), "/");
DirectoryModel.findOne({
name: directoryName,
path: directoryParent
@ -64,7 +65,7 @@ export class MongoGalleryManager implements IGalleryManager {
let directoryEntity = new Directory(directoryModel._id, directoryModel.name, directoryModel.path, directoryModel.lastupdate, [], []);
directoryModel.photos.forEach((photo) => {
let photoEntity = new Photo(photo._id, photo.name, null, photo.width, photo.height);
let photoEntity = new Photo(photo._id, photo.name, directoryEntity, photo.metadata);
directoryEntity.photos.push(photoEntity);
});

View File

@ -4,12 +4,36 @@ import {Schema} from "mongoose";
export var PhotoModel = DatabaseManager.getInstance().getModel('photo', {
name: String,
width:Number,
height: Number,
directory: {
type: Schema.Types.ObjectId,
ref: 'directory'
},
metadata: {
keywords: [String],
cameraData: {
ISO: Number,
maker: String,
fStop: Number,
exposure: Number,
focalLength: Number,
lens: String
},
positionData: {
GPSData: {
latitude: Number,
longitude: Number,
altitude: Number
},
country: String,
state: String,
city: String
},
size: {
width: Number,
height: Number
},
creationDate: Date
}
});

View File

@ -19,7 +19,7 @@ export class GalleryRouter {
private addDirectoryList() {
this.app.get(["/api/gallery/content/:directory(*)", "/api/gallery/", "/api/gallery//"],
AuthenticationMWs.authenticate,
// AuthenticationMWs.authenticate,
GalleryMWs.listDirectory,
RenderingMWs.renderResult
);

View File

@ -35,7 +35,20 @@ export class Utils {
public static setKeys(targetObject, sourceObject) {
Object.keys(sourceObject).forEach((key)=> {
if (typeof targetObject[key] === "object") {
Utils.updateKeys(targetObject[key], sourceObject[key]);
Utils.setKeys(targetObject[key], sourceObject[key]);
} else {
targetObject[key] = sourceObject[key];
}
});
}
public static setKeysForced(targetObject, sourceObject) {
Object.keys(sourceObject).forEach((key)=> {
if (typeof sourceObject[key] === "object") {
if (typeof targetObject[key] === "undefined") {
targetObject[key] = {};
}
Utils.setKeysForced(targetObject[key], sourceObject[key]);
} else {
targetObject[key] = sourceObject[key];
}

View File

@ -1,14 +1,47 @@
import {Directory} from "./Directory";
export class Photo {
constructor(public id?:number, public name?:string, public directory?:Directory, public width?:number, public height?:number) {
constructor(public id?:number,
public name?:string,
public directory?:Directory,
public metadata?:PhotoMetadata) {
}
}
/*public static getThumbnailPath(photo:Photo) {
return Utils.concatUrls("/api/gallery/content/", photo.directory.path, photo.directory.name, photo.name, "thumbnail");
export class PhotoMetadata {
constructor(public keywords?:Array<string>,
public cameraData?:CameraMetadata,
public positionData?:PositionMetaData,
public size?:ImageSize,
public creationDate?:Date) {
}
}
public static getPhotoPath(photo:Photo) {
return Utils.concatUrls("/api/gallery/content/", photo.directory.path, photo.directory.name, photo.name);
}*/
export interface ImageSize {
width:number;
height:number;
}
export interface CameraMetadata {
ISO?:number;
model?:string;
maker?:string;
fStop?:number;
exposure?:number;
focalLength?:number;
lens?:string;
}
export interface PositionMetaData {
GPSData?:GPSMetadata;
country?:string;
state?:string;
city?:string;
}
export interface GPSMetadata {
latitude?:string;
longitude?:string;
altitude?:string;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

View File

@ -55,7 +55,7 @@ export class GridRowBuilder {
public calcRowHeight():number {
let width = 0;
for (let i = 0; i < this.photoRow.length; i++) {
width += ((this.photoRow[i].width) / (this.photoRow[i].height)); //summing up aspect ratios
width += ((this.photoRow[i].metadata.size.width) / (this.photoRow[i].metadata.size.height)); //summing up aspect ratios
}
let height = (this.containerWidth - this.photoRow.length * (this.photoMargin * 2) - 1) / width; //cant be equal -> width-1

View File

@ -104,7 +104,7 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
let imageHeight = rowHeight - (this.IMAGE_MARGIN * 2);
photoRowBuilder.getPhotoRow().forEach((photo) => {
let imageWidth = imageHeight * (photo.width / photo.height);
let imageWidth = imageHeight * (photo.metadata.size.width / photo.metadata.size.height);
this.photosToRender.push(new GridPhoto(photo, imageWidth, imageHeight));
});

View File

@ -176,12 +176,12 @@ export class GalleryLightboxComponent {
private calcLightBoxPhotoDimension(photo:Photo):Dimension {
let width = 0;
let height = 0;
if (photo.height > photo.width) {
width = Math.round(photo.width * (this.getScreenHeight() / photo.height));
if (photo.metadata.size.height > photo.metadata.size.width) {
width = Math.round(photo.metadata.size.width * (this.getScreenHeight() / photo.metadata.size.height));
height = this.getScreenHeight();
} else {
width = this.getScreenWidth();
height = Math.round(photo.height * (this.getScreenWidth() / photo.width));
height = Math.round(photo.metadata.size.height * (this.getScreenWidth() / photo.metadata.size.width));
}
let top = (this.getScreenHeight() / 2 - height / 2);
let left = (this.getScreenWidth() / 2 - width / 2);

View File

@ -35,14 +35,15 @@
"core-js": "^2.4.0",
"debug": "^2.2.0",
"ejs": "^2.4.1",
"exif-parser": "^0.1.9",
"express": "^4.13.4",
"express-session": "^1.13.0",
"image-size": "^0.5.0",
"jimp": "^0.2.24",
"mime": "^1.3.4",
"mongoose": "^4.4.16",
"morgan": "^1.7.0",
"ng2-cookies": "^0.1.5",
"node-iptc": "^1.0.4",
"optimist": "^0.6.1",
"rxjs": "5.0.0-beta.6",
"ts-loader": "^0.8.2",

View File

@ -7,7 +7,6 @@
"debug": "github:DefinitelyTyped/DefinitelyTyped/debug/debug.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e",
"express": "github:DefinitelyTyped/DefinitelyTyped/express/express.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e",
"express-session": "registry:dt/express-session#0.0.0+20160331200931",
"image-size": "registry:dt/image-size#0.0.0+20160223165602",
"jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#d22516f9f089de107d7e7d5938566377370631f6",
"mime": "github:DefinitelyTyped/DefinitelyTyped/mime/mime.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e",
"mongoose": "registry:dt/mongoose#3.8.5+20160316155526",