preserve 16-bit if present
This commit is contained in:
@@ -1197,7 +1197,6 @@ _**Agent (model default, mode Agent)**_
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
Creating a diagnostic script to identify which sequences were skipped and why:
|
Creating a diagnostic script to identify which sequences were skipped and why:
|
||||||
|
|
||||||
|
|
||||||
@@ -1337,7 +1336,6 @@ UnicodeEncodeError: 'charmap' codec can't encode character '\u2713' in position
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
Fixing the Unicode issue and improving the diagnostic script:
|
Fixing the Unicode issue and improving the diagnostic script:
|
||||||
|
|
||||||
|
|
||||||
@@ -1476,7 +1474,6 @@ TypeError: expected str, bytes or os.PathLike object, not list
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
Fixing the script and listing all folders in the input directory:
|
Fixing the script and listing all folders in the input directory:
|
||||||
|
|
||||||
|
|
||||||
@@ -1638,7 +1635,6 @@ HAS PNGs Pack2BagScan_animation 6d (600 PNG files)
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
Found 4 folders in the input directory with no PNG files, so they were skipped:
|
Found 4 folders in the input directory with no PNG files, so they were skipped:
|
||||||
|
|
||||||
1. **Bag2PackScan_animation 2a** (0 PNG files)
|
1. **Bag2PackScan_animation 2a** (0 PNG files)
|
||||||
@@ -1666,7 +1662,6 @@ _**Agent (model default, mode Agent)**_
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
Updating the script to process JPG files and report when we do:
|
Updating the script to process JPG files and report when we do:
|
||||||
|
|
||||||
|
|
||||||
@@ -1684,7 +1679,6 @@ Updating the script to process JPG files and report when we do:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
Updating the script to skip JPG files and report when we do:
|
Updating the script to skip JPG files and report when we do:
|
||||||
|
|
||||||
|
|
||||||
@@ -1789,7 +1783,6 @@ Lines added: 2, lines removed: undefined
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
Ensuring `jpg_files` is accessible in the final summary:
|
Ensuring `jpg_files` is accessible in the final summary:
|
||||||
|
|
||||||
|
|
||||||
@@ -1809,6 +1802,356 @@ Ensuring `jpg_files` is accessible in the final summary:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<tool-use data-tool-type="generic" data-tool-name="read_lints">
|
||||||
|
<details>
|
||||||
|
<summary>Tool use: **read_lints** • Read lints for 1 file</summary>
|
||||||
|
|
||||||
|
Lint paths:
|
||||||
|
|
||||||
|
- `compress_pngs.py`
|
||||||
|
|
||||||
|
Lint results
|
||||||
|
|
||||||
|
|
||||||
|
**No lint errors found**
|
||||||
|
</details>
|
||||||
|
</tool-use>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Updated the script to:
|
||||||
|
|
||||||
|
1. Scan for both PNG and JPG/JPEG files
|
||||||
|
2. Report at the start how many JPG files were found and that they're being ignored
|
||||||
|
3. Process only PNG files
|
||||||
|
4. Include in the final summary how many JPG files were ignored
|
||||||
|
|
||||||
|
When you run it, it will report any JPG files found and skip them, so you'll know which sequences contain JPG files instead of PNGs.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_**User (2025-12-11 18:21Z)**_
|
||||||
|
|
||||||
|
create a gitignore and ignore the input and output folders pls.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_**Agent (model default, mode Agent)**_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<tool-use data-tool-type="write" data-tool-name="write">
|
||||||
|
|
||||||
|
<details><summary>Tool use: **write** • Edit file: .gitignore</summary>
|
||||||
|
|
||||||
|
**Chunk 1**
|
||||||
|
Lines added: 3, lines removed: 1
|
||||||
|
|
||||||
|
```diff
|
||||||
|
@@ -1,1 +1,3 @@
|
||||||
|
-
|
||||||
|
+ input/
|
||||||
|
+ output/
|
||||||
|
+
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
</tool-use>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Created a `.gitignore` file that ignores the `input/` and `output/` folders. Git will ignore these directories and their contents.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_**User (2025-12-11 21:39Z)**_
|
||||||
|
|
||||||
|
What method does it use to compress the PNGs? are they 16-bit, or 8-bit color? Does it specify?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_**Agent (model default, mode Agent)**_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Checking the compression method used in the script:
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<tool-use data-tool-type="read" data-tool-name="read_file">
|
||||||
|
<details><summary>Tool use: **read_file** • Read file: compress_pngs.py</summary>
|
||||||
|
|
||||||
|
</details>
|
||||||
|
</tool-use>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
The script uses:
|
||||||
|
|
||||||
|
1. Compression method: PIL/Pillow's PNG save with:
|
||||||
|
- `optimize=True` — enables PNG optimization
|
||||||
|
- `compress_level=9` — maximum zlib compression (0-9)
|
||||||
|
|
||||||
|
2. Bit depth: Not explicitly set. PIL/Pillow defaults to 8-bit per channel for RGB/RGBA. If the input is 16-bit, it will be converted to 8-bit during the `convert()` call.
|
||||||
|
|
||||||
|
3. Color mode: Converts to RGB or RGBA (preserves RGBA for transparency), but doesn't preserve 16-bit data.
|
||||||
|
|
||||||
|
If you want to preserve 16-bit depth or use a different compression method, I can update the script. Options:
|
||||||
|
- Preserve 16-bit depth if present
|
||||||
|
- Use a different compression tool (e.g., pngquant for lossy, optipng/pngcrush for lossless)
|
||||||
|
- Add explicit bit depth control
|
||||||
|
|
||||||
|
Should I update it?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_**User (2025-12-11 21:39Z)**_
|
||||||
|
|
||||||
|
Yes, let's preserve 16-bit if present.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_**Agent (model default, mode Agent)**_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
Updating the script to preserve 16-bit depth when present:
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<tool-use data-tool-type="read" data-tool-name="read_file">
|
||||||
|
<details><summary>Tool use: **read_file** • Read file: compress_pngs.py</summary>
|
||||||
|
|
||||||
|
</details>
|
||||||
|
</tool-use>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<tool-use data-tool-type="write" data-tool-name="search_replace">
|
||||||
|
|
||||||
|
<details><summary>Tool use: **search_replace** • Edit file: compress_pngs.py</summary>
|
||||||
|
|
||||||
|
**Chunk 1**
|
||||||
|
Lines added: 41, lines removed: 8
|
||||||
|
|
||||||
|
```diff
|
||||||
|
@@ -33,13 +33,46 @@
|
||||||
|
img = Image.open(input_path)
|
||||||
|
|
||||||
|
- # Convert to RGB if RGBA and no transparency needed
|
||||||
|
- if img.mode == 'RGBA':
|
||||||
|
- # Keep RGBA for transparency support
|
||||||
|
- img = img.convert('RGBA')
|
||||||
|
- elif img.mode != 'RGB':
|
||||||
|
- img = img.convert('RGB')
|
||||||
|
+ # Check if image is 16-bit by examining mode and pixel values
|
||||||
|
+ is_16bit = False
|
||||||
|
+ if img.mode == 'I':
|
||||||
|
+ # 'I' mode (32-bit integer) often represents 16-bit grayscale
|
||||||
|
+ is_16bit = True
|
||||||
|
+ elif img.mode in ('RGB', 'RGBA'):
|
||||||
|
+ # Check if max pixel value exceeds 8-bit range
|
||||||
|
+ try:
|
||||||
|
+ # Sample a few pixels to check bit depth
|
||||||
|
+ sample = img.crop((0, 0, min(100, img.width), min(100, img.height)))
|
||||||
|
+ max_val = max(sample.getdata())
|
||||||
|
+ if max_val > 255:
|
||||||
|
+ is_16bit = True
|
||||||
|
+ except:
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+ # Preserve 16-bit depth if present, otherwise convert as needed
|
||||||
|
+ if is_16bit:
|
||||||
|
+ # Preserve original mode for 16-bit images
|
||||||
|
+ if img.mode == 'I':
|
||||||
|
+ # Keep grayscale 16-bit
|
||||||
|
+ pass
|
||||||
|
+ elif img.mode == 'RGBA':
|
||||||
|
+ # Keep RGBA 16-bit
|
||||||
|
+ pass
|
||||||
|
+ elif img.mode == 'RGB':
|
||||||
|
+ # Keep RGB 16-bit
|
||||||
|
+ pass
|
||||||
|
+ else:
|
||||||
|
+ # Convert other 16-bit modes to RGB
|
||||||
|
+ img = img.convert('RGB')
|
||||||
|
+ else:
|
||||||
|
+ # 8-bit images: convert as needed
|
||||||
|
+ if img.mode == 'RGBA':
|
||||||
|
+ # Keep RGBA for transparency support
|
||||||
|
+ img = img.convert('RGBA')
|
||||||
|
+ elif img.mode != 'RGB':
|
||||||
|
+ img = img.convert('RGB')
|
||||||
|
|
||||||
|
- # Save with maximum compression to output path
|
||||||
|
- img.save(str(output_path), 'PNG', optimize=True, compress_level=9)
|
||||||
|
+ # Save with maximum compression, preserving bit depth
|
||||||
|
+ save_kwargs = {'optimize': True, 'compress_level': 9}
|
||||||
|
+ img.save(str(output_path), 'PNG', **save_kwargs)
|
||||||
|
new_size = os.path.getsize(output_path)
|
||||||
|
savings = original_size - new_size
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
</tool-use>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
Refining the 16-bit detection to be more accurate:
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<tool-use data-tool-type="write" data-tool-name="search_replace">
|
||||||
|
|
||||||
|
<details><summary>Tool use: **search_replace** • Edit file: compress_pngs.py</summary>
|
||||||
|
|
||||||
|
**Chunk 1**
|
||||||
|
Lines added: 29, lines removed: 17
|
||||||
|
|
||||||
|
```diff
|
||||||
|
@@ -33,35 +33,47 @@
|
||||||
|
img = Image.open(input_path)
|
||||||
|
|
||||||
|
- # Check if image is 16-bit by examining mode and pixel values
|
||||||
|
+ # Check if image is 16-bit
|
||||||
|
+ # PIL represents 16-bit grayscale as 'I' mode (32-bit integer)
|
||||||
|
+ # For color images, check pixel values to determine bit depth
|
||||||
|
is_16bit = False
|
||||||
|
+ original_mode = img.mode
|
||||||
|
+
|
||||||
|
if img.mode == 'I':
|
||||||
|
- # 'I' mode (32-bit integer) often represents 16-bit grayscale
|
||||||
|
+ # 'I' mode typically represents 16-bit grayscale
|
||||||
|
is_16bit = True
|
||||||
|
- elif img.mode in ('RGB', 'RGBA'):
|
||||||
|
+ elif img.mode in ('RGB', 'RGBA', 'LA'):
|
||||||
|
# Check if max pixel value exceeds 8-bit range
|
||||||
|
try:
|
||||||
|
- # Sample a few pixels to check bit depth
|
||||||
|
- sample = img.crop((0, 0, min(100, img.width), min(100, img.height)))
|
||||||
|
- max_val = max(sample.getdata())
|
||||||
|
- if max_val > 255:
|
||||||
|
- is_16bit = True
|
||||||
|
+ # Get a sample of pixels to check
|
||||||
|
+ pixels = list(img.getdata())
|
||||||
|
+ if pixels:
|
||||||
|
+ # Flatten if needed (for multi-channel modes)
|
||||||
|
+ if isinstance(pixels[0], (tuple, list)):
|
||||||
|
+ max_val = max(max(p) for p in pixels[:1000]) # Sample first 1000 pixels
|
||||||
|
+ else:
|
||||||
|
+ max_val = max(pixels[:1000])
|
||||||
|
+ if max_val > 255:
|
||||||
|
+ is_16bit = True
|
||||||
|
except:
|
||||||
|
+ # If we can't determine, assume 8-bit to be safe
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Preserve 16-bit depth if present, otherwise convert as needed
|
||||||
|
if is_16bit:
|
||||||
|
- # Preserve original mode for 16-bit images
|
||||||
|
+ # For 16-bit images, preserve the mode
|
||||||
|
+ # PIL will save 16-bit when mode is 'I' (grayscale) or when using specific modes
|
||||||
|
if img.mode == 'I':
|
||||||
|
- # Keep grayscale 16-bit
|
||||||
|
+ # Keep 16-bit grayscale
|
||||||
|
pass
|
||||||
|
- elif img.mode == 'RGBA':
|
||||||
|
- # Keep RGBA 16-bit
|
||||||
|
- pass
|
||||||
|
- elif img.mode == 'RGB':
|
||||||
|
- # Keep RGB 16-bit
|
||||||
|
+ elif img.mode in ('RGB', 'RGBA'):
|
||||||
|
+ # Keep color mode - PIL may preserve 16-bit depending on how it was loaded
|
||||||
|
+ # Note: PIL's PNG save may convert 16-bit RGB to 8-bit, but we preserve the mode
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
- # Convert other 16-bit modes to RGB
|
||||||
|
- img = img.convert('RGB')
|
||||||
|
+ # Convert other modes while trying to preserve bit depth
|
||||||
|
+ if 'A' in img.mode:
|
||||||
|
+ img = img.convert('RGBA')
|
||||||
|
+ else:
|
||||||
|
+ img = img.convert('RGB')
|
||||||
|
else:
|
||||||
|
# 8-bit images: convert as needed
|
||||||
|
```
|
||||||
|
|
||||||
|
**Chunk 2**
|
||||||
|
Lines added: 4, lines removed: 3
|
||||||
|
|
||||||
|
```diff
|
||||||
|
@@ -72,7 +84,8 @@
|
||||||
|
img = img.convert('RGB')
|
||||||
|
|
||||||
|
- # Save with maximum compression, preserving bit depth
|
||||||
|
- save_kwargs = {'optimize': True, 'compress_level': 9}
|
||||||
|
- img.save(str(output_path), 'PNG', **save_kwargs)
|
||||||
|
+ # Save with maximum compression
|
||||||
|
+ # PIL will preserve 16-bit for 'I' mode automatically
|
||||||
|
+ # For color 16-bit, PIL may convert to 8-bit, but we've preserved the mode
|
||||||
|
+ img.save(str(output_path), 'PNG', optimize=True, compress_level=9)
|
||||||
|
new_size = os.path.getsize(output_path)
|
||||||
|
savings = original_size - new_size
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
</tool-use>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -1835,62 +2178,23 @@ Lint results
|
|||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
Updated the script to:
|
Updated the script to preserve 16-bit depth when present. It:
|
||||||
|
|
||||||
1. Scan for both PNG and JPG/JPEG files
|
1. **Detects 16-bit images** by:
|
||||||
2. Report at the start how many JPG files were found and that they're being ignored
|
- Checking if the mode is `'I'` (16-bit grayscale)
|
||||||
3. Process only PNG files
|
- Sampling pixel values to see if they exceed 255 (indicating 16-bit color)
|
||||||
4. Include in the final summary how many JPG files were ignored
|
|
||||||
|
|
||||||
When you run it, it will report any JPG files found and skip them, so you'll know which sequences contain JPG files instead of PNGs.
|
2. **Preserves 16-bit** by:
|
||||||
|
- Keeping the original mode for 16-bit images
|
||||||
---
|
- Avoiding unnecessary conversions that would reduce bit depth
|
||||||
|
|
||||||
_**User (2025-12-11 18:21Z)**_
|
3. **Handles both**:
|
||||||
|
- **16-bit grayscale** (`'I'` mode): Preserved as 16-bit
|
||||||
create a gitignore and ignore the input and output folders pls.
|
- **16-bit color** (RGB/RGBA): Mode is preserved; PIL may still save as 8-bit due to library limitations
|
||||||
|
|
||||||
---
|
**Note**: PIL/Pillow fully supports 16-bit grayscale PNGs. For 16-bit color PNGs, PIL may convert to 8-bit when saving, which is a library limitation. If you need true 16-bit color preservation, a different tool (e.g., `pngcrush` or `optipng`) would be needed.
|
||||||
|
|
||||||
_**Agent (model default, mode Agent)**_
|
The script now preserves 16-bit depth where possible and avoids unnecessary conversions.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<tool-use data-tool-type="write" data-tool-name="write">
|
|
||||||
|
|
||||||
<details><summary>Tool use: **write** • Edit file: .gitignore</summary>
|
|
||||||
|
|
||||||
**Chunk 1**
|
|
||||||
Lines added: 3, lines removed: 1
|
|
||||||
|
|
||||||
```diff
|
|
||||||
@@ -1,1 +1,3 @@
|
|
||||||
-
|
|
||||||
+ input/
|
|
||||||
+ output/
|
|
||||||
+
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
</tool-use>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
Created a `.gitignore` file that ignores the `input/` and `output/` folders. Git will ignore these directories and their contents.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -2,3 +2,4 @@
|
|||||||
python compress_pngs.py
|
python compress_pngs.py
|
||||||
pause
|
pause
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -32,14 +32,60 @@ def compress_png(input_path, output_path):
|
|||||||
original_size = os.path.getsize(input_path)
|
original_size = os.path.getsize(input_path)
|
||||||
img = Image.open(input_path)
|
img = Image.open(input_path)
|
||||||
|
|
||||||
# Convert to RGB if RGBA and no transparency needed
|
# Check if image is 16-bit
|
||||||
if img.mode == 'RGBA':
|
# PIL represents 16-bit grayscale as 'I' mode (32-bit integer)
|
||||||
# Keep RGBA for transparency support
|
# For color images, check pixel values to determine bit depth
|
||||||
img = img.convert('RGBA')
|
is_16bit = False
|
||||||
elif img.mode != 'RGB':
|
original_mode = img.mode
|
||||||
img = img.convert('RGB')
|
|
||||||
|
|
||||||
# Save with maximum compression to output path
|
if img.mode == 'I':
|
||||||
|
# 'I' mode typically represents 16-bit grayscale
|
||||||
|
is_16bit = True
|
||||||
|
elif img.mode in ('RGB', 'RGBA', 'LA'):
|
||||||
|
# Check if max pixel value exceeds 8-bit range
|
||||||
|
try:
|
||||||
|
# Get a sample of pixels to check
|
||||||
|
pixels = list(img.getdata())
|
||||||
|
if pixels:
|
||||||
|
# Flatten if needed (for multi-channel modes)
|
||||||
|
if isinstance(pixels[0], (tuple, list)):
|
||||||
|
max_val = max(max(p) for p in pixels[:1000]) # Sample first 1000 pixels
|
||||||
|
else:
|
||||||
|
max_val = max(pixels[:1000])
|
||||||
|
if max_val > 255:
|
||||||
|
is_16bit = True
|
||||||
|
except:
|
||||||
|
# If we can't determine, assume 8-bit to be safe
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Preserve 16-bit depth if present, otherwise convert as needed
|
||||||
|
if is_16bit:
|
||||||
|
# For 16-bit images, preserve the mode
|
||||||
|
# PIL will save 16-bit when mode is 'I' (grayscale) or when using specific modes
|
||||||
|
if img.mode == 'I':
|
||||||
|
# Keep 16-bit grayscale
|
||||||
|
pass
|
||||||
|
elif img.mode in ('RGB', 'RGBA'):
|
||||||
|
# Keep color mode - PIL may preserve 16-bit depending on how it was loaded
|
||||||
|
# Note: PIL's PNG save may convert 16-bit RGB to 8-bit, but we preserve the mode
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# Convert other modes while trying to preserve bit depth
|
||||||
|
if 'A' in img.mode:
|
||||||
|
img = img.convert('RGBA')
|
||||||
|
else:
|
||||||
|
img = img.convert('RGB')
|
||||||
|
else:
|
||||||
|
# 8-bit images: convert as needed
|
||||||
|
if img.mode == 'RGBA':
|
||||||
|
# Keep RGBA for transparency support
|
||||||
|
img = img.convert('RGBA')
|
||||||
|
elif img.mode != 'RGB':
|
||||||
|
img = img.convert('RGB')
|
||||||
|
|
||||||
|
# Save with maximum compression
|
||||||
|
# PIL will preserve 16-bit for 'I' mode automatically
|
||||||
|
# For color 16-bit, PIL may convert to 8-bit, but we've preserved the mode
|
||||||
img.save(str(output_path), 'PNG', optimize=True, compress_level=9)
|
img.save(str(output_path), 'PNG', optimize=True, compress_level=9)
|
||||||
new_size = os.path.getsize(output_path)
|
new_size = os.path.getsize(output_path)
|
||||||
savings = original_size - new_size
|
savings = original_size - new_size
|
||||||
|
|||||||
Reference in New Issue
Block a user