Added height, width, orientation, filesize, closes #163
This commit is contained in:
21
README.md
21
README.md
@@ -1048,6 +1048,27 @@ Returns the absolute path to the edited photo on disk as a string. If the photo
|
||||
|
||||
**Note**: will also return None if the edited photo is missing on disk.
|
||||
|
||||
#### `height`
|
||||
Returns height of the photo in pixels. If image has been edited, returns height of the edited image, otherwise returns height of the original image. See also [original_height](#original_height).
|
||||
|
||||
#### `width`
|
||||
Returns width of the photo in pixels. If image has been edited, returns width of the edited image, otherwise returns width of the original image. See also [original_width](#original_width).
|
||||
|
||||
#### `orientation`
|
||||
Returns EXIF orientation value of the photo as integer. If image has been edited, returns orientation of the edited image, otherwise returns orientation of the original image. See also [original_orientation](#original_orientation).
|
||||
|
||||
#### `original_height`
|
||||
Returns height of the original photo in pixels. See also [height](#height).
|
||||
|
||||
#### `original_width`
|
||||
Returns width of the original photo in pixels. See also [width](#width).
|
||||
|
||||
#### `original_orientation`
|
||||
Returns EXIF orientation value of the original photo as integer. See also [orientation](#orientation).
|
||||
|
||||
#### `original_filesize`
|
||||
Returns size of the original photo in bytes as integer.
|
||||
|
||||
#### `ismissing`
|
||||
Returns `True` if the original image file is missing on disk, otherwise `False`. This can occur if the file has been uploaded to iCloud but not yet downloaded to the local library or if the file was deleted or imported from a disk that has been unmounted and user hasn't enabled "Copy items to the Photos library" in Photos preferences. **Note**: this status is computed based on data in the Photos library and `ismissing` does not verify if the photo is actually missing. See also [path](#path).
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
""" version info """
|
||||
|
||||
__version__ = "0.30.4"
|
||||
__version__ = "0.30.5"
|
||||
|
||||
@@ -642,6 +642,41 @@ class PhotoInfo:
|
||||
otherwise returns False """
|
||||
return self._info["raw_is_original"]
|
||||
|
||||
@property
|
||||
def height(self):
|
||||
""" returns height of the current photo version in pixels """
|
||||
return self._info["height"]
|
||||
|
||||
@property
|
||||
def width(self):
|
||||
""" returns width of the current photo version in pixels """
|
||||
return self._info["width"]
|
||||
|
||||
@property
|
||||
def orientation(self):
|
||||
""" returns EXIF orientation of the current photo version as int """
|
||||
return self._info["orientation"]
|
||||
|
||||
@property
|
||||
def original_height(self):
|
||||
""" returns height of the original photo version in pixels """
|
||||
return self._info["original_height"]
|
||||
|
||||
@property
|
||||
def original_width(self):
|
||||
""" returns width of the original photo version in pixels """
|
||||
return self._info["original_width"]
|
||||
|
||||
@property
|
||||
def original_orientation(self):
|
||||
""" returns EXIF orientation of the original photo version as int """
|
||||
return self._info["original_orientation"]
|
||||
|
||||
@property
|
||||
def original_filesize(self):
|
||||
""" returns filesize of original photo in bytes as int """
|
||||
return self._info["original_filesize"]
|
||||
|
||||
def render_template(
|
||||
self,
|
||||
template_str,
|
||||
|
||||
@@ -716,7 +716,14 @@ class PhotosDB:
|
||||
RKVersion.rawMasterUuid,
|
||||
RKVersion.nonRawMasterUuid,
|
||||
RKMaster.alternateMasterUuid,
|
||||
RKVersion.isInTrash
|
||||
RKVersion.isInTrash,
|
||||
RKVersion.processedHeight,
|
||||
RKVersion.processedWidth,
|
||||
RKVersion.orientation,
|
||||
RKMaster.height,
|
||||
RKMaster.width,
|
||||
RKMaster.orientation,
|
||||
RKMaster.fileSize
|
||||
FROM RKVersion, RKMaster
|
||||
WHERE RKVersion.masterUuid = RKMaster.uuid"""
|
||||
)
|
||||
@@ -736,7 +743,14 @@ class PhotosDB:
|
||||
RKVersion.rawMasterUuid,
|
||||
RKVersion.nonRawMasterUuid,
|
||||
RKMaster.alternateMasterUuid,
|
||||
RKVersion.isInTrash
|
||||
RKVersion.isInTrash,
|
||||
RKVersion.processedHeight,
|
||||
RKVersion.processedWidth,
|
||||
RKVersion.orientation,
|
||||
RKMaster.height,
|
||||
RKMaster.width,
|
||||
RKMaster.orientation,
|
||||
RKMaster.originalFileSize
|
||||
FROM RKVersion, RKMaster
|
||||
WHERE RKVersion.masterUuid = RKMaster.uuid"""
|
||||
)
|
||||
@@ -775,6 +789,13 @@ class PhotosDB:
|
||||
# 30 RKVersion.nonRawMasterUuid, -- UUID of non-RAW master
|
||||
# 31 RKMaster.alternateMasterUuid -- UUID of alternate master (will be RAW master for JPEG and JPEG master for RAW)
|
||||
# 32 RKVersion.isInTrash
|
||||
# 33 RKVersion.processedHeight,
|
||||
# 34 RKVersion.processedWidth,
|
||||
# 35 RKVersion.orientation,
|
||||
# 36 RKMaster.height,
|
||||
# 37 RKMaster.width,
|
||||
# 38 RKMaster.orientation,
|
||||
# 39 RKMaster.originalFileSize
|
||||
|
||||
for row in c:
|
||||
uuid = row[0]
|
||||
@@ -920,6 +941,15 @@ class PhotosDB:
|
||||
# recently deleted items
|
||||
self._dbphotos[uuid]["intrash"] = True if row[32] == 1 else False
|
||||
|
||||
# height/width/orientation
|
||||
self._dbphotos[uuid]["height"] = row[33]
|
||||
self._dbphotos[uuid]["width"] = row[34]
|
||||
self._dbphotos[uuid]["orientation"] = row[35]
|
||||
self._dbphotos[uuid]["original_height"] = row[36]
|
||||
self._dbphotos[uuid]["original_width"] = row[37]
|
||||
self._dbphotos[uuid]["original_orientation"] = row[38]
|
||||
self._dbphotos[uuid]["original_filesize"] = row[39]
|
||||
|
||||
# get additional details from RKMaster, needed for RAW processing
|
||||
c.execute(
|
||||
""" SELECT
|
||||
@@ -1457,7 +1487,14 @@ class PhotosDB:
|
||||
ZADDITIONALASSETATTRIBUTES.ZREVERSELOCATIONDATA,
|
||||
ZGENERICASSET.ZMOMENT,
|
||||
ZADDITIONALASSETATTRIBUTES.ZORIGINALRESOURCECHOICE,
|
||||
ZGENERICASSET.ZTRASHEDSTATE
|
||||
ZGENERICASSET.ZTRASHEDSTATE,
|
||||
ZGENERICASSET.ZHEIGHT,
|
||||
ZGENERICASSET.ZWIDTH,
|
||||
ZGENERICASSET.ZORIENTATION,
|
||||
ZADDITIONALASSETATTRIBUTES.ZORIGINALHEIGHT,
|
||||
ZADDITIONALASSETATTRIBUTES.ZORIGINALWIDTH,
|
||||
ZADDITIONALASSETATTRIBUTES.ZORIGINALORIENTATION,
|
||||
ZADDITIONALASSETATTRIBUTES.ZORIGINALFILESIZE
|
||||
FROM ZGENERICASSET
|
||||
JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = ZGENERICASSET.Z_PK
|
||||
ORDER BY ZGENERICASSET.ZUUID """
|
||||
@@ -1493,6 +1530,13 @@ class PhotosDB:
|
||||
# 26 ZGENERICASSET.ZMOMENT -- FK for ZMOMENT.Z_PK
|
||||
# 27 ZADDITIONALASSETATTRIBUTES.ZORIGINALRESOURCECHOICE -- 1 if associated RAW image is original else 0
|
||||
# 28 ZGENERICASSET.ZTRASHEDSTATE -- 0 if not in trash, 1 if in trash
|
||||
# 29 ZGENERICASSET.ZHEIGHT,
|
||||
# 30 ZGENERICASSET.ZWIDTH,
|
||||
# 31 ZGENERICASSET.ZORIENTATION,
|
||||
# 32 ZADDITIONALASSETATTRIBUTES.ZORIGINALHEIGHT,
|
||||
# 33 ZADDITIONALASSETATTRIBUTES.ZORIGINALWIDTH,
|
||||
# 34 ZADDITIONALASSETATTRIBUTES.ZORIGINALORIENTATION,
|
||||
# 35 ZADDITIONALASSETATTRIBUTES.ZORIGINALFILESIZE
|
||||
|
||||
for row in c:
|
||||
uuid = row[0]
|
||||
@@ -1644,6 +1688,15 @@ class PhotosDB:
|
||||
# recently deleted items
|
||||
info["intrash"] = True if row[28] == 1 else False
|
||||
|
||||
# height/width/orientation
|
||||
info["height"] = row[29]
|
||||
info["width"] = row[30]
|
||||
info["orientation"] = row[31]
|
||||
info["original_height"] = row[32]
|
||||
info["original_width"] = row[33]
|
||||
info["original_orientation"] = row[34]
|
||||
info["original_filesize"] = row[35]
|
||||
|
||||
# associated RAW image info
|
||||
# will be filled in later
|
||||
info["has_raw"] = False
|
||||
|
||||
@@ -241,6 +241,46 @@ def test_attributes():
|
||||
assert p.ismissing == False
|
||||
|
||||
|
||||
def test_attributes_2():
|
||||
""" Test attributes including height, width, etc """
|
||||
import datetime
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
|
||||
assert len(photos) == 1
|
||||
p = photos[0]
|
||||
assert p.keywords == ["wedding"]
|
||||
assert p.original_filename == "wedding.jpg"
|
||||
assert p.filename == "E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51.jpeg"
|
||||
assert p.date == datetime.datetime(
|
||||
2019,
|
||||
4,
|
||||
15,
|
||||
14,
|
||||
40,
|
||||
24,
|
||||
86000,
|
||||
datetime.timezone(datetime.timedelta(seconds=-14400)),
|
||||
)
|
||||
assert p.description == "Bride Wedding day"
|
||||
assert p.title is None
|
||||
assert sorted(p.albums) == ["AlbumInFolder", "I have a deleted twin"]
|
||||
assert p.persons == ["Maria"]
|
||||
assert p.path.endswith(
|
||||
"tests/Test-10.15.5.photoslibrary/originals/E/E9BC5C36-7CD1-40A1-A72B-8B8FAC227D51.jpeg"
|
||||
)
|
||||
assert not p.ismissing
|
||||
assert p.hasadjustments
|
||||
assert p.height == 1325
|
||||
assert p.width == 1526
|
||||
assert p.original_height == 1367
|
||||
assert p.original_width == 2048
|
||||
assert p.orientation == 1
|
||||
assert p.original_orientation == 1
|
||||
assert p.original_filesize == 460483
|
||||
|
||||
|
||||
def test_missing():
|
||||
import osxphotos
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ UUID_DICT = {
|
||||
"date_invalid": "YZFCPY24TUySvpu7owiqxA",
|
||||
"intrash": "3tljdX43R8+k6peNHVrJNQ",
|
||||
"not_intrash": "6bxcNnzRQKGnK4uPrCJ9UQ",
|
||||
"has_adjustments": "6bxcNnzRQKGnK4uPrCJ9UQ",
|
||||
}
|
||||
|
||||
PHOTOS_DB_LEN = 8
|
||||
@@ -161,6 +162,44 @@ def test_attributes():
|
||||
assert p.ismissing == False
|
||||
|
||||
|
||||
def test_attributes_2():
|
||||
""" Test attributes including height, width, etc """
|
||||
import datetime
|
||||
import osxphotos
|
||||
|
||||
photosdb = osxphotos.PhotosDB(dbfile=PHOTOS_DB)
|
||||
photos = photosdb.photos(uuid=[UUID_DICT["has_adjustments"]])
|
||||
assert len(photos) == 1
|
||||
p = photos[0]
|
||||
assert p.keywords == ["wedding"]
|
||||
assert p.original_filename == "wedding.jpg"
|
||||
assert p.filename == "wedding.jpg"
|
||||
assert p.date == datetime.datetime(
|
||||
2019,
|
||||
4,
|
||||
15,
|
||||
14,
|
||||
40,
|
||||
24,
|
||||
86000,
|
||||
datetime.timezone(datetime.timedelta(seconds=-14400)),
|
||||
)
|
||||
assert p.description == "Bride Wedding day"
|
||||
assert p.title is None
|
||||
assert sorted(p.albums) == []
|
||||
assert p.persons == ["Maria"]
|
||||
assert p.path.endswith("Masters/2019/07/27/20190727-131650/wedding.jpg")
|
||||
assert not p.ismissing
|
||||
assert p.hasadjustments
|
||||
assert p.height == 1325
|
||||
assert p.width == 1526
|
||||
assert p.original_height == 1367
|
||||
assert p.original_width == 2048
|
||||
assert p.orientation == 1
|
||||
assert p.original_orientation == 1
|
||||
assert p.original_filesize == 460483
|
||||
|
||||
|
||||
def test_missing():
|
||||
import osxphotos
|
||||
|
||||
|
||||
Reference in New Issue
Block a user