78 lines
2.2 KiB
TypeScript
78 lines
2.2 KiB
TypeScript
import { OrientationTypes, type ExifData } from 'ts-exif-parser';
|
|
import { formatNumberToFraction, roundToString } from './number';
|
|
import * as PiExif from 'piexifjs';
|
|
|
|
const OFFSET_REGEX = /[+-]\d\d:\d\d/;
|
|
|
|
export const getOffsetFromExif = (data: ExifData) =>
|
|
Object.values(data.tags as any)
|
|
.find((value: any) =>
|
|
typeof value === 'string' &&
|
|
OFFSET_REGEX.test(value)
|
|
) as string | undefined;
|
|
|
|
export const getAspectRatioFromExif = (data: ExifData): number => {
|
|
// Using '||' operator to handle `Orientation` unexpectedly being '0'
|
|
const orientation = data.tags?.Orientation || OrientationTypes.TOP_LEFT;
|
|
|
|
const width = data.imageSize?.width ?? 3.0;
|
|
const height = data.imageSize?.height ?? 2.0;
|
|
|
|
switch (orientation) {
|
|
case OrientationTypes.TOP_LEFT:
|
|
case OrientationTypes.TOP_RIGHT:
|
|
case OrientationTypes.BOTTOM_RIGHT:
|
|
case OrientationTypes.BOTTOM_LEFT:
|
|
case OrientationTypes.LEFT_TOP:
|
|
case OrientationTypes.RIGHT_BOTTOM:
|
|
return width / height;
|
|
case OrientationTypes.RIGHT_TOP:
|
|
case OrientationTypes.LEFT_BOTTOM:
|
|
return height / width;
|
|
}
|
|
};
|
|
|
|
export const formatAperture = (aperture?: number) =>
|
|
aperture
|
|
? `ƒ/${roundToString(aperture)}`
|
|
: undefined;
|
|
|
|
export const formatIso = (iso?: number) =>
|
|
iso ? `ISO ${iso.toLocaleString()}` : undefined;
|
|
|
|
export const formatExposureTime = (exposureTime = 0) =>
|
|
exposureTime > 0
|
|
? exposureTime < 1
|
|
? `1/${Math.floor(1 / exposureTime)}s`
|
|
: `${exposureTime}s`
|
|
: undefined;
|
|
|
|
export const formatExposureCompensation = (exposureCompensation?: number) => {
|
|
if (
|
|
exposureCompensation &&
|
|
Math.abs(exposureCompensation) > 0.01
|
|
) {
|
|
return `${formatNumberToFraction(exposureCompensation)}ev`;
|
|
} else {
|
|
return undefined;
|
|
}
|
|
};
|
|
|
|
export const removeGpsFromFile = async (
|
|
fileBytes: ArrayBuffer
|
|
): Promise<Blob> => {
|
|
const base64 = Buffer.from(fileBytes).toString('base64');
|
|
const base64Url = `data:image/jpeg;base64,${base64}`;
|
|
|
|
const exifObject = PiExif.load(base64Url) as Record<string, any>;
|
|
delete exifObject.GPS;
|
|
const exifDataWithoutGps = PiExif.dump(exifObject);
|
|
|
|
const data = PiExif.insert(
|
|
exifDataWithoutGps,
|
|
base64Url,
|
|
);
|
|
|
|
return fetch(data, { cache: 'no-store' }).then(res => res.blob());
|
|
};
|