|
4 | 4 | from pathlib import Path |
5 | 5 | from typing import Any, Dict, List, Optional |
6 | 6 |
|
| 7 | +import numpy as np |
7 | 8 | import sqlalchemy |
8 | 9 | from fastapi import APIRouter, Depends |
9 | 10 | from ispyb.sqlalchemy import ( |
@@ -1104,29 +1105,43 @@ async def make_gif( |
1104 | 1105 | ] |
1105 | 1106 | output_dir = ( |
1106 | 1107 | (machine_config.rsync_basepath or Path("")).resolve() |
1107 | | - / secure_filename(year) |
| 1108 | + / secure_filename(str(year)) |
1108 | 1109 | / secure_filename(visit_name) |
1109 | 1110 | / "processed" |
1110 | 1111 | ) |
1111 | 1112 | output_dir.mkdir(exist_ok=True) |
1112 | 1113 | output_dir = output_dir / secure_filename(gif_params.raw_directory) |
1113 | 1114 | output_dir.mkdir(exist_ok=True) |
1114 | 1115 | output_path = output_dir / f"lamella_{gif_params.lamella_number}_milling.gif" |
1115 | | - image_full_paths = [ |
1116 | | - output_dir.parent / gif_params.raw_directory / i for i in gif_params.images |
1117 | | - ] |
| 1116 | + |
1118 | 1117 | if Image is not None: |
1119 | | - images = [Image.open(f) for f in image_full_paths] |
| 1118 | + images = [Image.open(f) for f in gif_params.images] |
1120 | 1119 | else: |
1121 | 1120 | images = [] |
1122 | 1121 | for im in images: |
1123 | 1122 | im.thumbnail((512, 512)) |
1124 | | - images[0].save( |
| 1123 | + |
| 1124 | + # Normalize and convert individual frames to 8-bit |
| 1125 | + arr: list[np.ndarray] = [] |
| 1126 | + for im in images: |
| 1127 | + frame = np.array(im).astype(np.float32) |
| 1128 | + vmin, vmax = np.percentile(frame, (0.5, 99.5)) |
| 1129 | + scale = 255 / ((vmax - vmin) or 1) |
| 1130 | + np.clip(frame, a_min=vmin, a_max=vmax, out=frame) |
| 1131 | + np.subtract(frame, vmin, out=frame) |
| 1132 | + np.multiply(frame, scale, out=frame) |
| 1133 | + arr.append(frame.astype(np.uint8)) |
| 1134 | + arr = np.array(arr).astype(np.uint8) |
| 1135 | + |
| 1136 | + # Convert back to Image objects and save as GIF |
| 1137 | + converted = [Image.fromarray(arr[f], mode="L") for f in range(len(images))] |
| 1138 | + converted[0].save( |
1125 | 1139 | output_path, |
1126 | 1140 | format="GIF", |
1127 | | - append_images=images[1:], |
| 1141 | + append_images=converted[1:], |
1128 | 1142 | save_all=True, |
1129 | 1143 | duration=30, |
1130 | 1144 | loop=0, |
1131 | 1145 | ) |
| 1146 | + |
1132 | 1147 | return {"output_gif": str(output_path)} |
0 commit comments