🚨 Shai-Hulud Strikes Again:834 Packages Compromised.Technical Analysis →
Socket
Book a DemoInstallSign in
Socket

photo-info

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

photo-info

[![npm version](https://img.shields.io/npm/v/photo-info.svg?style=flat-square)](https://www.npmjs.com/package/photo-info) [![CI](https://github.com/tyom/photo-info/actions/workflows/ci.yaml/badge.svg)](https://github.com/tyom/photo-info/actions/workflows/

latest
Source
npmnpm
Version
0.4.1
Version published
Maintainers
1
Created
Source

Photo Info

npm version CI

This package provides a function to extract useful information from photos, such as geo location, camera make and model, focal length and angle of view, which could be useful to orient the photo on the map.

Demo App

Try the demo app with a few geotagged photos. All photos operations are done in the browser. No data is sent to any server.

Installation

npm install photo-info

Usage

Basic Usage

import { getPhotoInfo } from 'photo-info';

const photoInfo = await getPhotoInfo(file);
console.log(photoInfo);
// {
//   make: 'Apple',
//   model: 'iPhone 15 Pro',
//   angleOfView: 23.5,
//   effectiveAngleOfView: 23.5,
//   bearing: 45.2,
//   gpsPosition: [51.5074, -0.1276, 10.5],
//   gpsAccuracy: {
//     error: 5,
//     grade: 'A',
//     description: 'Excellent - High confidence GPS fix'
//   },
//   gpsSpeed: { value: 5.4, unit: 'km/h' },
//   focalLength: 6.86,
//   focalLengthIn35mm: 48,
//   width: 4032,
//   height: 3024,
//   orientation: 'landscape',
//   frontCamera: false,
//   dateTime: '2024-03-15T14:30:00',
//   exposureTime: '1/120',
//   exposureProgram: 'Normal program',
//   fNumber: 'f/1.8',
//   lens: 'iPhone 15 Pro back camera 6.86mm f/1.78'
// }

Including Original EXIF Tags

const { originalTags, ...photoInfo } = await getPhotoInfo(file, true);

API Reference

getPhotoInfo(file: File, includeOriginalTags?: boolean): Promise<PhotoInfo>

Extracts photo information from an image file containing EXIF data.

Parameters

  • file - A File object (typically from an input element or drag-and-drop)
  • includeOriginalTags - Optional. When true, includes the raw EXIF data in the response

Returns

A PhotoInfo object with the following properties:

PropertyTypeDescription
makestring | nullCamera manufacturer (e.g., "Canon", "Apple")
modelstring | nullCamera model (e.g., "iPhone 15 Pro")
angleOfViewnumber | nullHorizontal angle of view in degrees
effectiveAngleOfViewnumber | nullEffective FOV for map display (considers orientation)
bearingnumber | nullCompass direction the camera was facing (0-360°)
gpsPosition[lat, lng, alt?] | nullGPS coordinates: latitude, longitude, altitude (meters)
gpsAccuracy{error, grade, description} | nullGPS accuracy with error (meters), grade (A-F), and text description
gpsSpeed{value, unit} | nullSpeed at capture time with unit (typically "km/h")
focalLengthnumber | nullActual focal length in millimeters
focalLengthIn35mmnumber | null35mm equivalent focal length
widthnumberImage width in pixels
heightnumberImage height in pixels
orientation'portrait' | 'landscape' | 'square'Image orientation
frontCamerabooleanWhether taken with front-facing camera
dateTimestring | nullISO 8601 formatted capture time
exposureTimestring | nullShutter speed (e.g., "1/120")
exposureProgramstring | nullCamera exposure mode
fNumberstring | nullAperture value (e.g., "f/1.8")
lensstring | nullLens model/description
originalTagsobject | undefinedRaw EXIF data (when requested)

getMappedPhotoInfo(file: File): Promise<MappedExifData>

Get photo information with user-friendly mapped EXIF data.

Returns

A mapped object where each EXIF tag has:

  • value - The raw EXIF value
  • displayName - Human-readable property name
  • formattedValue - Formatted value for display
const mappedData = await getMappedPhotoInfo(file);
console.log(mappedData.ISO);
// {
//   value: 100,
//   displayName: 'ISO Speed',
//   formattedValue: 'ISO 100'
// }

getGroupedPhotoInfo(file: File): Promise<GroupedExifData>

Get photo EXIF data organized by categories.

Returns

EXIF data grouped into categories:

  • Camera - Make, model, lens info
  • GPS - Location, altitude, speed
  • Image - Dimensions, orientation, compression
  • Capture - Date, time, settings
  • Other - Additional metadata
const grouped = await getGroupedPhotoInfo(file);
console.log(grouped.Camera);
// { Make: 'Canon', Model: 'EOS R5', ... }
console.log(grouped.GPS);
// { GPSLatitude: 51.5074, GPSLongitude: -0.1276, ... }

getComprehensivePhotoInfo(file: File): Promise<...>

Get all photo information formats in a single call.

Returns

An object containing:

  • original - Standard PhotoInfo with all fields
  • mapped - User-friendly mapped EXIF data
  • grouped - EXIF data organized by categories
const comprehensive = await getComprehensivePhotoInfo(file);
console.log(comprehensive.original); // PhotoInfo object
console.log(comprehensive.mapped); // MappedExifData
console.log(comprehensive.grouped); // GroupedExifData

createFovMarkerSvg(options: MarkerOptions): string

Creates an SVG string for visualizing photo field-of-view on maps.

import { createFovMarkerSvg } from 'photo-info';

const svgString = createFovMarkerSvg({
  angleOfView: 65,
  bearing: 180,
  circleColor: 'red',
  fovColor: 'rgba(255, 0, 0, 0.3)',
});

// Use with Leaflet, Mapbox, or other mapping libraries

Options

  • angleOfView - Field of view angle in degrees
  • bearing - Direction in degrees (0-360)
  • viewBoxSize - SVG viewbox size (default: 200)
  • circleSize - Center marker size (default: 5)
  • circleColor - Center marker color (default: 'orange')
  • fovColor - Field of view wedge color (default: 'lightblue')

Error Handling

The library gracefully handles missing or invalid EXIF data:

try {
  const info = await getPhotoInfo(file);

  // Properties will be null when data is unavailable
  if (info.gpsPosition) {
    console.log('Photo has GPS coordinates');
  }

  // Core properties like width/height default to 0 if unavailable
  if (info.width === 0) {
    console.log('Could not determine image dimensions');
  }
} catch (error) {
  // File reading errors will throw
  console.error('Failed to read file:', error);
}

Utility Functions

The library also exports various utility functions for advanced use:

Camera & Lens Calculations

import {
  calculateAngleOfView,
  calculateAnglesOfView,
  calculateSensorSize,
  calculate35mmEquivalentFocalLength,
  calculateCropFactor,
} from 'photo-info';

// Calculate field of view angles
const { horizontal, vertical } = calculateAnglesOfView(
  24, // focal length in mm
  50, // 35mm equivalent
  '3:2', // aspect ratio
);

// Calculate sensor dimensions
const sensorSize = calculateSensorSize(5.6, '4:3'); // crop factor and aspect ratio

// Calculate 35mm equivalent focal length
const equiv = calculate35mmEquivalentFocalLength(24, 1.5); // focal length and crop factor

Practical Examples

Display photos on a map with GPS accuracy

const photos = await Promise.all(
  files.map(async (file) => ({
    file,
    info: await getPhotoInfo(file),
  })),
);

// Filter photos with GPS data
const geotaggedPhotos = photos.filter((p) => p.info.gpsPosition);

// Add markers to your map
geotaggedPhotos.forEach(({ info }) => {
  const [lat, lng] = info.gpsPosition;

  // Create marker with field-of-view indicator
  const marker = L.marker([lat, lng]);

  // Show GPS accuracy if available
  if (info.gpsAccuracy) {
    const { error, grade, description } = info.gpsAccuracy;
    marker.bindPopup(`
      GPS Accuracy: ${description}
      Error: ±${error}m (Grade ${grade})
    `);
  }

  if (info.effectiveAngleOfView && info.bearing) {
    // Use effectiveAngleOfView for correct orientation handling
    const svg = createFovMarkerSvg({
      angleOfView: info.effectiveAngleOfView,
      bearing: info.bearing,
    });
    // Add SVG overlay to map
  }
});

Extract camera settings

const info = await getPhotoInfo(file);

if (info.fNumber && info.exposureTime && info.focalLength) {
  console.log(
    `Shot at ${info.fNumber}, ${info.exposureTime}s, ${info.focalLength}mm`,
  );

  if (info.focalLengthIn35mm) {
    console.log(`35mm equivalent: ${info.focalLengthIn35mm}mm`);
  }
}

Working with different data formats

// Get comprehensive data in one call
const { original, mapped, grouped } = await getComprehensivePhotoInfo(file);

// Access camera info from grouped data
console.log('Camera:', grouped.Camera);

// Get user-friendly display values
for (const [tag, data] of Object.entries(mapped)) {
  console.log(`${data.displayName}: ${data.formattedValue}`);
}

Browser Compatibility

This library requires:

  • Modern browser with File API support
  • async/await support (or transpilation)
  • Works with JPEG, TIFF, PNG, HEIC, and WebP files containing EXIF data

Keywords

typescript

FAQs

Package last updated on 14 Sep 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts