diff --git a/.jules/bolt.md b/.jules/bolt.md index bb29aea..e33e696 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -14,3 +14,9 @@ - Naive conversion `np.clip(255. * tensor.cpu().numpy(), 0, 255).astype(np.uint8)` creates large intermediate float arrays on CPU. - Performing scaling, clamping, and casting on the tensor *before* moving to CPU (`(tensor * 255.0).clamp(0, 255).to(dtype=torch.uint8).cpu().numpy()`) is significantly faster and more memory efficient. **Action:** Always process tensors (scale/clamp/cast) before converting to numpy/CPU when preparing images for PIL/OpenCV. + +## 2026-01-14 - Avoid Redundant PIL to Numpy Conversion +**Learning:** +- Converting a large PIL Image back to a Numpy array (`np.array(img)`) is surprisingly slow (measured ~500ms for 4K image). +- When the PIL Image wraps an existing Numpy array and hasn't been modified (e.g. resized), reusing the original Numpy array avoids this overhead completely. +**Action:** Track modifications to PIL images (like resizing) and reuse the source Numpy array for OpenCV operations if no modifications occurred. diff --git a/discord_image_node.py b/discord_image_node.py index c90f804..cf6a495 100644 --- a/discord_image_node.py +++ b/discord_image_node.py @@ -432,6 +432,9 @@ class DiscordSendSaveImage: i = tensor_to_numpy_uint8(image) img = Image.fromarray(i) + # Track if resizing happened to optimize Discord encoding later + was_resized = False + # Get original dimensions before any resizing orig_width, orig_height = img.size @@ -452,11 +455,13 @@ class DiscordSendSaveImage: if (new_width != orig_width or new_height != orig_height): try: img = img.resize((new_width, new_height), selected_resize_method) + was_resized = True print(f"Successfully resized using {resize_method} method") except Exception as e: print(f"Error during power of 2 resize: {e}") # Fallback to BICUBIC if selected method fails img = img.resize((new_width, new_height), Image.BICUBIC) + was_resized = True print("Fallback to BICUBIC resize method due to error") # Get dimensions - either original or resized @@ -598,7 +603,12 @@ class DiscordSendSaveImage: elif file_format == "png": # Use CV2 for PNG (significantly faster) - img_cv = np.array(img) + # Optimization: If image wasn't resized, use the original numpy array 'i' + # This avoids an expensive PIL->Numpy conversion/copy (~500ms for 4K images) + if not was_resized: + img_cv = i + else: + img_cv = np.array(img) # Convert RGB (PIL) to BGR (OpenCV) if len(img_cv.shape) == 3 and img_cv.shape[2] == 3: