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.
|
**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`
|
#### `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).
|
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 info """
|
||||||
|
|
||||||
__version__ = "0.30.4"
|
__version__ = "0.30.5"
|
||||||
|
|||||||
@@ -642,6 +642,41 @@ class PhotoInfo:
|
|||||||
otherwise returns False """
|
otherwise returns False """
|
||||||
return self._info["raw_is_original"]
|
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(
|
def render_template(
|
||||||
self,
|
self,
|
||||||
template_str,
|
template_str,
|
||||||
|
|||||||
@@ -716,7 +716,14 @@ class PhotosDB:
|
|||||||
RKVersion.rawMasterUuid,
|
RKVersion.rawMasterUuid,
|
||||||
RKVersion.nonRawMasterUuid,
|
RKVersion.nonRawMasterUuid,
|
||||||
RKMaster.alternateMasterUuid,
|
RKMaster.alternateMasterUuid,
|
||||||
RKVersion.isInTrash
|
RKVersion.isInTrash,
|
||||||
|
RKVersion.processedHeight,
|
||||||
|
RKVersion.processedWidth,
|
||||||
|
RKVersion.orientation,
|
||||||
|
RKMaster.height,
|
||||||
|
RKMaster.width,
|
||||||
|
RKMaster.orientation,
|
||||||
|
RKMaster.fileSize
|
||||||
FROM RKVersion, RKMaster
|
FROM RKVersion, RKMaster
|
||||||
WHERE RKVersion.masterUuid = RKMaster.uuid"""
|
WHERE RKVersion.masterUuid = RKMaster.uuid"""
|
||||||
)
|
)
|
||||||
@@ -736,7 +743,14 @@ class PhotosDB:
|
|||||||
RKVersion.rawMasterUuid,
|
RKVersion.rawMasterUuid,
|
||||||
RKVersion.nonRawMasterUuid,
|
RKVersion.nonRawMasterUuid,
|
||||||
RKMaster.alternateMasterUuid,
|
RKMaster.alternateMasterUuid,
|
||||||
RKVersion.isInTrash
|
RKVersion.isInTrash,
|
||||||
|
RKVersion.processedHeight,
|
||||||
|
RKVersion.processedWidth,
|
||||||
|
RKVersion.orientation,
|
||||||
|
RKMaster.height,
|
||||||
|
RKMaster.width,
|
||||||
|
RKMaster.orientation,
|
||||||
|
RKMaster.originalFileSize
|
||||||
FROM RKVersion, RKMaster
|
FROM RKVersion, RKMaster
|
||||||
WHERE RKVersion.masterUuid = RKMaster.uuid"""
|
WHERE RKVersion.masterUuid = RKMaster.uuid"""
|
||||||
)
|
)
|
||||||
@@ -775,6 +789,13 @@ class PhotosDB:
|
|||||||
# 30 RKVersion.nonRawMasterUuid, -- UUID of non-RAW master
|
# 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)
|
# 31 RKMaster.alternateMasterUuid -- UUID of alternate master (will be RAW master for JPEG and JPEG master for RAW)
|
||||||
# 32 RKVersion.isInTrash
|
# 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:
|
for row in c:
|
||||||
uuid = row[0]
|
uuid = row[0]
|
||||||
@@ -920,6 +941,15 @@ class PhotosDB:
|
|||||||
# recently deleted items
|
# recently deleted items
|
||||||
self._dbphotos[uuid]["intrash"] = True if row[32] == 1 else False
|
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
|
# get additional details from RKMaster, needed for RAW processing
|
||||||
c.execute(
|
c.execute(
|
||||||
""" SELECT
|
""" SELECT
|
||||||
@@ -1457,7 +1487,14 @@ class PhotosDB:
|
|||||||
ZADDITIONALASSETATTRIBUTES.ZREVERSELOCATIONDATA,
|
ZADDITIONALASSETATTRIBUTES.ZREVERSELOCATIONDATA,
|
||||||
ZGENERICASSET.ZMOMENT,
|
ZGENERICASSET.ZMOMENT,
|
||||||
ZADDITIONALASSETATTRIBUTES.ZORIGINALRESOURCECHOICE,
|
ZADDITIONALASSETATTRIBUTES.ZORIGINALRESOURCECHOICE,
|
||||||
ZGENERICASSET.ZTRASHEDSTATE
|
ZGENERICASSET.ZTRASHEDSTATE,
|
||||||
|
ZGENERICASSET.ZHEIGHT,
|
||||||
|
ZGENERICASSET.ZWIDTH,
|
||||||
|
ZGENERICASSET.ZORIENTATION,
|
||||||
|
ZADDITIONALASSETATTRIBUTES.ZORIGINALHEIGHT,
|
||||||
|
ZADDITIONALASSETATTRIBUTES.ZORIGINALWIDTH,
|
||||||
|
ZADDITIONALASSETATTRIBUTES.ZORIGINALORIENTATION,
|
||||||
|
ZADDITIONALASSETATTRIBUTES.ZORIGINALFILESIZE
|
||||||
FROM ZGENERICASSET
|
FROM ZGENERICASSET
|
||||||
JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = ZGENERICASSET.Z_PK
|
JOIN ZADDITIONALASSETATTRIBUTES ON ZADDITIONALASSETATTRIBUTES.ZASSET = ZGENERICASSET.Z_PK
|
||||||
ORDER BY ZGENERICASSET.ZUUID """
|
ORDER BY ZGENERICASSET.ZUUID """
|
||||||
@@ -1493,6 +1530,13 @@ class PhotosDB:
|
|||||||
# 26 ZGENERICASSET.ZMOMENT -- FK for ZMOMENT.Z_PK
|
# 26 ZGENERICASSET.ZMOMENT -- FK for ZMOMENT.Z_PK
|
||||||
# 27 ZADDITIONALASSETATTRIBUTES.ZORIGINALRESOURCECHOICE -- 1 if associated RAW image is original else 0
|
# 27 ZADDITIONALASSETATTRIBUTES.ZORIGINALRESOURCECHOICE -- 1 if associated RAW image is original else 0
|
||||||
# 28 ZGENERICASSET.ZTRASHEDSTATE -- 0 if not in trash, 1 if in trash
|
# 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:
|
for row in c:
|
||||||
uuid = row[0]
|
uuid = row[0]
|
||||||
@@ -1644,6 +1688,15 @@ class PhotosDB:
|
|||||||
# recently deleted items
|
# recently deleted items
|
||||||
info["intrash"] = True if row[28] == 1 else False
|
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
|
# associated RAW image info
|
||||||
# will be filled in later
|
# will be filled in later
|
||||||
info["has_raw"] = False
|
info["has_raw"] = False
|
||||||
|
|||||||
@@ -241,6 +241,46 @@ def test_attributes():
|
|||||||
assert p.ismissing == False
|
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():
|
def test_missing():
|
||||||
import osxphotos
|
import osxphotos
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ UUID_DICT = {
|
|||||||
"date_invalid": "YZFCPY24TUySvpu7owiqxA",
|
"date_invalid": "YZFCPY24TUySvpu7owiqxA",
|
||||||
"intrash": "3tljdX43R8+k6peNHVrJNQ",
|
"intrash": "3tljdX43R8+k6peNHVrJNQ",
|
||||||
"not_intrash": "6bxcNnzRQKGnK4uPrCJ9UQ",
|
"not_intrash": "6bxcNnzRQKGnK4uPrCJ9UQ",
|
||||||
|
"has_adjustments": "6bxcNnzRQKGnK4uPrCJ9UQ",
|
||||||
}
|
}
|
||||||
|
|
||||||
PHOTOS_DB_LEN = 8
|
PHOTOS_DB_LEN = 8
|
||||||
@@ -161,6 +162,44 @@ def test_attributes():
|
|||||||
assert p.ismissing == False
|
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():
|
def test_missing():
|
||||||
import osxphotos
|
import osxphotos
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user