From 145de3311cb9f32ac0bc9842b0600fcad84fed16 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Fri, 9 May 2025 21:58:54 -0500 Subject: add support for downloading new images from immich api on a separate thread --- immich.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 immich.py (limited to 'immich.py') diff --git a/immich.py b/immich.py new file mode 100644 index 0000000..1f1ccb8 --- /dev/null +++ b/immich.py @@ -0,0 +1,33 @@ +import requests +from io import BytesIO + +from texture import ImageTexture + + +class ImmichConnector: + def __init__(self, server_url, api_key): + self.server_url = server_url.removesuffix("/") + self.api_key = api_key + + def _request(self, endpoint): + return requests.get(f"{self.server_url}/api/{endpoint}", headers={ "x-api-key": self.api_key }) + + def load_album_assets(self, key): + response = self._request(f"albums/{key}") + if response.status_code != 200: return + + data = response.json() + return data["assets"] + + def load_image(self, pd, key, exif=None): + response = self._request(f"assets/{key}/thumbnail?size=fullsize") + if response.status_code != 200: return + + image_data = BytesIO(response.content) + it = ImageTexture(image_data, exif) + pd.textures.append(it) + print(f"Loaded image {key}") + + def idle(self, pd): + for asset in self.load_album_assets("bac029a5-972b-4519-bce0-a0d74add3969"): + self.load_image(pd, asset["id"], asset["exifInfo"]) -- cgit v1.2.3 From 31f1940ec8c4aba6a0c21b20eff9657d5d11cf80 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sun, 11 May 2025 00:20:08 -0500 Subject: albums thumbnails endpoint and albums endpoint --- immich.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'immich.py') diff --git a/immich.py b/immich.py index 1f1ccb8..63e6f63 100644 --- a/immich.py +++ b/immich.py @@ -12,6 +12,13 @@ class ImmichConnector: def _request(self, endpoint): return requests.get(f"{self.server_url}/api/{endpoint}", headers={ "x-api-key": self.api_key }) + def load_all_albums(self): + response = self._request("albums") + if response.status_code != 200: return + + data = response.json() + return data + def load_album_assets(self, key): response = self._request(f"albums/{key}") if response.status_code != 200: return @@ -19,15 +26,20 @@ class ImmichConnector: data = response.json() return data["assets"] - def load_image(self, pd, key, exif=None): - response = self._request(f"assets/{key}/thumbnail?size=fullsize") - if response.status_code != 200: return + def load_image(self, key, size="preview"): + response = self._request(f"assets/{key}/thumbnail?size={size}") + if response.status_code != 200: return None, None image_data = BytesIO(response.content) + mimetype = response.headers.get("Content-Type") + return image_data, mimetype + + def load_texture(self, pd, key, exif=None, size="preview"): + image_data, _ = self.load_image(key, size) it = ImageTexture(image_data, exif) pd.textures.append(it) print(f"Loaded image {key}") def idle(self, pd): for asset in self.load_album_assets("bac029a5-972b-4519-bce0-a0d74add3969"): - self.load_image(pd, asset["id"], asset["exifInfo"]) + self.load_texture(pd, asset["id"], asset["exifInfo"]) -- cgit v1.2.3 From e1a6fc09afc088dcb67263ed5923f5be41c32c31 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sun, 25 May 2025 21:38:37 -0500 Subject: use lazy caching texture list to limit number of images loaded at one time --- immich.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'immich.py') diff --git a/immich.py b/immich.py index 63e6f63..e73b34e 100644 --- a/immich.py +++ b/immich.py @@ -1,5 +1,6 @@ import requests from io import BytesIO +from queue import Queue from texture import ImageTexture @@ -8,6 +9,7 @@ class ImmichConnector: def __init__(self, server_url, api_key): self.server_url = server_url.removesuffix("/") self.api_key = api_key + self.texture_load_queue = Queue() def _request(self, endpoint): return requests.get(f"{self.server_url}/api/{endpoint}", headers={ "x-api-key": self.api_key }) @@ -34,12 +36,14 @@ class ImmichConnector: mimetype = response.headers.get("Content-Type") return image_data, mimetype - def load_texture(self, pd, key, exif=None, size="preview"): - image_data, _ = self.load_image(key, size) - it = ImageTexture(image_data, exif) - pd.textures.append(it) - print(f"Loaded image {key}") - - def idle(self, pd): - for asset in self.load_album_assets("bac029a5-972b-4519-bce0-a0d74add3969"): - self.load_texture(pd, asset["id"], asset["exifInfo"]) + def load_texture_async(self, texture_list, image_texture): + self.texture_load_queue.put((texture_list, image_texture)) + + def idle(self): + size = "preview" # TODO + while True: + texture_list, image_texture = self.texture_load_queue.get() + if not texture_list.index_in_cache_range(image_texture.asset_index): + continue # Texture was never loaded so it doesn't need to be free'd + image_data, _ = self.load_image(image_texture.asset_key, size) + image_texture.initialize(image_data) -- cgit v1.2.3 From b8df4605b42d9a61bb4ae4731efabbdc38166063 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Mon, 16 Jun 2025 21:50:38 -0500 Subject: add config and add application thread manager --- immich.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'immich.py') diff --git a/immich.py b/immich.py index e73b34e..ad39942 100644 --- a/immich.py +++ b/immich.py @@ -3,34 +3,38 @@ from io import BytesIO from queue import Queue from texture import ImageTexture +from manager import PixMan class ImmichConnector: - def __init__(self, server_url, api_key): - self.server_url = server_url.removesuffix("/") - self.api_key = api_key + def __init__(self): + config = PixMan().config + self.server_url = config.immich_url.removesuffix("/") + self.api_key = config.immich_api_key self.texture_load_queue = Queue() def _request(self, endpoint): + if not self.server_url: + return None return requests.get(f"{self.server_url}/api/{endpoint}", headers={ "x-api-key": self.api_key }) def load_all_albums(self): response = self._request("albums") - if response.status_code != 200: return + if not response or response.status_code != 200: return data = response.json() return data def load_album_assets(self, key): response = self._request(f"albums/{key}") - if response.status_code != 200: return + if not response or response.status_code != 200: return data = response.json() return data["assets"] def load_image(self, key, size="preview"): response = self._request(f"assets/{key}/thumbnail?size={size}") - if response.status_code != 200: return None, None + if not response or response.status_code != 200: return None, None image_data = BytesIO(response.content) mimetype = response.headers.get("Content-Type") @@ -47,3 +51,7 @@ class ImmichConnector: continue # Texture was never loaded so it doesn't need to be free'd image_data, _ = self.load_image(image_texture.asset_key, size) image_texture.initialize(image_data) + + def validate_connection(self): + # TODO + return True -- cgit v1.2.3 From ce64f1a42c9570efa75cc2f568e59d683f499bdd Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Fri, 20 Jun 2025 22:32:28 -0500 Subject: config update and more endpoints for api fromtend --- immich.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'immich.py') diff --git a/immich.py b/immich.py index ad39942..0f319c5 100644 --- a/immich.py +++ b/immich.py @@ -40,6 +40,13 @@ class ImmichConnector: mimetype = response.headers.get("Content-Type") return image_data, mimetype + def load_image_filename(self, key): + response = self._request(f"assets/{key}") + if not response or response.status_code != 200: return None, None + + data = response.json() + return data["originalFileName"] + def load_texture_async(self, texture_list, image_texture): self.texture_load_queue.put((texture_list, image_texture)) -- cgit v1.2.3 From 4c3d572eb850c32a45ec9cbaf82688d45c1eebf4 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Tue, 24 Jun 2025 19:16:36 -0500 Subject: add ability to change out albums list during runtime --- immich.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'immich.py') diff --git a/immich.py b/immich.py index 0f319c5..8c4f3e6 100644 --- a/immich.py +++ b/immich.py @@ -54,7 +54,7 @@ class ImmichConnector: size = "preview" # TODO while True: texture_list, image_texture = self.texture_load_queue.get() - if not texture_list.index_in_cache_range(image_texture.asset_index): + if not texture_list.index_in_cache_range(image_texture.asset_index) or texture_list.void: continue # Texture was never loaded so it doesn't need to be free'd image_data, _ = self.load_image(image_texture.asset_key, size) image_texture.initialize(image_data) -- cgit v1.2.3