Skip to content

Commit

Permalink
refactor: Extract ExifReader from ExifRenderer.
Browse files Browse the repository at this point in the history
  • Loading branch information
mrseanryan committed Jan 6, 2019
1 parent 66799e8 commit 0741ad6
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 103 deletions.
4 changes: 2 additions & 2 deletions src/electronApp/rendering/DetailPaneRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ImageDetail } from "../../bars/model/ImageDetail";
import { JQueryUtils } from "../../utils/JQueryUtils";
import { MathUtils } from "../../utils/MathUtils";
import { IOutputter } from "../../utils/outputter/IOutputter";
import { ExifRenderer } from "./ExifRenderer";
import { ExifRenderer } from "./exif/ExifRenderer";
import { HistogramRenderer } from "./HistogramRenderer";
import { LoaderRenderer } from "./LoaderRenderer";

Expand Down Expand Up @@ -48,7 +48,7 @@ export namespace DetailPaneRenderer {
`<div>file size: ${MathUtils.roundToFewPlaces(image.fileSizeInMb)} Mb</div>` +
`<div id="image-exif" class="exifContainer"></div>`;

ExifRenderer.getHtmlForImage(image, "image-exif");
ExifRenderer.renderHtmlForImage(image, "image-exif");

jquery("#image-text").append(html);
}
Expand Down
101 changes: 0 additions & 101 deletions src/electronApp/rendering/ExifRenderer.ts

This file was deleted.

12 changes: 12 additions & 0 deletions src/electronApp/rendering/exif/ExifOrientation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// ref: https://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/
// note: rotating *clockwise*
export enum ExifOrientation {
Normal = 0,
Rotated90 = 8,
Rotated180 = 3,
Rotated270 = 6,
ReflectedVerticalAxis = 2,
Rotated90AndReflectedHorizontalAxis = 7,
Rotated180AndReflectedVerticalAxis = 4,
Rotated270AndReflectedHorizontalAxis = 5
}
46 changes: 46 additions & 0 deletions src/electronApp/rendering/exif/ExifReader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as fs from "fs";
import * as path from "path";

import { ImageDetail } from "../../../bars/model/ImageDetail";
import { ExifTagSet } from "./ExifTagSet";

const jpegDecoder = require("jpg-stream/decoder");

export namespace ExifReader {
export async function getExifTagsForImageAsync(
image: ImageDetail
): Promise<ExifTagSet[] | null> {
if (!hasFileExif(image.originalFilepath)) {
return null;
}

return new Promise<ExifTagSet[]>((resolve, reject) => {
// decode a JPEG file to RGB pixels
fs.createReadStream(image.originalFilepath)
.pipe(new jpegDecoder({ width: 600, height: 400 }))
.on("meta", (meta: any) => {
// meta contains an exif object as decoded by
// https://github.com/devongovett/exif-reader

resolve(parseExif(meta));
});
});
}

function hasFileExif(filepath: string): boolean {
const extension = path.extname(filepath).toLowerCase();

// currently we are decoding only JPEG files.
// note: some PNG files can have some EXIF data but it's not yet standard.

return [".jpg", ".jpeg"].includes(extension);
}

function parseExif(meta: any): ExifTagSet[] {
return [
ExifTagSet.fromTags(meta.exif, "Image"),
ExifTagSet.fromTags(meta.image, "Device"),
ExifTagSet.fromTags(meta.gps, "GPS")
].filter(e => !!e) as ExifTagSet[];
}
}
45 changes: 45 additions & 0 deletions src/electronApp/rendering/exif/ExifRenderer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as jquery from "jquery";

import { ImageDetail } from "../../../bars/model/ImageDetail";
import { ExifReader } from "./ExifReader";
import { ExifTagSet } from "./ExifTagSet";

export namespace ExifRenderer {
export async function renderHtmlForImage(image: ImageDetail, divId: string) {
const html = await getHtmlForImageAsync(image);

jquery("#" + divId).append(html);
}

async function getHtmlForImageAsync(image: ImageDetail): Promise<string> {
const tagSets = await ExifReader.getExifTagsForImageAsync(image);
if (!tagSets) {
return "";
}

let html = "<pre>";

html += tagSets.map(set => renderTagSet(set)).join("\n");

html += "</pre>";

return html;
}

function renderTagSet(tagSet: ExifTagSet): string {
let sectionHtml = "";

tagSet.map.forEach((value, key) => {
if (value !== null && value !== undefined) {
const valueAsText = value.toString();
sectionHtml += valueAsText.length > 0 ? `${key}: ${valueAsText}\n` : "";
}
});

if (sectionHtml.length > 0) {
return `--- ${tagSet.title} ---\n` + sectionHtml;
}

return "";
}
}
56 changes: 56 additions & 0 deletions src/electronApp/rendering/exif/ExifTagSet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
export class ExifTagSet {
static fromTags(tags: any, name: string): ExifTagSet | null {
if (!tags) {
return null;
}

const interestingTags = Object.keys(ExifTag);

const tagSet = new ExifTagSet(name);

interestingTags.forEach(tag => {
const value = tags[tag] ? tags[tag] : null;

if (value) {
tagSet.map.set(tag as ExifTag, value);
}
});

return tagSet;
}

readonly map = new Map<ExifTag, string>();

constructor(readonly title: string) {}

get(tag: ExifTag): string | null {
if (!this.map.has(tag)) {
return null;
}

return this.map.get(tag)!;
}
}

enum ExifTag {
// 'exif'
ApertureValue = "ApertureValue",
BrightnessValue = "BrightnessValue",
FNumber = "FNumber",
Flash = "Flash",
FocalLength = "FocalLength",
ISO = "ISO",
// 'gps'
GPSAltitude = "GPSAltitude",
GPSAltitudeRef = "GPSAltitudeRef",
GPSLatitude = "GPSLatitude",
GPSLatitudeRef = "GPSLatitudeRef",
// 'image'
ModifyDate = "ModifyDate",
Orientation = "Orientation",
Software = "Software",
XResolution = "XResolution",
YResolution = "YResolution",
Make = "Make",
Model = "Model"
}

0 comments on commit 0741ad6

Please sign in to comment.