Added height, width, orientation, filesize, closes #163

This commit is contained in:
Rhet Turnbull
2020-07-03 11:24:59 -07:00
parent 6ab0ad7e86
commit 541c390b7b
6 changed files with 192 additions and 4 deletions

View File

@@ -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).

View File

@@ -1,3 +1,3 @@
""" version info """
__version__ = "0.30.4"
__version__ = "0.30.5"

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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