Format code with Black

This commit is contained in:
Michał Gdula 2023-04-07 12:35:30 +00:00
parent fef8a557d2
commit 128464d43f
18 changed files with 697 additions and 604 deletions

View file

@ -16,7 +16,10 @@ def contrast(background, light, dark, threshold=0.179):
# Calculate contrast
uicolors = [red / 255, green / 255, blue / 255]
cont = [col / 12.92 if col <= 0.03928 else ((col + 0.055) / 1.055) ** 2.4 for col in uicolors]
cont = [
col / 12.92 if col <= 0.03928 else ((col + 0.055) / 1.055) ** 2.4
for col in uicolors
]
lightness = (0.2126 * cont[0]) + (0.7152 * cont[1]) + (0.0722 * cont[2])
return light if lightness > threshold else dark

View file

@ -8,8 +8,8 @@ from PIL import Image, ImageOps
from werkzeug.utils import secure_filename
CACHE_PATH = platformdirs.user_config_dir('onlylegs') + '/cache'
UPLOAD_PATH = platformdirs.user_config_dir('onlylegs') + '/uploads'
CACHE_PATH = os.path.join(platformdirs.user_config_dir("onlylegs"), "cache")
UPLOAD_PATH = os.path.join(platformdirs.user_config_dir("onlylegs"), "uploads")
def generate_thumbnail(file_name, resolution, ext=None):
@ -25,34 +25,34 @@ def generate_thumbnail(file_name, resolution, ext=None):
os.makedirs(CACHE_PATH)
# no sussy business
file_name, file_ext = secure_filename(file_name).rsplit('.')
file_name, file_ext = secure_filename(file_name).rsplit(".")
if not ext:
ext = file_ext.strip('.')
ext = file_ext.strip(".")
# PIL doesnt like jpg so we convert it to jpeg
if ext.lower() == "jpg":
ext = "jpeg"
# Set resolution based on preset resolutions
if resolution in ['prev', 'preview']:
if resolution in ["prev", "preview"]:
res_x, res_y = (1920, 1080)
elif resolution in ['thumb', 'thumbnail']:
elif resolution in ["thumb", "thumbnail"]:
res_x, res_y = (400, 400)
elif resolution in ['icon', 'favicon']:
elif resolution in ["icon", "favicon"]:
res_x, res_y = (10, 10)
else:
return None
# If image has been already generated, return it from the cache
if os.path.exists(os.path.join(CACHE_PATH, f'{file_name}_{res_x}x{res_y}.{ext}')):
return os.path.join(CACHE_PATH, f'{file_name}_{res_x}x{res_y}.{ext}')
if os.path.exists(os.path.join(CACHE_PATH, f"{file_name}_{res_x}x{res_y}.{ext}")):
return os.path.join(CACHE_PATH, f"{file_name}_{res_x}x{res_y}.{ext}")
# Check if image exists in the uploads directory
if not os.path.exists(os.path.join(UPLOAD_PATH, f'{file_name}.{file_ext}')):
if not os.path.exists(os.path.join(UPLOAD_PATH, f"{file_name}.{file_ext}")):
return None
# Open image and rotate it based on EXIF data and get ICC profile so colors are correct
image = Image.open(os.path.join(UPLOAD_PATH, f'{file_name}.{file_ext}'))
image = Image.open(os.path.join(UPLOAD_PATH, f"{file_name}.{file_ext}"))
image_icc = image.info.get("icc_profile")
img_x, img_y = image.size
@ -62,16 +62,20 @@ def generate_thumbnail(file_name, resolution, ext=None):
# Save image to cache directory
try:
image.save(os.path.join(CACHE_PATH, f'{file_name}_{res_x}x{res_y}.{ext}'),
icc_profile=image_icc)
image.save(
os.path.join(CACHE_PATH, f"{file_name}_{res_x}x{res_y}.{ext}"),
icc_profile=image_icc,
)
except OSError:
# This usually happens when saving a JPEG with an ICC profile,
# so we convert to RGB and try again
image = image.convert('RGB')
image.save(os.path.join(CACHE_PATH, f'{file_name}_{res_x}x{res_y}.{ext}'),
icc_profile=image_icc)
image = image.convert("RGB")
image.save(
os.path.join(CACHE_PATH, f"{file_name}_{res_x}x{res_y}.{ext}"),
icc_profile=image_icc,
)
# No need to keep the image in memory, learned the hard way
image.close()
return os.path.join(CACHE_PATH, f'{file_name}_{res_x}x{res_y}.{ext}')
return os.path.join(CACHE_PATH, f"{file_name}_{res_x}x{res_y}.{ext}")

