|
1 | | -[](https://dev.azure.com/robertoprevato/Nest/_build/latest?definitionId=27&branchName=master) [](https://pypi.org/project/gallerist-azurestorage/) |
| 1 | +[](https://github.com/Neoteroi/Gallerist-AzureStorage/actions/workflows/build.yml) |
| 2 | +[](https://pypi.python.org/pypi/gallerist-azurestorage) |
| 3 | +[](https://github.com/Neoteroi/Gallerist-AzureStorage) |
| 4 | +[](https://github.com/Neoteroi/Gallerist-AzureStorage/blob/main/LICENSE) |
2 | 5 |
|
3 | 6 | # Gallerist-AzureStorage |
4 | | -Gallerist classes for Azure Storage: implements reading image files from Azure Blob Service, and writing of resized pictures to the same. |
| 7 | +Gallerist classes for Azure Storage: implements reading image files from Azure |
| 8 | +Blob Service, and writing of resized pictures to the same. |
5 | 9 |
|
6 | 10 | ```bash |
7 | 11 | $ pip install gallerist-azurestorage |
8 | 12 | ``` |
9 | 13 |
|
10 | | -This library is used in [Gallerist-AzureFunctions](https://github.com/RobertoPrevato/Gallerist-AzureFunctions), an Azure Functions front-end that uses [`Gallerist`](https://github.com/RobertoPrevato/Gallerist) library, to resize pictures |
11 | | -in Azure Storage Blob Service. |
| 14 | +This library is used in |
| 15 | +[Gallerist-AzureFunctions](https://github.com/Neoteroi/Gallerist-AzureFunctions), |
| 16 | +an Azure Functions front-end that uses |
| 17 | +[`Gallerist`](https://github.com/Neoteroi/Gallerist) library, to resize |
| 18 | +pictures in Azure Storage Blob Service. |
| 19 | + |
| 20 | +# Example: synchronous code resizing pictures on Azure Storage |
| 21 | + |
| 22 | +```python |
| 23 | +from gallerist import Gallerist, ImageSize |
| 24 | +from galleristazurestorage import AzureBlobFileStore |
| 25 | + |
| 26 | +store = AzureBlobFileStore.from_connection_string( |
| 27 | + "<YOUR_CONNECTION_STRING>", |
| 28 | + "CONTAINER_NAME", |
| 29 | +) |
| 30 | + |
| 31 | +gallerist = Gallerist(store) |
| 32 | + |
| 33 | +# configuring sizes by mime (use '*' to match any other mime): |
| 34 | +gallerist = Gallerist( |
| 35 | + store, |
| 36 | + sizes={ |
| 37 | + "image/jpeg": [ImageSize("a", 1200), ImageSize("b", 600), ImageSize("c", 300)], |
| 38 | + "image/png": [ImageSize("a", 350), ImageSize("b", 250), ImageSize("c", 150)], |
| 39 | + }, |
| 40 | +) |
| 41 | + |
| 42 | +# the following function call causes the creation of several versions of the |
| 43 | +# image in different sizes; note that this operation is IO bound |
| 44 | +metadata = gallerist.process_image("ORIGINAL_FILE_NAME_ALREADY_ON_STORAGE.png") |
| 45 | + |
| 46 | +print(metadata) |
| 47 | + |
| 48 | +``` |
| 49 | + |
| 50 | +# Asynchronous example using executors (recommended for async scenarios) |
| 51 | + |
| 52 | +```python |
| 53 | +import asyncio |
| 54 | +import concurrent.futures |
| 55 | + |
| 56 | +from gallerist import Gallerist, ImageSize |
| 57 | + |
| 58 | +from galleristazurestorage import AzureBlobFileStore |
| 59 | + |
| 60 | +store = AzureBlobFileStore.from_connection_string( |
| 61 | + "<YOUR_CONNECTION_STRING>", |
| 62 | + "CONTAINER_NAME", |
| 63 | +) |
| 64 | + |
| 65 | +gallerist = Gallerist(store) |
| 66 | + |
| 67 | +# configuring sizes by mime (use '*' to match any other mime): |
| 68 | +gallerist = Gallerist( |
| 69 | + store, |
| 70 | + sizes={ |
| 71 | + "image/jpeg": [ImageSize("a", 1200), ImageSize("b", 600), ImageSize("c", 300)], |
| 72 | + "image/png": [ImageSize("a", 350), ImageSize("b", 250), ImageSize("c", 150)], |
| 73 | + }, |
| 74 | +) |
| 75 | + |
| 76 | + |
| 77 | +async def main(): |
| 78 | + loop = asyncio.get_event_loop() |
| 79 | + |
| 80 | + with concurrent.futures.ProcessPoolExecutor() as pool: |
| 81 | + metadata = await loop.run_in_executor( |
| 82 | + pool, gallerist.process_image, "EXISTING_FILE_ON_STORAGE.jpg" |
| 83 | + ) |
| 84 | + |
| 85 | + print(metadata) |
| 86 | + |
| 87 | + |
| 88 | +asyncio.run(main()) |
| 89 | + |
| 90 | +``` |
| 91 | + |
| 92 | +Alternatively to using an executor explicitly, it is possible to use |
| 93 | +`loop.call_soon_threadsafe`: |
| 94 | + |
| 95 | +```python |
| 96 | +from gallerist import Gallerist, ImageSize |
| 97 | +from galleristazurestorage import AzureBlobFileStore |
| 98 | + |
| 99 | +store = AzureBlobFileStore.from_connection_string( |
| 100 | + "<YOUR_CONNECTION_STRING>", |
| 101 | + "CONTAINER_NAME", |
| 102 | +) |
| 103 | + |
| 104 | +gallerist = Gallerist(store) |
| 105 | + |
| 106 | +# configuring sizes by mime (use '*' to match any other mime): |
| 107 | +gallerist = Gallerist( |
| 108 | + store, |
| 109 | + sizes={ |
| 110 | + "image/jpeg": [ImageSize("a", 1200), ImageSize("b", 600), ImageSize("c", 300)], |
| 111 | + "image/png": [ImageSize("a", 350), ImageSize("b", 250), ImageSize("c", 150)], |
| 112 | + }, |
| 113 | +) |
| 114 | + |
| 115 | +def process_image(image_path: str): |
| 116 | + # configuring sizes by mime (use '*' to match any other mime): |
| 117 | + gallerist = Gallerist( |
| 118 | + store, |
| 119 | + sizes={ |
| 120 | + "image/jpeg": [ |
| 121 | + ImageSize("a", 1200), |
| 122 | + ImageSize("b", 600), |
| 123 | + ImageSize("c", 300), |
| 124 | + ], |
| 125 | + "image/png": [ |
| 126 | + ImageSize("a", 350), |
| 127 | + ImageSize("b", 250), |
| 128 | + ImageSize("c", 150), |
| 129 | + ], |
| 130 | + }, |
| 131 | + ) |
| 132 | + |
| 133 | + metadata = gallerist.process_image(image_path) |
| 134 | + |
| 135 | + print(metadata) |
| 136 | + |
| 137 | + |
| 138 | +async def main(): |
| 139 | + loop = asyncio.get_event_loop() |
| 140 | + loop.call_soon_threadsafe(process_image, "EXISTING_FILE_ON_STORAGE.jpg") |
| 141 | + |
| 142 | + |
| 143 | +asyncio.run(main()) |
| 144 | +``` |
| 145 | + |
| 146 | +# Asynchronous example using asynchronous methods from azure-storage-blob.aio |
| 147 | + |
| 148 | +Note: `azure-storage-blob` requires `aiohttp`, and is not compatible with |
| 149 | +`concurrent.futures.ProcessPoolExecutor`. |
| 150 | + |
| 151 | +```python |
| 152 | +import asyncio |
| 153 | +from gallerist import Gallerist, ImageSize |
| 154 | +from galleristazurestorage.aio import AzureBlobAsyncFileStore |
| 155 | + |
| 156 | +store = AzureBlobFileStore.from_connection_string( |
| 157 | + "<YOUR_CONNECTION_STRING>", |
| 158 | + "CONTAINER_NAME", |
| 159 | +) |
| 160 | + |
| 161 | +gallerist = Gallerist(store) |
| 162 | + |
| 163 | +# configuring sizes by mime (use '*' to match any other mime): |
| 164 | +gallerist = Gallerist( |
| 165 | + store, |
| 166 | + sizes={ |
| 167 | + "image/jpeg": [ImageSize("a", 1200), ImageSize("b", 600), ImageSize("c", 300)], |
| 168 | + "image/png": [ImageSize("a", 350), ImageSize("b", 250), ImageSize("c", 150)], |
| 169 | + }, |
| 170 | +) |
| 171 | + |
| 172 | + |
| 173 | +async def main(): |
| 174 | + metadata = await gallerist.process_image_async( |
| 175 | + "EXISTING_FILE_ON_STORAGE.jpg" |
| 176 | + ) |
| 177 | + |
| 178 | + print(metadata) |
| 179 | + |
| 180 | + |
| 181 | +asyncio.run(main()) |
| 182 | +``` |
0 commit comments