Fixed ComfyUI-Custom-Scripts
D:\USERFILES\ComfyUI\ComfyUI\custom_nodes\ComfyUI-Custom-Scripts\py\constrain_image.py
---
## Errors That Occurred
### Error 1: `ZeroDivisionError: division by zero`
```python
if constrained_width / constrained_height > aspect_ratio:
~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
# constrained_height is 0, causing division by zero failureError 2: `ValueError: height and width must be > 0`
resized_image = img.resize((constrained_width, constrained_height), Image.LANCZOS)
# PIL does not accept dimensions of 0 or lessRoot Cause Analysis
When a user sets `max_height=0` or `max_width=0`:
1. User sets max_height = 0
↓
2. constrained_height = min(max(current_height, min_height), max_height)
= min(max(768, 0), 0)
= min(768, 0)
= 0 ← Becomes zero!
↓
3. aspect_ratio = current_width / current_height
= 1024 / 0 ← Division by zero error!And if this somehow passes:
4. resized_image = img.resize((1, 0))
← PIL raises "height must be > 0" error and failsComplete Fixed Code
Fixed Code (Lines 28-86):
def constrain_image(self, images, max_width, max_height, min_width, min_height, crop_if_required):
crop_if_required = crop_if_required == "yes"
results = []
for image in images:
i = 255. * image.cpu().numpy()
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)).convert("RGB")
current_width, current_height = img.size
# ========== Check Point 1: Image Size Zero Check ==========
# Zero value check (set minimum value to 1)
if current_height <= 0:
current_height = 1
if current_width <= 0:
current_width = 1
aspect_ratio = current_width / current_height # ✓ Safe
# ========== Check Point 2: Parameter Zero Check ==========
# If max_width or max_height is 0, use the original size
if max_width <= 0:
max_width = current_width
if max_height <= 0:
max_height = current_height
# ========== Check Point 3: Initial Calculation ==========
constrained_width = min(max(current_width, min_width), max_width)
constrained_height = min(max(current_height, min_height), max_height)
# ========== Check Point 4: Zero Prevention After Calculation ==========
# Prevent zero after calculation
if constrained_width <= 0:
constrained_width = 1
if constrained_height <= 0:
constrained_height = 1
# ========== Check Point 5: Aspect Ratio Adjustment ==========
if constrained_width / constrained_height > aspect_ratio:
constrained_width = max(int(constrained_height * aspect_ratio), 1)
if crop_if_required and current_width > 0:
constrained_height = max(int(current_height / (current_width / max(constrained_width, 1))), 1)
else:
constrained_height = max(int(constrained_width / aspect_ratio), 1)
if crop_if_required and current_height > 0:
constrained_width = max(int(current_width / (current_height / max(constrained_height, 1))), 1)
# ========== Check Point 6: Final Verification ==========
# Final check: ensure size is positive
constrained_width = max(int(constrained_width), 1)
constrained_height = max(int(constrained_height), 1)
# ========== Execute PIL Resize ==========
resized_image = img.resize((constrained_width, constrained_height), Image.LANCZOS)
if crop_if_required and (constrained_width > max_width or constrained_height > max_height):
left = max((constrained_width - max_width) // 2, 0)
top = max((constrained_height - max_height) // 2, 0)
right = min(constrained_width, max_width) + left
bottom = min(constrained_height, max_height) + top
resized_image = resized_image.crop((left, top, right, bottom))
resized_image = np.array(resized_image).astype(np.float32) / 255.0
resized_image = torch.from_numpy(resized_image)[None,]
results.append(resized_image)
return (results,)Detailed Explanation of 6 Check Points
1️⃣ Check Point 1: Image Size Zero Check (Lines 37-41)
if current_height <= 0:
current_height = 1
if current_width <= 0:
current_width = 1What it does:
If the image height retrieved from PIL is 0 or negative, force it to 1
Why it is needed:
The image file might be corrupted
Prevents division by zero
Used in `aspect_ratio = current_width / current_height`
Example:
Original image: current_height = 0
After fix: current_height = 1 ← Avoids zero division2️⃣ Check Point 2: Parameter Zero Check (Lines 45-49)
if max_width <= 0:
max_width = current_width
if max_height <= 0:
max_height = current_heightWhat it does:
If a user sets `max_width=0` or `max_height=0`, set the upper limit to the original image size
Why it is needed:
Users might accidentally set zero values
Prevents `min(..., max_width)` from becoming 0
Concrete Example:
User sets: max_height = 0
Before fix (calculation):
constrained_height = min(max(768, 0), 0)
= min(768, 0)
= 0 ← Fails!
After fix:
max_height = 768 (original size)
constrained_height = min(max(768, 0), 768)
= min(768, 768)
= 768 ✓ Success3️⃣ Check Point 3: Initial Calculation (Lines 51-52)
constrained_width = min(max(current_width, min_width), max_width)
constrained_height = min(max(current_height, min_height), max_height)What it does:
Apply both minimum and maximum value constraints simultaneously
`max(...)` ensures at least the minimum value
`min(...)` ensures at most the maximum value
Calculation Logic:
constrained_height = min(max(current_height, min_height), max_height)
= min( apply minimum constraint, apply maximum constraint )
Example: current_height=768, min_height=0, max_height=1024
= min(max(768, 0), 1024)
= min(768, 1024)
= 768 ✓Note: At this point, values might still become 0
4️⃣ Check Point 4: Zero Prevention After Calculation (Lines 54-58)
if constrained_width <= 0:
constrained_width = 1
if constrained_height <= 0:
constrained_height = 1What it does:
After Check Point 3 calculation, if a value becomes 0 or negative, force it to 1
Why it is needed:
Even after Check Point 2's fix, Check Point 3's result might not be safe
Double-check strategy
Example:
Check Point 2 fix: max_height = 768
Check Point 3: constrained_height = min(768, 768) = 768
Check Point 4: 768 > 0, so no change ✓
However, other calculation paths might yield 0, so we need this safeguard5️⃣ Check Point 5: Aspect Ratio Adjustment (Lines 60-67)
if constrained_width / constrained_height > aspect_ratio:
constrained_width = max(int(constrained_height * aspect_ratio), 1)
if crop_if_required and current_width > 0:
constrained_height = max(int(current_height / (current_width / max(constrained_width, 1))), 1)
else:
constrained_height = max(int(constrained_width / aspect_ratio), 1)
if crop_if_required and current_height > 0:
constrained_width = max(int(current_width / (current_height / max(constrained_height, 1))), 1)What it does:
Adjust width or height while maintaining the aspect ratio (width-to-height ratio)
Ensure calculated results are at least 1 by using `max(..., 1)`
Logic:
If width is too large compared to height → Adjust width based on height
If height is too large compared to width → Adjust height based on width
Important: No division by zero occurs at this point (guaranteed by Check Point 4)
6️⃣ Check Point 6: Final Verification (Lines 69-71)
constrained_width = max(int(constrained_width), 1)
constrained_height = max(int(constrained_height), 1)
resized_image = img.resize((constrained_width, constrained_height), Image.LANCZOS)What it does:
Final verification after all calculation steps
Convert floating-point numbers to integers using `int()`
Ensure values are at least 1 by using `max(..., 1)`
Triple-check strategy
Example:
Calculation result: constrained_width = 0.5
Step 1: int(0.5) = 0
Step 2: max(0, 1) = 1 ✓
Calculation result: constrained_height = 0.0
Step 1: int(0.0) = 0
Step 2: max(0, 1) = 1 ✓This is where `img.resize()` is called:
PIL accepts only positive integers
Only values of 1 or higher pass through all checks
Fix Summary Flow Diagram
Input: max_height=0
↓
[Check Point 1] Verify image size (if 0, set to 1)
↓
[Check Point 2] max_height=0 → Fix to max_height = current_height ✅
↓
[Check Point 3] Calculate constraints
↓
[Check Point 4] Result is 0? → Fix to 1
↓
[Check Point 5] Adjust aspect ratio (guarantee minimum 1)
↓
[Check Point 6] Final check (int conversion + max(..., 1))
↓
PIL.resize((1 or more, 1 or more)) → Success! ✅Before and After Comparison
| Item | Before Fix | After Fix |
|------|-----------|-----------|
| Zero Division Prevention | None | 6 check points |
| max_width=0 Handling | None | Check Point 2 fix |
| Post-Calculation Check | None | Check Point 4 rechecks |
| PIL Pre-Call Check | None | Check Point 6 final verification |
| Error: ZeroDivisionError | Occurs | None (safe) |
| Error: ValueError height/width | Occurs | None (safe) |
Mathematical Guarantee
After all 6 check points, the following is absolutely guaranteed:
1 ≤ constrained_width < ∞ (positive integer)
1 ≤ constrained_height < ∞ (positive integer)Therefore:
`constrained_width / constrained_height` is always valid (never divides by zero)
`PIL.Image.resize((constrained_width, constrained_height))` will always succeed
No exceptions will be raised
Why Multiple Check Points Are Necessary
Each check point handles a different failure scenario:
Check Point 1: Handles corrupted image files
Check Point 2: Handles user input errors (0 values)
Check Point 3: Calculates constrained dimensions
Check Point 4: Catches unexpected zero values from Check Point 3
Check Point 5: Maintains aspect ratio with guaranteed minimums
Check Point 6: Final guarantee before passing to PIL
Redundancy is safety. Each check point is independent and acts as a fallback for the others.
Code Execution Example with max_height=0
Input parameters:
current_width = 1024
current_height = 768
max_width = 1024
max_height = 0
min_width = 0
min_height = 0
Step 1: Check image size
current_height = 768 > 0 → No change
current_width = 1024 > 0 → No change
aspect_ratio = 1024 / 768 = 1.333
Step 2: Check parameters
max_height = 0 ≤ 0 → Fix to current_height = 768 ✅
Step 3: Calculate constraints
constrained_width = min(max(1024, 0), 1024) = 1024
constrained_height = min(max(768, 0), 768) = 768
Step 4: Check after calculation
constrained_width = 1024 > 0 → No change
constrained_height = 768 > 0 → No change
Step 5: Aspect ratio adjustment
1024 / 768 = 1.333 vs 1.333 → Equal, use else branch
constrained_height = max(int(1024 / 1.333), 1) = max(768, 1) = 768
Step 6: Final check
constrained_width = max(int(1024), 1) = 1024 ✓
constrained_height = max(int(768), 1) = 768 ✓
PIL.resize((1024, 768)) → SUCCESS! ✓This fix ensures absolute safety at every calculation step!
\py\constrain_image.py
---
## Errors That Occurred
### Error 1: `ZeroDivisionError: division by zero`
```python
if constrained_width / constrained_height > aspect_ratio:
~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
# constrained_height is 0, causing division by zero failureError 2: `ValueError: height and width must be > 0`
resized_image = img.resize((constrained_width, constrained_height), Image.LANCZOS)
# PIL does not accept dimensions of 0 or lessRoot Cause Analysis
When a user sets `max_height=0` or `max_width=0`:
1. User sets max_height = 0
↓
2. constrained_height = min(max(current_height, min_height), max_height)
= min(max(768, 0), 0)
= min(768, 0)
= 0 ← Becomes zero!
↓
3. aspect_ratio = current_width / current_height
= 1024 / 0 ← Division by zero error!And if this somehow passes:
4. resized_image = img.resize((1, 0))
← PIL raises "height must be > 0" error and failsComplete Fixed Code
Fixed Code (Lines 28-86):
def constrain_image(self, images, max_width, max_height, min_width, min_height, crop_if_required):
crop_if_required = crop_if_required == "yes"
results = []
for image in images:
i = 255. * image.cpu().numpy()
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)).convert("RGB")
current_width, current_height = img.size
# ========== Check Point 1: Image Size Zero Check ==========
# Zero value check (set minimum value to 1)
if current_height <= 0:
current_height = 1
if current_width <= 0:
current_width = 1
aspect_ratio = current_width / current_height # ✓ Safe
# ========== Check Point 2: Parameter Zero Check ==========
# If max_width or max_height is 0, use the original size
if max_width <= 0:
max_width = current_width
if max_height <= 0:
max_height = current_height
# ========== Check Point 3: Initial Calculation ==========
constrained_width = min(max(current_width, min_width), max_width)
constrained_height = min(max(current_height, min_height), max_height)
# ========== Check Point 4: Zero Prevention After Calculation ==========
# Prevent zero after calculation
if constrained_width <= 0:
constrained_width = 1
if constrained_height <= 0:
constrained_height = 1
# ========== Check Point 5: Aspect Ratio Adjustment ==========
if constrained_width / constrained_height > aspect_ratio:
constrained_width = max(int(constrained_height * aspect_ratio), 1)
if crop_if_required and current_width > 0:
constrained_height = max(int(current_height / (current_width / max(constrained_width, 1))), 1)
else:
constrained_height = max(int(constrained_width / aspect_ratio), 1)
if crop_if_required and current_height > 0:
constrained_width = max(int(current_width / (current_height / max(constrained_height, 1))), 1)
# ========== Check Point 6: Final Verification ==========
# Final check: ensure size is positive
constrained_width = max(int(constrained_width), 1)
constrained_height = max(int(constrained_height), 1)
# ========== Execute PIL Resize ==========
resized_image = img.resize((constrained_width, constrained_height), Image.LANCZOS)
if crop_if_required and (constrained_width > max_width or constrained_height > max_height):
left = max((constrained_width - max_width) // 2, 0)
top = max((constrained_height - max_height) // 2, 0)
right = min(constrained_width, max_width) + left
bottom = min(constrained_height, max_height) + top
resized_image = resized_image.crop((left, top, right, bottom))
resized_image = np.array(resized_image).astype(np.float32) / 255.0
resized_image = torch.from_numpy(resized_image)[None,]
results.append(resized_image)
return (results,)Detailed Explanation of 6 Check Points
1️⃣ Check Point 1: Image Size Zero Check (Lines 37-41)
if current_height <= 0:
current_height = 1
if current_width <= 0:
current_width = 1What it does:
If the image height retrieved from PIL is 0 or negative, force it to 1
Why it is needed:
The image file might be corrupted
Prevents division by zero
Used in `aspect_ratio = current_width / current_height`
Example:
Original image: current_height = 0
After fix: current_height = 1 ← Avoids zero division2️⃣ Check Point 2: Parameter Zero Check (Lines 45-49)
if max_width <= 0:
max_width = current_width
if max_height <= 0:
max_height = current_heightWhat it does:
If a user sets `max_width=0` or `max_height=0`, set the upper limit to the original image size
Why it is needed:
Users might accidentally set zero values
Prevents `min(..., max_width)` from becoming 0
Concrete Example:
User sets: max_height = 0
Before fix (calculation):
constrained_height = min(max(768, 0), 0)
= min(768, 0)
= 0 ← Fails!
After fix:
max_height = 768 (original size)
constrained_height = min(max(768, 0), 768)
= min(768, 768)
= 768 ✓ Success3️⃣ Check Point 3: Initial Calculation (Lines 51-52)
constrained_width = min(max(current_width, min_width), max_width)
constrained_height = min(max(current_height, min_height), max_height)What it does:
Apply both minimum and maximum value constraints simultaneously
`max(...)` ensures at least the minimum value
`min(...)` ensures at most the maximum value
Calculation Logic:
constrained_height = min(max(current_height, min_height), max_height)
= min( apply minimum constraint, apply maximum constraint )
Example: current_height=768, min_height=0, max_height=1024
= min(max(768, 0), 1024)
= min(768, 1024)
= 768 ✓Note: At this point, values might still become 0
4️⃣ Check Point 4: Zero Prevention After Calculation (Lines 54-58)
if constrained_width <= 0:
constrained_width = 1
if constrained_height <= 0:
constrained_height = 1What it does:
After Check Point 3 calculation, if a value becomes 0 or negative, force it to 1
Why it is needed:
Even after Check Point 2's fix, Check Point 3's result might not be safe
Double-check strategy
Example:
Check Point 2 fix: max_height = 768
Check Point 3: constrained_height = min(768, 768) = 768
Check Point 4: 768 > 0, so no change ✓
However, other calculation paths might yield 0, so we need this safeguard5️⃣ Check Point 5: Aspect Ratio Adjustment (Lines 60-67)
if constrained_width / constrained_height > aspect_ratio:
constrained_width = max(int(constrained_height * aspect_ratio), 1)
if crop_if_required and current_width > 0:
constrained_height = max(int(current_height / (current_width / max(constrained_width, 1))), 1)
else:
constrained_height = max(int(constrained_width / aspect_ratio), 1)
if crop_if_required and current_height > 0:
constrained_width = max(int(current_width / (current_height / max(constrained_height, 1))), 1)What it does:
Adjust width or height while maintaining the aspect ratio (width-to-height ratio)
Ensure calculated results are at least 1 by using `max(..., 1)`
Logic:
If width is too large compared to height → Adjust width based on height
If height is too large compared to width → Adjust height based on width
Important: No division by zero occurs at this point (guaranteed by Check Point 4)
6️⃣ Check Point 6: Final Verification (Lines 69-71)
constrained_width = max(int(constrained_width), 1)
constrained_height = max(int(constrained_height), 1)
resized_image = img.resize((constrained_width, constrained_height), Image.LANCZOS)What it does:
Final verification after all calculation steps
Convert floating-point numbers to integers using `int()`
Ensure values are at least 1 by using `max(..., 1)`
Triple-check strategy
Example:
Calculation result: constrained_width = 0.5
Step 1: int(0.5) = 0
Step 2: max(0, 1) = 1 ✓
Calculation result: constrained_height = 0.0
Step 1: int(0.0) = 0
Step 2: max(0, 1) = 1 ✓This is where `img.resize()` is called:
PIL accepts only positive integers
Only values of 1 or higher pass through all checks
Fix Summary Flow Diagram
Input: max_height=0
↓
[Check Point 1] Verify image size (if 0, set to 1)
↓
[Check Point 2] max_height=0 → Fix to max_height = current_height ✅
↓
[Check Point 3] Calculate constraints
↓
[Check Point 4] Result is 0? → Fix to 1
↓
[Check Point 5] Adjust aspect ratio (guarantee minimum 1)
↓
[Check Point 6] Final check (int conversion + max(..., 1))
↓
PIL.resize((1 or more, 1 or more)) → Success! ✅Before and After Comparison
| Item | Before Fix | After Fix |
|------|-----------|-----------|
| Zero Division Prevention | None | 6 check points |
| max_width=0 Handling | None | Check Point 2 fix |
| Post-Calculation Check | None | Check Point 4 rechecks |
| PIL Pre-Call Check | None | Check Point 6 final verification |
| Error: ZeroDivisionError | Occurs | None (safe) |
| Error: ValueError height/width | Occurs | None (safe) |
Mathematical Guarantee
After all 6 check points, the following is absolutely guaranteed:
1 ≤ constrained_width < ∞ (positive integer)
1 ≤ constrained_height < ∞ (positive integer)Therefore:
`constrained_width / constrained_height` is always valid (never divides by zero)
`PIL.Image.resize((constrained_width, constrained_height))` will always succeed
No exceptions will be raised
Why Multiple Check Points Are Necessary
Each check point handles a different failure scenario:
Check Point 1: Handles corrupted image files
Check Point 2: Handles user input errors (0 values)
Check Point 3: Calculates constrained dimensions
Check Point 4: Catches unexpected zero values from Check Point 3
Check Point 5: Maintains aspect ratio with guaranteed minimums
Check Point 6: Final guarantee before passing to PIL
Redundancy is safety. Each check point is independent and acts as a fallback for the others.
Code Execution Example with max_height=0
Input parameters:
current_width = 1024
current_height = 768
max_width = 1024
max_height = 0
min_width = 0
min_height = 0
Step 1: Check image size
current_height = 768 > 0 → No change
current_width = 1024 > 0 → No change
aspect_ratio = 1024 / 768 = 1.333
Step 2: Check parameters
max_height = 0 ≤ 0 → Fix to current_height = 768 ✅
Step 3: Calculate constraints
constrained_width = min(max(1024, 0), 1024) = 1024
constrained_height = min(max(768, 0), 768) = 768
Step 4: Check after calculation
constrained_width = 1024 > 0 → No change
constrained_height = 768 > 0 → No change
Step 5: Aspect ratio adjustment
1024 / 768 = 1.333 vs 1.333 → Equal, use else branch
constrained_height = max(int(1024 / 1.333), 1) = max(768, 1) = 768
Step 6: Final check
constrained_width = max(int(1024), 1) = 1024 ✓
constrained_height = max(int(768), 1) = 768 ✓
PIL.resize((1024, 768)) → SUCCESS! ✓This fix ensures absolute safety at every calculation step!