View file

@ -16,6 +16,7 @@ class Metadata:
"""
Metadata parser
"""
def __init__(self, file_path):
"""
Initialize the metadata parser
@ -32,17 +33,17 @@ class Metadata:
if tag in tags:
img_exif[value] = tags[tag]
img_exif['FileName'] = os.path.basename(file_path)
img_exif['FileSize'] = os.path.getsize(file_path)
img_exif['FileFormat'] = img_exif['FileName'].split('.')[-1]
img_exif['FileWidth'], img_exif['FileHeight'] = file.size
img_exif["FileName"] = os.path.basename(file_path)
img_exif["FileSize"] = os.path.getsize(file_path)
img_exif["FileFormat"] = img_exif["FileName"].split(".")[-1]
img_exif["FileWidth"], img_exif["FileHeight"] = file.size
file.close()
except TypeError:
img_exif['FileName'] = os.path.basename(file_path)
img_exif['FileSize'] = os.path.getsize(file_path)
img_exif['FileFormat'] = img_exif['FileName'].split('.')[-1]
img_exif['FileWidth'], img_exif['FileHeight'] = file.size
img_exif["FileName"] = os.path.basename(file_path)
img_exif["FileSize"] = os.path.getsize(file_path)
img_exif["FileFormat"] = img_exif["FileName"].split(".")[-1]
img_exif["FileWidth"], img_exif["FileHeight"] = file.size
self.encoded = img_exif
@ -60,10 +61,10 @@ class Metadata:
Formats the data into a dictionary
"""
exif = {
'Photographer': {},
'Camera': {},
'Software': {},
'File': {},
"Photographer": {},
"Camera": {},
"Software": {},
"File": {},
}
# Thanks chatGPT xP
@ -73,26 +74,29 @@ class Metadata:
if len(mapping_val[key]) == 2:
# the helper function works, so not sure why it triggers pylint
exif[mapping_name][mapping_val[key][0]] = {
'raw': value,
'formatted': (
getattr(helpers, mapping_val[key][1]) # pylint: disable=E0602
(value)
),
"raw": value,
"formatted": (
getattr(
helpers, mapping_val[key][1]
)( # pylint: disable=E0602
value
)
),
}
else:
exif[mapping_name][mapping_val[key][0]] = {
'raw': value,
"raw": value,
}
continue
# Remove empty keys
if not exif['Photographer']:
del exif['Photographer']
if not exif['Camera']:
del exif['Camera']
if not exif['Software']:
del exif['Software']
if not exif['File']:
del exif['File']
if not exif["Photographer"]:
del exif["Photographer"]
if not exif["Camera"]:
del exif["Camera"]
if not exif["Software"]:
del exif["Software"]
if not exif["File"]:
del exif["File"]
return exif

View file

