Skip to content

Commit 0406fa3

Browse files
committed
Basic JPEG file extract
1 parent c2180f6 commit 0406fa3

File tree

1 file changed

+68
-37
lines changed

1 file changed

+68
-37
lines changed

PythonFileFormats/JPEG.py

Lines changed: 68 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,12 @@ def processExifSegment(info, segment) :
127127
continueLooking = True
128128
while(continueLooking) :
129129
newIFDinfo = []
130-
for knownIFDname, d in dict.items() :
130+
for d in dict.values() :
131131
for embeddedIFDtag, embeddedIFDname in knownEmbeddedIFDs().items() :
132132
# This will re-search all IFDs each time through the loop, not just ones we've added last time
133133
# around, so ignore embedded IFDs we've already picked up. (Assuming the only exist in one place.)
134134
if embeddedIFDtag in d and embeddedIFDname not in dict:
135135
IFDname = embeddedIFDname
136-
#print("Handling embedded IFD:", IFDname)
137136
embeddedIFDOffset = d[embeddedIFDtag]['value']
138137
embeddedIFDentries, nextIFDOffset = processIFD(TIFF, embeddedIFDOffset, byteAlignmentIndicator)
139138
# Put info about embedded IFD onto a list, we can't put it directly in the main dictionary
@@ -475,9 +474,10 @@ def latLongAsStringNumber(NSEW, latLongTuples) :
475474
n = (degrees + (minutes / 60.0) + (seconds / 60.0 / 60.0) ) * multiplier
476475
return (s,n)
477476

478-
def summariseTags(allTags) :
477+
def summariseTags(propertiesDict, allTags, verbose) :
479478

480-
print()
479+
if verbose :
480+
print()
481481

482482
# Where was the image (photo) produced ?
483483
if 'GPS' in allTags :
@@ -507,19 +507,25 @@ def summariseTags(allTags) :
507507

508508
if NS and latitude and EW and longitude :
509509
sLatitude, nLatitude = latLongAsStringNumber(NS, latitude)
510-
print("Latitude:", sLatitude, " = ", nLatitude)
511510
sLongitude, nLongitude = latLongAsStringNumber(EW, longitude)
512-
print("Longitude:", sLongitude, " = ", nLongitude)
513511
zoomLevel = 16
514-
print("OSMaps Link:", "https://osmaps.ordnancesurvey.co.uk/{0:f}%2C{1:f}%2C{2:d}".format(nLatitude, nLongitude, zoomLevel)) # No Pn
515-
# Google Maps URL API doesn't seem to allow a Pin to be displayed at the lat/long coordinates at the same time as specifying a zoom and a map type
516-
print("Google Link:", "https://www.google.com/maps/%40?api=1&map_action=map&center={0:f}%2C{1:f}&zoom={2:d}&basemap=satellite".format(nLatitude, nLongitude, zoomLevel)) # No pin
517-
print("Google Link with Pin:", "https://www.google.com/maps/search/?api=1&query={0:f}%2C{1:f}&zoom=10".format(nLatitude, nLongitude)) # Pin
512+
propertiesDict['latitude'] = nLatitude
513+
propertiesDict['longitude'] = nLongitude
514+
propertiesDict['fromGPS'] = fromGPS
515+
if verbose :
516+
print("Latitude:", sLatitude, " = ", nLatitude)
517+
print("Longitude:", sLongitude, " = ", nLongitude)
518+
print("OSMaps Link:", "https://osmaps.ordnancesurvey.co.uk/{0:f}%2C{1:f}%2C{2:d}".format(nLatitude, nLongitude, zoomLevel)) # No Pn
519+
# Google Maps URL API doesn't seem to allow a Pin to be displayed at the lat/long coordinates at the same time as specifying a zoom and a map type
520+
print("Google Link:", "https://www.google.com/maps/%40?api=1&map_action=map&center={0:f}%2C{1:f}&zoom={2:d}&basemap=satellite".format(nLatitude, nLongitude, zoomLevel)) # No pin
521+
print("Google Link with Pin:", "https://www.google.com/maps/search/?api=1&query={0:f}%2C{1:f}&zoom=10".format(nLatitude, nLongitude)) # Pin
518522

519523
if fromGPS and 6 in GPSTags :
520524
altitudeTuple = GPSTags[6]['value']
521-
altitude = altitudeTuple[0]/altitudeTuple[1]
522-
print("Rough Altitude:", "{0:.0f} m".format(round(altitude, -2)))
525+
altitude = round(altitudeTuple[0]/altitudeTuple[1], -2)
526+
if verbose :
527+
print("Rough Altitude:", "{0:.0f} m".format(altitude))
528+
propertiesDict['altitude'] = altitude
523529

