metadata-scrubber-tool:
added the png_metadata processing functionalities, added an exception class to handle various error
This commit is contained in:
parent
ceb5ef6d55
commit
a517d774c2
Binary file not shown.
|
|
@ -7,12 +7,17 @@ from PIL import Image
|
|||
|
||||
from src.services.metadata_handler import MetadataHandler
|
||||
from src.utils.jpeg_metadata import JpegProcessaor
|
||||
from src.utils.png_metadata import PngProcessor
|
||||
|
||||
|
||||
class ImageHandler(MetadataHandler):
|
||||
def __init__(self, filepath: str):
|
||||
super().__init__(filepath)
|
||||
self.processors = {".jpeg": JpegProcessaor(), ".jpg": JpegProcessaor()}
|
||||
self.processors = {
|
||||
".jpeg": JpegProcessaor(),
|
||||
".jpg": JpegProcessaor(),
|
||||
".png": PngProcessor(),
|
||||
}
|
||||
self.tags_to_delete = []
|
||||
|
||||
def read(self):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
class MetadataException(Exception):
|
||||
"""Base class for other exceptions in this module."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class UnsupportedFormatError(MetadataException):
|
||||
"""Exception raised when an unsupported file format is encountered."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class MetadataNotFoundError(MetadataException):
|
||||
"""Exception raised when metadata is not found."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class MetadataProcessingError(MetadataException):
|
||||
"""Exception raised when an error occurs during metadata processing."""
|
||||
|
||||
pass
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
import piexif
|
||||
import piexif # pyright: ignore[reportMissingTypeStubs]
|
||||
|
||||
from src.utils.exceptions import MetadataNotFoundError, MetadataProcessingError
|
||||
|
||||
|
||||
class JpegProcessaor:
|
||||
|
|
@ -7,48 +9,55 @@ class JpegProcessaor:
|
|||
self.data = {}
|
||||
|
||||
def get_metadata(self, img):
|
||||
if "exif" in img.info:
|
||||
try:
|
||||
if "exif" in img.info:
|
||||
exif_dict = piexif.load(img.info["exif"])
|
||||
for ifd, value in exif_dict.items():
|
||||
# this exclude thumbnail IFD (its the thumbnails blob data. it can be removed but the image will take a couple more seconds to load)
|
||||
if not isinstance(exif_dict[ifd], dict):
|
||||
continue
|
||||
|
||||
# iterate through the IFD
|
||||
for tag, tag_value in exif_dict[ifd].items():
|
||||
tag_info = piexif.TAGS[ifd].get(tag, {})
|
||||
|
||||
# Get the human-readable name for the tag
|
||||
tag_name = (
|
||||
tag_info.get("name", "Unknown Tag")
|
||||
if tag_info
|
||||
else "Unknown Tag"
|
||||
)
|
||||
|
||||
# exculudes tags that are necessary for image display integrity
|
||||
if (
|
||||
tag_name == "Orientation"
|
||||
or tag_name == "ColorSpace"
|
||||
or tag_name == "ExifTag"
|
||||
):
|
||||
continue
|
||||
|
||||
# save to list and dict
|
||||
self.tags_to_delete.append(tag)
|
||||
self.data[tag_name] = tag_value
|
||||
return {"data": self.data, "tags_to_delete": self.tags_to_delete}
|
||||
else:
|
||||
raise MetadataNotFoundError("No EXIF data found in the image.")
|
||||
except MetadataNotFoundError as e:
|
||||
return f"Error: {str(e)}"
|
||||
|
||||
def delete_metadata(self, img, tags_to_delete):
|
||||
try:
|
||||
exif_dict = piexif.load(img.info["exif"])
|
||||
for ifd, value in exif_dict.items():
|
||||
# this exclude thumbnail IFD (its the thumbnails blob data. it can be removed but the image will take a couple more seconds to load)
|
||||
# exclude thumbnail IFD (its the thumbnails blob data so i dont wanna deal with that)
|
||||
if not isinstance(exif_dict[ifd], dict):
|
||||
continue
|
||||
|
||||
# iterate through the IFD
|
||||
for tag, tag_value in exif_dict[ifd].items():
|
||||
tag_info = piexif.TAGS[ifd].get(tag, {})
|
||||
# iterate through and delete tags
|
||||
for tag in list(exif_dict[ifd]):
|
||||
if tag in tags_to_delete:
|
||||
del exif_dict[ifd][tag]
|
||||
|
||||
# Get the human-readable name for the tag
|
||||
tag_name = (
|
||||
tag_info.get("name", "Unknown Tag")
|
||||
if tag_info
|
||||
else "Unknown Tag"
|
||||
)
|
||||
|
||||
# exculudes tags that are necessary for image display integrity
|
||||
if (
|
||||
tag_name == "Orientation"
|
||||
or tag_name == "ColorSpace"
|
||||
or tag_name == "ExifTag"
|
||||
):
|
||||
continue
|
||||
|
||||
# save to list and dict
|
||||
self.tags_to_delete.append(tag)
|
||||
self.data[tag_name] = tag_value
|
||||
|
||||
return {"data": self.data, "tags_to_delete": self.tags_to_delete}
|
||||
|
||||
def delete_metadata(self, img, tags_to_delete):
|
||||
exif_dict = piexif.load(img.info["exif"])
|
||||
for ifd, value in exif_dict.items():
|
||||
# exclude thumbnail IFD (its the thumbnails blob data so i dont wanna deal with that)
|
||||
if not isinstance(exif_dict[ifd], dict):
|
||||
continue
|
||||
|
||||
# iterate through and delete tags
|
||||
for tag in list(exif_dict[ifd]):
|
||||
if tag in tags_to_delete:
|
||||
del exif_dict[ifd][tag]
|
||||
|
||||
return exif_dict
|
||||
return exif_dict
|
||||
except Exception as e:
|
||||
raise MetadataProcessingError(f"Error Processing: {str(e)}")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
from PIL import ExifTags
|
||||
|
||||
from src.utils.exceptions import MetadataNotFoundError, MetadataProcessingError
|
||||
|
||||
|
||||
class PngProcessor:
|
||||
def __init__(self):
|
||||
self.tags_to_delete = []
|
||||
self.data = {}
|
||||
|
||||
def get_metadata(self, img):
|
||||
img.load()
|
||||
exif = img.getexif()
|
||||
try:
|
||||
if exif:
|
||||
# iterate through the (0th) IFD
|
||||
for tag, value in exif.items():
|
||||
# Get the human-readable name for the tag
|
||||
tag_name = ExifTags.TAGS.get(tag, tag)
|
||||
|
||||
# save to list and dict
|
||||
self.tags_to_delete.append(tag)
|
||||
self.data[tag_name] = value
|
||||
print(f"{tag_name}: {value}")
|
||||
|
||||
# terate through the (GPS) IFD
|
||||
gps_ifd = exif.get_ifd(ExifTags.IFD.GPSInfo)
|
||||
for tag, value in gps_ifd.items():
|
||||
# Get the human-readable name for the tag
|
||||
tag_name = ExifTags.GPSTAGS.get(tag, tag)
|
||||
|
||||
# save to list and dict
|
||||
self.tags_to_delete.append(tag)
|
||||
self.data[tag_name] = value
|
||||
print(f"{tag_name}: {value}")
|
||||
|
||||
return {"data": self.data, "tags_to_delete": self.tags_to_delete}
|
||||
else:
|
||||
raise MetadataNotFoundError("No EXIF data found in the image.")
|
||||
except MetadataNotFoundError as e:
|
||||
return f"Error: {str(e)}"
|
||||
|
||||
def delete_metadata(self, img, tags_to_delete):
|
||||
img.load()
|
||||
exif = img.getexif()
|
||||
try:
|
||||
# iterate through the (0th) IFD
|
||||
for tag_id, value in exif.items():
|
||||
if tag_id in tags_to_delete:
|
||||
del exif[tag_id]
|
||||
|
||||
# terate through the (GPS) IFD
|
||||
gps_ifd = exif.get_ifd(ExifTags.IFD.GPSInfo)
|
||||
for tag_id, value in gps_ifd.items():
|
||||
if tag_id in tags_to_delete:
|
||||
del gps_ifd[tag_id]
|
||||
|
||||
return exif + gps_ifd
|
||||
except Exception as e:
|
||||
raise MetadataProcessingError(f"Error Processing image: {str(e)}")
|
||||
Loading…
Reference in New Issue