@ -21,28 +21,28 @@ def date_format(value):
"""
Formats the date into a standard format
"""
return str(datetime.strptime(value, '%Y:%m:%d %H:%M:%S'))
return str(datetime.strptime(value, "%Y:%m:%d %H:%M:%S"))
def fnumber(value):
"""
Formats the f-number into a standard format
"""
return 'ƒ/' + str(value)
return "ƒ/" + str(value)
def iso(value):
"""
Formats the ISO into a standard format
"""
return 'ISO ' + str(value)
return "ISO " + str(value)
def shutter(value):
"""
Formats the shutter speed into a standard format
"""
return str(value) + 's'
return str(value) + "s"
def focal_length(value):
@ -50,27 +50,23 @@ def focal_length(value):
Formats the focal length into a standard format
"""
try:
return str(value[0] / value[1]) + 'mm'
return str(value[0] / value[1]) + "mm"
except TypeError:
return str(value) + 'mm'
return str(value) + "mm"
def exposure(value):
"""
Formats the exposure value into a standard format
"""
return str(value) + 'EV'
return str(value) + "EV"
def color_space(value):
"""
Maps the value of the color space to a human readable format
"""
value_map = {
0: 'Reserved',
1: 'sRGB',
65535: 'Uncalibrated'
}
value_map = {0: "Reserved", 1: "sRGB", 65535: "Uncalibrated"}
try:
return value_map[int(value)]
except KeyError:
@ -82,28 +78,28 @@ def flash(value):
Maps the value of the flash to a human readable format
"""
value_map = {
0: 'Flash did not fire',
1: 'Flash fired',
5: 'Strobe return light not detected',
7: 'Strobe return light detected',
9: 'Flash fired, compulsory flash mode',
13: 'Flash fired, compulsory flash mode, return light not detected',
15: 'Flash fired, compulsory flash mode, return light detected',
16: 'Flash did not fire, compulsory flash mode',
24: 'Flash did not fire, auto mode',
25: 'Flash fired, auto mode',
29: 'Flash fired, auto mode, return light not detected',
31: 'Flash fired, auto mode, return light detected',
32: 'No flash function',
65: 'Flash fired, red-eye reduction mode',
69: 'Flash fired, red-eye reduction mode, return light not detected',
71: 'Flash fired, red-eye reduction mode, return light detected',
73: 'Flash fired, compulsory flash mode, red-eye reduction mode',
77: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected',
79: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected',
89: 'Flash fired, auto mode, red-eye reduction mode',
93: 'Flash fired, auto mode, return light not detected, red-eye reduction mode',
95: 'Flash fired, auto mode, return light detected, red-eye reduction mode'
0: "Flash did not fire",
1: "Flash fired",
5: "Strobe return light not detected",
7: "Strobe return light detected",
9: "Flash fired, compulsory flash mode",
13: "Flash fired, compulsory flash mode, return light not detected",
15: "Flash fired, compulsory flash mode, return light detected",
16: "Flash did not fire, compulsory flash mode",
24: "Flash did not fire, auto mode",
25: "Flash fired, auto mode",
29: "Flash fired, auto mode, return light not detected",
31: "Flash fired, auto mode, return light detected",
32: "No flash function",
65: "Flash fired, red-eye reduction mode",
69: "Flash fired, red-eye reduction mode, return light not detected",
71: "Flash fired, red-eye reduction mode, return light detected",
73: "Flash fired, compulsory flash mode, red-eye reduction mode",
77: "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",
79: "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",
89: "Flash fired, auto mode, red-eye reduction mode",
93: "Flash fired, auto mode, return light not detected, red-eye reduction mode",
95: "Flash fired, auto mode, return light detected, red-eye reduction mode",
}
try:
return value_map[int(value)]
@ -116,15 +112,15 @@ def exposure_program(value):
Maps the value of the exposure program to a human readable format
"""
value_map = {
0: 'Not defined',
1: 'Manual',
2: 'Normal program',
3: 'Aperture priority',
4: 'Shutter priority',
5: 'Creative program',
6: 'Action program',
7: 'Portrait mode',
8: 'Landscape mode'
0: "Not defined",
1: "Manual",
2: "Normal program",
3: "Aperture priority",
4: "Shutter priority",
5: "Creative program",
6: "Action program",
7: "Portrait mode",
8: "Landscape mode",
}
try:
return value_map[int(value)]
@ -137,14 +133,14 @@ def metering_mode(value):
Maps the value of the metering mode to a human readable format
"""
value_map = {
0: 'Unknown',
1: 'Average',
2: 'Center-Weighted Average',
3: 'Spot',
4: 'Multi-Spot',
5: 'Pattern',
6: 'Partial',
255: 'Other'
0: "Unknown",
1: "Average",
2: "Center-Weighted Average",
3: "Spot",
4: "Multi-Spot",
5: "Pattern",
6: "Partial",
255: "Other",
}
try:
return value_map[int(value)]
@ -156,11 +152,7 @@ def resolution_unit(value):
"""
Maps the value of the resolution unit to a human readable format
"""
value_map = {
1: 'No absolute unit of measurement',
2: 'Inch',
3: 'Centimeter'
}
value_map = {1: "No absolute unit of measurement", 2: "Inch", 3: "Centimeter"}
try:
return value_map[int(value)]
except KeyError:
@ -172,27 +164,27 @@ def light_source(value):
Maps the value of the light source to a human readable format
"""
value_map = {
0: 'Unknown',
1: 'Daylight',
2: 'Fluorescent',
3: 'Tungsten (incandescent light)',
4: 'Flash',
9: 'Fine weather',
10: 'Cloudy weather',
11: 'Shade',
12: 'Daylight fluorescent (D 5700 - 7100K)',
13: 'Day white fluorescent (N 4600 - 5400K)',
14: 'Cool white fluorescent (W 3900 - 4500K)',
15: 'White fluorescent (WW 3200 - 3700K)',
17: 'Standard light A',
18: 'Standard light B',
19: 'Standard light C',
20: 'D55',
21: 'D65',
22: 'D75',
23: 'D50',
24: 'ISO studio tungsten',
255: 'Other light source',
0: "Unknown",
1: "Daylight",
2: "Fluorescent",
3: "Tungsten (incandescent light)",
4: "Flash",
9: "Fine weather",
10: "Cloudy weather",
11: "Shade",
12: "Daylight fluorescent (D 5700 - 7100K)",
13: "Day white fluorescent (N 4600 - 5400K)",
14: "Cool white fluorescent (W 3900 - 4500K)",
15: "White fluorescent (WW 3200 - 3700K)",
17: "Standard light A",
18: "Standard light B",
19: "Standard light C",
20: "D55",
21: "D65",
22: "D75",
23: "D50",
24: "ISO studio tungsten",
255: "Other light source",
}
try:
return value_map[int(value)]
@ -205,10 +197,10 @@ def scene_capture_type(value):
Maps the value of the scene capture type to a human readable format
"""
value_map = {
0: 'Standard',
1: 'Landscape',
2: 'Portrait',
3: 'Night scene',
0: "Standard",
1: "Landscape",
2: "Portrait",
3: "Night scene",
}
try:
return value_map[int(value)]
@ -221,8 +213,8 @@ def white_balance(value):
Maps the value of the white balance to a human readable format
"""
value_map = {
0: 'Auto white balance',
1: 'Manual white balance',
0: "Auto white balance",
1: "Manual white balance",
}
try:
return value_map[int(value)]
@ -235,9 +227,9 @@ def exposure_mode(value):
Maps the value of the exposure mode to a human readable format
"""
value_map = {
0: 'Auto exposure',
1: 'Manual exposure',
2: 'Auto bracket',
0: "Auto exposure",
1: "Manual exposure",
2: "Auto bracket",
}
try:
return value_map[int(value)]
@ -250,22 +242,14 @@ def sensitivity_type(value):
Maps the value of the sensitivity type to a human readable format
"""
value_map = {
0:
'Unknown',
1:
'Standard Output Sensitivity',
2:
'Recommended Exposure Index',
3:
'ISO Speed',
4:
'Standard Output Sensitivity and Recommended Exposure Index',
5:
'Standard Output Sensitivity and ISO Speed',
6:
'Recommended Exposure Index and ISO Speed',
7:
'Standard Output Sensitivity, Recommended Exposure Index and ISO Speed',
0: "Unknown",
1: "Standard Output Sensitivity",
2: "Recommended Exposure Index",
3: "ISO Speed",
4: "Standard Output Sensitivity and Recommended Exposure Index",
5: "Standard Output Sensitivity and ISO Speed",
6: "Recommended Exposure Index and ISO Speed",
7: "Standard Output Sensitivity, Recommended Exposure Index and ISO Speed",
}
try:
return value_map[int(value)]
@ -278,7 +262,7 @@ def lens_specification(value):
Maps the value of the lens specification to a human readable format
"""
try:
return str(value[0] / value[1]) + 'mm - ' + str(value[2] / value[3]) + 'mm'
return str(value[0] / value[1]) + "mm - " + str(value[2] / value[3]) + "mm"
except TypeError:
return None
@ -288,55 +272,55 @@ def compression_type(value):
Maps the value of the compression type to a human readable format
"""
value_map = {
1: 'Uncompressed',
2: 'CCITT 1D',
3: 'T4/Group 3 Fax',
4: 'T6/Group 4 Fax',
5: 'LZW',
6: 'JPEG (old-style)',
7: 'JPEG',
8: 'Adobe Deflate',
9: 'JBIG B&W',
10: 'JBIG Color',
99: 'JPEG',
262: 'Kodak 262',
32766: 'Next',
32767: 'Sony ARW Compressed',
32769: 'Packed RAW',
32770: 'Samsung SRW Compressed',
32771: 'CCIRLEW',
32772: 'Samsung SRW Compressed 2',
32773: 'PackBits',
32809: 'Thunderscan',
32867: 'Kodak KDC Compressed',
32895: 'IT8CTPAD',
32896: 'IT8LW',
32897: 'IT8MP',
32898: 'IT8BL',
32908: 'PixarFilm',
32909: 'PixarLog',
32946: 'Deflate',
32947: 'DCS',
33003: 'Aperio JPEG 2000 YCbCr',
33005: 'Aperio JPEG 2000 RGB',
34661: 'JBIG',
34676: 'SGILog',
34677: 'SGILog24',
34712: 'JPEG 2000',
34713: 'Nikon NEF Compressed',
34715: 'JBIG2 TIFF FX',
34718: '(MDI) Binary Level Codec',
34719: '(MDI) Progressive Transform Codec',
34720: '(MDI) Vector',
34887: 'ESRI Lerc',
34892: 'Lossy JPEG',
34925: 'LZMA2',
34926: 'Zstd',
34927: 'WebP',
34933: 'PNG',
34934: 'JPEG XR',
65000: 'Kodak DCR Compressed',
65535: 'Pentax PEF Compressed',
1: "Uncompressed",
2: "CCITT 1D",
3: "T4/Group 3 Fax",
4: "T6/Group 4 Fax",
5: "LZW",
6: "JPEG (old-style)",
7: "JPEG",
8: "Adobe Deflate",
9: "JBIG B&W",
10: "JBIG Color",
99: "JPEG",
262: "Kodak 262",
32766: "Next",
32767: "Sony ARW Compressed",
32769: "Packed RAW",
32770: "Samsung SRW Compressed",
32771: "CCIRLEW",
32772: "Samsung SRW Compressed 2",
32773: "PackBits",
32809: "Thunderscan",
32867: "Kodak KDC Compressed",
32895: "IT8CTPAD",
32896: "IT8LW",
32897: "IT8MP",
32898: "IT8BL",
32908: "PixarFilm",
32909: "PixarLog",
32946: "Deflate",
32947: "DCS",
33003: "Aperio JPEG 2000 YCbCr",
33005: "Aperio JPEG 2000 RGB",
34661: "JBIG",
34676: "SGILog",
34677: "SGILog24",
34712: "JPEG 2000",
34713: "Nikon NEF Compressed",
34715: "JBIG2 TIFF FX",
34718: "(MDI) Binary Level Codec",
34719: "(MDI) Progressive Transform Codec",
34720: "(MDI) Vector",
34887: "ESRI Lerc",
34892: "Lossy JPEG",
34925: "LZMA2",
34926: "Zstd",
34927: "WebP",
34933: "PNG",
34934: "JPEG XR",
65000: "Kodak DCR Compressed",
65535: "Pentax PEF Compressed",
}
try:
return value_map[int(value)]
@ -349,15 +333,15 @@ def orientation(value):
Maps the value of the orientation to a human readable format
"""
value_map = {
0: 'Undefined',
1: 'Horizontal (normal)',
2: 'Mirror horizontal',
3: 'Rotate 180',
4: 'Mirror vertical',
5: 'Mirror horizontal and rotate 270 CW',
6: 'Rotate 90 CW',
7: 'Mirror horizontal and rotate 90 CW',
8: 'Rotate 270 CW',
0: "Undefined",
1: "Horizontal (normal)",
2: "Mirror horizontal",
3: "Rotate 180",
4: "Mirror vertical",
5: "Mirror horizontal and rotate 270 CW",
6: "Rotate 90 CW",
7: "Mirror horizontal and rotate 90 CW",
8: "Rotate 270 CW",
}
try:
return value_map[int(value)]
@ -370,16 +354,16 @@ def components_configuration(value):
Maps the value of the components configuration to a human readable format
"""
value_map = {
0: '',
1: 'Y',
2: 'Cb',
3: 'Cr',
4: 'R',
5: 'G',
6: 'B',
0: "",
1: "Y",
2: "Cb",
3: "Cr",
4: "R",
5: "G",
6: "B",
}
try:
return ''.join([value_map[int(x)] for x in value])
return "".join([value_map[int(x)] for x in value])
except KeyError:
return None
@ -388,18 +372,18 @@ def rating(value):
"""
Maps the value of the rating to a human readable format
"""
return str(value) + ' stars'
return str(value) + " stars"
def rating_percent(value):
"""
Maps the value of the rating to a human readable format
"""
return str(value) + '%'
return str(value) + "%"
def pixel_dimension(value):
"""
Maps the value of the pixel dimension to a human readable format
"""
return str(value) + 'px'
return str(value) + "px"

View file

@ -4,66 +4,66 @@ Mapping for metadata
"""
PHOTOGRAHER_MAPPING = {
'Artist': ['Artist'],
'UserComment': ['Comment'],
'ImageDescription': ['Description'],
'Copyright': ['Copyright'],
"Artist": ["Artist"],
"UserComment": ["Comment"],
"ImageDescription": ["Description"],
"Copyright": ["Copyright"],
}
CAMERA_MAPPING = {
'Model': ['Model'],
'Make': ['Make'],
'BodySerialNumber': ['Camera Type'],
'LensMake': ['Lens Make'],
'LenseModel': ['Lens Model'],
'LensSpecification': ['Lens Specification', 'lens_specification'],
'ComponentsConfiguration': ['Components Configuration', 'components_configuration'],
'DateTime': ['Date Processed', 'date_format'],
'DateTimeDigitized': ['Time Digitized', 'date_format'],
'OffsetTime': ['Time Offset'],
'OffsetTimeOriginal': ['Time Offset - Original'],
'OffsetTimeDigitized': ['Time Offset - Digitized'],
'DateTimeOriginal': ['Date Original', 'date_format'],
'FNumber': ['F-Stop', 'fnumber'],
'FocalLength': ['Focal Length', 'focal_length'],
'FocalLengthIn35mmFilm': ['Focal Length (35mm format)', 'focal_length'],
'MaxApertureValue': ['Max Aperture', 'fnumber'],
'ApertureValue': ['Aperture', 'fnumber'],
'ShutterSpeedValue': ['Shutter Speed', 'shutter'],
'ISOSpeedRatings': ['ISO Speed Ratings', 'iso'],
'ISOSpeed': ['ISO Speed', 'iso'],
'SensitivityType': ['Sensitivity Type', 'sensitivity_type'],
'ExposureBiasValue': ['Exposure Bias', 'exposure'],
'ExposureTime': ['Exposure Time', 'shutter'],
'ExposureMode': ['Exposure Mode', 'exposure_mode'],
'ExposureProgram': ['Exposure Program', 'exposure_program'],
'WhiteBalance': ['White Balance', 'white_balance'],
'Flash': ['Flash', 'flash'],
'MeteringMode': ['Metering Mode', 'metering_mode'],
'LightSource': ['Light Source', 'light_source'],
'SceneCaptureType': ['Scene Capture Type', 'scene_capture_type'],
"Model": ["Model"],
"Make": ["Make"],
"BodySerialNumber": ["Camera Type"],
"LensMake": ["Lens Make"],
"LenseModel": ["Lens Model"],
"LensSpecification": ["Lens Specification", "lens_specification"],
"ComponentsConfiguration": ["Components Configuration", "components_configuration"],
"DateTime": ["Date Processed", "date_format"],
"DateTimeDigitized": ["Time Digitized", "date_format"],
"OffsetTime": ["Time Offset"],
"OffsetTimeOriginal": ["Time Offset - Original"],
"OffsetTimeDigitized": ["Time Offset - Digitized"],
"DateTimeOriginal": ["Date Original", "date_format"],
"FNumber": ["F-Stop", "fnumber"],
"FocalLength": ["Focal Length", "focal_length"],
"FocalLengthIn35mmFilm": ["Focal Length (35mm format)", "focal_length"],
"MaxApertureValue": ["Max Aperture", "fnumber"],
"ApertureValue": ["Aperture", "fnumber"],
"ShutterSpeedValue": ["Shutter Speed", "shutter"],
"ISOSpeedRatings": ["ISO Speed Ratings", "iso"],
"ISOSpeed": ["ISO Speed", "iso"],
"SensitivityType": ["Sensitivity Type", "sensitivity_type"],
"ExposureBiasValue": ["Exposure Bias", "exposure"],
"ExposureTime": ["Exposure Time", "shutter"],
"ExposureMode": ["Exposure Mode", "exposure_mode"],
"ExposureProgram": ["Exposure Program", "exposure_program"],
"WhiteBalance": ["White Balance", "white_balance"],
"Flash": ["Flash", "flash"],
"MeteringMode": ["Metering Mode", "metering_mode"],
"LightSource": ["Light Source", "light_source"],
"SceneCaptureType": ["Scene Capture Type", "scene_capture_type"],
}
SOFTWARE_MAPPING = {
'Software': ['Software'],
'ColorSpace': ['Colour Space', 'color_space'],
'Compression': ['Compression', 'compression_type'],
"Software": ["Software"],
"ColorSpace": ["Colour Space", "color_space"],
"Compression": ["Compression", "compression_type"],
}
FILE_MAPPING = {
'FileName': ['Name'],
'FileSize': ['Size', 'human_size'],
'FileFormat': ['Format'],
'FileWidth': ['Width', 'pixel_dimension'],
'FileHeight': ['Height', 'pixel_dimension'],
'Orientation': ['Orientation', 'orientation'],
'XResolution': ['X-resolution'],
'YResolution': ['Y-resolution'],
'ResolutionUnit': ['Resolution Units', 'resolution_unit'],
'Rating': ['Rating', 'rating'],
'RatingPercent': ['Rating Percent', 'rating_percent'],
"FileName": ["Name"],
"FileSize": ["Size", "human_size"],
"FileFormat": ["Format"],
"FileWidth": ["Width", "pixel_dimension"],
"FileHeight": ["Height", "pixel_dimension"],
"Orientation": ["Orientation", "orientation"],
"XResolution": ["X-resolution"],
"YResolution": ["Y-resolution"],
"ResolutionUnit": ["Resolution Units", "resolution_unit"],
"Rating": ["Rating", "rating"],
"RatingPercent": ["Rating Percent", "rating_percent"],
}
EXIF_MAPPING = [
('Photographer', PHOTOGRAHER_MAPPING),
('Camera', CAMERA_MAPPING),
('Software', SOFTWARE_MAPPING),
('File', FILE_MAPPING)
("Photographer", PHOTOGRAHER_MAPPING),
("Camera", CAMERA_MAPPING),
("Software", SOFTWARE_MAPPING),
("File", FILE_MAPPING),
]