524530
# for k,d in GPSTags.items() :
525531
# print(k, d)
@@ -532,12 +538,23 @@ def summariseTags(allTags) :
532538
if 306 in IFD0Tags :
533539
timestamp = IFD0Tags[306]['value']
534540
if timestamp[0:4] != "0000" :
535-
print("Timestamp:", IFD0Tags[306]['value'], "GMT")
541+
if verbose :
542+
print("Timestamp:", IFD0Tags[306]['value'], "GMT")
543+
propertiesDict['timestamp'] = timestamp
536544

537545
if 256 in IFD0Tags and 257 in IFD0Tags :
538-
print("Size:", IFD0Tags[256]['value'], " x ", IFD0Tags[257]['value'], "pixels")
546+
columns = IFD0Tags[256]['value']
547+
rows = IFD0Tags[257]['value']
548+
if verbose:
549+
print("Size:", columns, " x ", rows, "pixels")
550+
propertiesDict['columns'] = columns
551+
propertiesDict['rows'] = rows
552+
539553
if 271 in IFD0Tags :
540-
print("Make:", IFD0Tags[271]['value'])
554+
make = IFD0Tags[271]['value']
555+
if verbose :
556+
print("Make:", make)
557+
propertiesDict['make'] = make
541558

542559
# IFD1 = thumbnail
543560
# 256, 257, 259, 274, 282, 283, 296, 512, 514
@@ -558,9 +575,10 @@ def summariseTags(allTags) :
558575
###########################################################################
559576
##
560577

561-
def processFile(filename) :
578+
def processFile(filename, verbose=True) :
562579

563-
print("Reading from:", filename)
580+
if verbose :
581+
print("Reading from:", filename)
564582

565583
bytecount = 0
566584
aborted = False
@@ -672,19 +690,20 @@ def processFile(filename) :
672690
bytecount += len(trailingBytes)
673691

674692
# Summarise what we've found
675-
for s in segmentsInfo :
676-
print(s)
693+
if verbose :
694+
for s in segmentsInfo :
695+
print(s)
677696

678-
if EOIFound and trailingBytes :
679-
print("Found", len(trailingBytes), "unknown bytes after EOI marker:", *trailingBytes[0:10], "...")
697+
if EOIFound and trailingBytes :
698+
print("Found", len(trailingBytes), "unknown bytes after EOI marker:", *trailingBytes[0:10], "...")
680699

681700
if not (SOIFound and EOIFound) :
682-
print("*** Start/End of Image character(s) not found")
701+
print("*** Start/End of Image character(s) not found in file:", filename)
683702

684-
if not aborted :
703+
if aborted :
704+
print("*** Aborted read of file:", filename)
705+
elif verbose :
685706
print("Read all bytes:", bytecount, "bytes")
686-
else :
687-
print("*** Aborted read")
688707

689708
allTags = {}
690709

@@ -694,32 +713,44 @@ def processFile(filename) :
694713
appName = info['app']
695714
if appName == "Exif" :
696715
Exifdict = processExifSegment(info, data)
697-
print("Extracted these IFDs from the Exif segment:")
716+
if verbose :
717+
print("Extracted these IFDs from the Exif segment:")
698718
for n, d in Exifdict.items() :
699-
print("- ", n, ":", len(d), "item(s)")
719+
if verbose :
720+
print("- ", n, ":", len(d), "item(s)")
700721
allTags[n] = d
701722
elif appName == "JFIF" :
702723
JFIFdict = processJFIFSegment(info, data)
703-
print("Extracted JFIF segment data:", len(JFIFdict), "item(s)")
724+
if verbose :
725+
print("Extracted JFIF segment data:", len(JFIFdict), "item(s)")
704726
allTags['JFIF'] = JFIFdict
705727
elif appName == "ICC_PROFILE" :
706728
ICCdict = processICCProfileSegment(info, data)
707-
print("Extracted ICC Profile segment data:", len(ICCdict), "item(s)")
729+
if verbose :
730+
print("Extracted ICC Profile segment data:", len(ICCdict), "item(s)")
708731
allTags['ICC'] = ICCdict
709732
else :
710-
print("Not examining", appName, " data segment")
733+
if verbose :
734+
print("Not examining", appName, " data segment")
711735

736+
propertiesDict = {}
737+
propertiesDict['filename'] = filename
738+
propertiesDict['bytes'] = bytecount
739+
#propertiesDict['segments'] = segmentsInfo
740+
summariseTags(propertiesDict, allTags, verbose)
712741

713-
summariseTags(allTags)
714-
742+
return propertiesDict
715743
#
716744
####################################
717745
#
718746

719-
if len(sys.argv) == 1 :
720-
print("No filename command line argument provided")
721-
exit()
747+
if __name__ == "__main__" :
748+
749+
if len(sys.argv) == 1 :
750+
print("No filename command line argument provided")
751+
exit()
722752

723-
filename = sys.argv[1]
724-
processFile(filename)
753+
filename = sys.argv[1]
754+
mainProperties = processFile(filename, True)
725755

756+
# print(mainProperties)

0 commit comments

Comments
 (0)