Skip to content

Neoteroi/Gallerist-AzureStorage

Repository files navigation

Build pypi versions license

Gallerist-AzureStorage

Gallerist classes for Azure Storage: implements reading image files from Azure Blob Service, and writing of resized pictures to the same.

$ pip install gallerist-azurestorage

This library is used in Torino, a file explorer for Azure Storage Account, and in Gallerist-AzureFunctions, an Azure Functions front-end that uses Gallerist library, to resize pictures in Azure Storage Blob Service.

Example: synchronous code resizing pictures on Azure Storage

from gallerist import Gallerist, ImageSize
from galleristazurestorage import AzureBlobFileStore

store = AzureBlobFileStore.from_connection_string(
    "<YOUR_CONNECTION_STRING>",
    "CONTAINER_NAME",
)

gallerist = Gallerist(store)

# configuring sizes by mime (use '*' to match any other mime):
gallerist = Gallerist(
    store,
    sizes={
        "image/jpeg": [ImageSize("a", 1200), ImageSize("b", 600), ImageSize("c", 300)],
        "image/png": [ImageSize("a", 350), ImageSize("b", 250), ImageSize("c", 150)],
    },
)

# the following function call causes the creation of several versions of the
# image in different sizes; note that this operation is CPU bound
metadata = gallerist.process_image("ORIGINAL_FILE_NAME_ALREADY_ON_STORAGE.png")

print(metadata)

Asynchronous example using executors (recommended for async scenarios)

import asyncio
import concurrent.futures

from gallerist import Gallerist, ImageSize

from galleristazurestorage import AzureBlobFileStore

store = AzureBlobFileStore.from_connection_string(
    "<YOUR_CONNECTION_STRING>",
    "CONTAINER_NAME",
)

gallerist = Gallerist(store)

# configuring sizes by mime (use '*' to match any other mime):
gallerist = Gallerist(
    store,
    sizes={
        "image/jpeg": [ImageSize("a", 1200), ImageSize("b", 600), ImageSize("c", 300)],
        "image/png": [ImageSize("a", 350), ImageSize("b", 250), ImageSize("c", 150)],
    },
)


async def main():
    loop = asyncio.get_event_loop()

    with concurrent.futures.ProcessPoolExecutor() as pool:
        metadata = await loop.run_in_executor(
            pool, gallerist.process_image, "EXISTING_FILE_ON_STORAGE.jpg"
        )

        print(metadata)


asyncio.run(main())

Alternatively to using an executor explicitly, it is possible to use loop.call_soon_threadsafe:

from gallerist import Gallerist, ImageSize
from galleristazurestorage import AzureBlobFileStore

store = AzureBlobFileStore.from_connection_string(
    "<YOUR_CONNECTION_STRING>",
    "CONTAINER_NAME",
)

gallerist = Gallerist(store)

# configuring sizes by mime (use '*' to match any other mime):
gallerist = Gallerist(
    store,
    sizes={
        "image/jpeg": [ImageSize("a", 1200), ImageSize("b", 600), ImageSize("c", 300)],
        "image/png": [ImageSize("a", 350), ImageSize("b", 250), ImageSize("c", 150)],
    },
)

def process_image(image_path: str):
    # configuring sizes by mime (use '*' to match any other mime):
    gallerist = Gallerist(
        store,
        sizes={
            "image/jpeg": [
                ImageSize("a", 1200),
                ImageSize("b", 600),
                ImageSize("c", 300),
            ],
            "image/png": [
                ImageSize("a", 350),
                ImageSize("b", 250),
                ImageSize("c", 150),
            ],
        },
    )

    metadata = gallerist.process_image(image_path)

    print(metadata)


async def main():
    loop = asyncio.get_event_loop()
    loop.call_soon_threadsafe(process_image, "EXISTING_FILE_ON_STORAGE.jpg")


asyncio.run(main())

Asynchronous example using asynchronous methods from azure-storage-blob.aio

Note: azure-storage-blob requires aiohttp, and is not compatible with concurrent.futures.ProcessPoolExecutor.

import asyncio
from gallerist import Gallerist, ImageSize
from galleristazurestorage.aio import AzureBlobAsyncFileStore

store = AzureBlobFileStore.from_connection_string(
    "<YOUR_CONNECTION_STRING>",
    "CONTAINER_NAME",
)

gallerist = Gallerist(store)

# configuring sizes by mime (use '*' to match any other mime):
gallerist = Gallerist(
    store,
    sizes={
        "image/jpeg": [ImageSize("a", 1200), ImageSize("b", 600), ImageSize("c", 300)],
        "image/png": [ImageSize("a", 350), ImageSize("b", 250), ImageSize("c", 150)],
    },
)


async def main():
    metadata = await gallerist.process_image_async(
        "EXISTING_FILE_ON_STORAGE.jpg"
    )

    print(metadata)


asyncio.run(main())