Skip to content

Commit

Permalink
explore exif
Browse files Browse the repository at this point in the history
  • Loading branch information
Erotemic committed Nov 2, 2024
1 parent 19e1379 commit 3869963
Showing 1 changed file with 93 additions and 0 deletions.
93 changes: 93 additions & 0 deletions shitspotter/util/util_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,96 @@ def extract_exif_metadata(fpath):
# TODO: get raw rationals?
exif['GPSInfo'] = ub.map_keys(GPSTAGS, exif['GPSInfo'])
return exif


def scrub_exif_metadata(fpath, new_fpath):
"""
Test that we can modify EXIF data (e.g. remove GPS or timestamp)
without modifying the image.
Example:
>>> # xdoctest: +REQUIRES(module:PIL)
>>> # xdoctest: +REQUIRES(module:piexif)
>>> from shitspotter.util.util_image import * # NOQA
>>> from shitspotter.util.util_image import * # NOQA
>>> fpath = _dummy_exif_image()
>>> new_fpath = fpath.augment(stemsuffix='scrubed')
>>> scrub_exif_metadata(fpath, new_fpath)
>>> import kwimage
>>> data1 = kwimage.imread(fpath)
>>> data2 = kwimage.imread(new_fpath)
>>> from kwimage.im_io import _imread_exif
>>> meta1 = _imread_exif(fpath)
>>> meta2 = _imread_exif(new_fpath)
>>> assert sum(len(v) for v in meta1.values() if v is not None) > 10
>>> assert sum(len(v) for v in meta2.values() if v is not None) == 0
>>> assert (data2 == data1).all()
Ignore:
ub.cmd(f'xxd {fpath} > b1.hex', shell=True)
ub.cmd(f'xxd {new_fpath} > b2.hex', shell=True)
_ = ub.cmd('diff -y b1.hex b2.hex', verbose=3, shell=1)
"""
import piexif
import os
new_exif = piexif.dump({})
raw_bytes = fpath.read_bytes()
# old_exif = piexif.load(raw_bytes)
piexif.insert(new_exif, raw_bytes, new_file=os.fspath(new_fpath))


def _dummy_exif_image():
import kwimage
from PIL import Image
import piexif
import ubelt as ub
dpath = ub.Path.appdir('shitspotter/tests/exif').ensuredir()
fpath = dpath / 'test_1.jpg'
# Create a basic EXIF dictionary with dummy camera data
# Reference: https://piexif.readthedocs.io/en/latest/functions.html#piexif.dump
raw_exif = {
"0th": {
piexif.ImageIFD.Make: b"FakeMake",
piexif.ImageIFD.Model: b"FakeModel",
piexif.ImageIFD.Software: b"FakeSoftware 1.0",
piexif.ImageIFD.ImageDescription: b"Sample image with dummy EXIF data",
piexif.ImageIFD.DateTime: b"2345:01:23 12:34:56", # YYYY:MM:DD HH:MM:SS format
},
"Exif": {
piexif.ExifIFD.ExposureTime: (1, 60), # Exposure time (1/60 second)
piexif.ExifIFD.FNumber: (28, 10), # F/2.8 aperture
piexif.ExifIFD.ISOSpeedRatings: 100, # ISO speed
piexif.ExifIFD.ShutterSpeedValue: (600, 100), # Shutter speed in APEX value
piexif.ExifIFD.ApertureValue: (280, 100), # Aperture in APEX value
piexif.ExifIFD.BrightnessValue: (5, 1), # Brightness level
piexif.ExifIFD.FocalLength: (50, 1), # Focal length (50mm)
piexif.ExifIFD.LensMake: b"FakeLensMake", # Lens manufacturer
piexif.ExifIFD.LensModel: b"FakeLensModel", # Lens model
},
"GPS": {
piexif.GPSIFD.GPSLatitudeRef: b"N",
piexif.GPSIFD.GPSLatitude: [(40, 1), (0, 1), (0, 1)], # 40°0'0" N
piexif.GPSIFD.GPSLongitudeRef: b"W",
piexif.GPSIFD.GPSLongitude: [(74, 1), (0, 1), (0, 1)], # 74°0'0" W
piexif.GPSIFD.GPSAltitudeRef: 0,
piexif.GPSIFD.GPSAltitude: (100, 1), # 100 meters above sea level
},
# Writing 1st doesnot seem to work with piexif, need to understand why
"1st": {},
"thumbnail": None,
#"1st": {
# piexif.ImageIFD.Make: "Canon",
# piexif.ImageIFD.XResolution: (40, 1),
# piexif.ImageIFD.YResolution: (40, 1),
# piexif.ImageIFD.Software: "piexif"
#},
#"thumbnail": None,
"Interop": {
piexif.InteropIFD.InteroperabilityIndex: b"R98", # Interoperability index
}
}
exif_bytes = piexif.dump(raw_exif)
imdata = kwimage.grab_test_image()
pil_img = Image.fromarray(imdata)
pil_img.save(fpath, exif=exif_bytes)
return fpath

0 comments on commit 3869963

Please sign in to comment.