-
Notifications
You must be signed in to change notification settings - Fork 325
Adding Image Resizer Project #1804
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughAdds a new Tkinter-based Image Resizer GUI (with Pillow) and its README under Advanced_Projects/Image_resizer. Removes the reverse backdoor implementation by deleting Cybersecurity_Tools/Reverse_backdoor/backdoor.py. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant UI as Tkinter UI
participant App as ImageResizerApp
participant PIL as Pillow (PIL)
participant FS as File System
participant Msg as MessageBox
User->>UI: Click "Select Images"
UI->>App: _select_images()
App->>FS: Open file dialog
FS-->>App: Image paths
App-->>Msg: Show selection result
User->>UI: Enter width/height or scale
User->>UI: Click "Resize"
UI->>App: _resize_images()
App->>App: Validate inputs (paths, dims/scale)
loop For each selected image
App->>PIL: Open image
App->>App: Compute target size
App->>PIL: Resize (Lanczos)
App->>FS: Save with "_resized" suffix
end
App-->>Msg: Success or error message
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal). Please share your feedback with us on this Discord post. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ PR validation passed! Syncing labels and assignees from the linked issue... |
👋 Thank you for opening this pull request! We're excited to review your contribution. Please give us a moment, and we'll get back to you shortly! Feel free to join our community on Discord to discuss more! |
✅ PR validation passed! Syncing labels and assignees from the linked issue... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (7)
Advanced_Projects/Image_resizer/readme.md (3)
21-25
: Fix MD040 and correct project path in structure block.Add fenced-code language and reflect actual repo path to avoid confusion.
-``` +```text -image_resizer/ +Advanced_Projects/Image_resizer/ │── app.py # Full application (GUI + logic) └── output/ # Resized images are saved here -``` +```
42-52
: Add “how to run” step.Include commands to launch the app from the repo path.
## 📖 Usage - -1. Click **“📂 Select Images”** → choose one or more images. +Run the app: + +```bash +cd Advanced_Projects/Image_resizer +python app.py +``` + +1. Click **“📂 Select Images”** → choose one or more images.
55-61
: Clarify GIF support caveat (animated GIFs).Current implementation resizes a single frame; animations won’t be preserved.
- GIF + +- Note: Animated GIFs are not preserved (only the first frame is resized).
Advanced_Projects/Image_resizer/app.py (4)
55-56
: Broaden file dialog filter (case variants + All Files).Improves UX across platforms with case differences.
- filetypes=[("Image Files", "*.jpg *.jpeg *.png *.bmp *.gif")] + filetypes=[ + ("Image Files", "*.jpg *.jpeg *.png *.bmp *.gif *.JPG *.JPEG *.PNG *.BMP *.GIF"), + ("All Files", "*.*"), + ]
67-88
: Avoid blind except; validate inputs; handle per-image errors without aborting batch.Current try/except swallows all errors and stops the entire batch on the first failure.
def _resize_images(self): if not self.images: messagebox.showerror("Error", "No images selected.") return width = self.width_entry.get() height = self.height_entry.get() scale = self.scale_entry.get() - try: - width = int(width) if width else None - height = int(height) if height else None - scale = int(scale) if scale else None - - for img_path in self.images: - self._resize_single(img_path, width, height, scale) - - messagebox.showinfo("Success", "Images resized successfully!") - - except Exception as e: - messagebox.showerror("Error", str(e)) + # Parse + width = int(width) if width else None + height = int(height) if height else None + scale = int(scale) if scale else None + + # Basic validation + for name, val in (("Width", width), ("Height", height), ("Scale (%)", scale)): + if val is not None and val <= 0: + messagebox.showerror("Error", f"{name} must be > 0.") + return + + successes, failures = 0, 0 + errors = [] + for img_path in self.images: + try: + self._resize_single(img_path, width, height, scale) + successes += 1 + except (UnidentifiedImageError, OSError, ValueError) as e: + failures += 1 + errors.append(f"{os.path.basename(img_path)}: {e}") + + if successes: + messagebox.showinfo("Success", f"Resized {successes} of {len(self.images)} image(s).") + if failures: + preview = "\n".join(errors[:5]) + suffix = "\n..." if failures > 5 else "" + messagebox.showwarning("Some images failed", f"{preview}{suffix}")
89-107
: Close files reliably and respect EXIF orientation; use version-safe resample.Prevents file-handle leaks, rotated outputs, and Pillow version crashes.
- def _resize_single(self, input_path, width, height, scale): - img = Image.open(input_path) - orig_width, orig_height = img.size - - if scale: - width = int(orig_width * scale / 100) - height = int(orig_height * scale / 100) - elif width and height: - width, height = int(width), int(height) - else: - raise ValueError("Provide width/height or scale.") - - resized = img.resize((width, height), Image.Resampling.LANCZOS) - - os.makedirs(self.output_folder, exist_ok=True) - base, ext = os.path.splitext(os.path.basename(input_path)) - output_file = os.path.join(self.output_folder, f"{base}_resized{ext}") - resized.save(output_file) + def _resize_single(self, input_path, width, height, scale): + with Image.open(input_path) as img: + # Normalize orientation from EXIF before measuring/resizing + img = ImageOps.exif_transpose(img) + orig_width, orig_height = img.size + + if scale: + width = int(orig_width * scale / 100) + height = int(orig_height * scale / 100) + elif width and height: + width, height = int(width), int(height) + else: + raise ValueError("Provide width/height or scale.") + + resized = img.resize((width, height), RESAMPLE) + + os.makedirs(self.output_folder, exist_ok=True) + base, ext = os.path.splitext(os.path.basename(input_path)) + output_file = os.path.join(self.output_folder, f"{base}_resized{ext}") + resized.save(output_file)
93-99
: Optionally support single-dimension resize while preserving aspect ratio.Nice UX improvement: allow width or height alone.
- elif width and height: - width, height = int(width), int(height) + elif width and height: + width, height = int(width), int(height) + elif width or height: + # Preserve aspect ratio when one dimension is provided + if width: + width = int(width) + height = int(orig_height * (width / orig_width)) + else: + height = int(height) + width = int(orig_width * (height / orig_height))
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
Advanced_Projects/Image_resizer/Screenshot 2025-09-24 003634.png
is excluded by!**/*.png
📒 Files selected for processing (3)
Advanced_Projects/Image_resizer/app.py
(1 hunks)Advanced_Projects/Image_resizer/readme.md
(1 hunks)Cybersecurity_Tools/Reverse_backdoor/backdoor.py
(0 hunks)
💤 Files with no reviewable changes (1)
- Cybersecurity_Tools/Reverse_backdoor/backdoor.py
🧰 Additional context used
🪛 Ruff (0.13.1)
Advanced_Projects/Image_resizer/app.py
86-86: Do not catch blind exception: Exception
(BLE001)
99-99: Avoid specifying long messages outside the exception class
(TRY003)
🪛 markdownlint-cli2 (0.18.1)
Advanced_Projects/Image_resizer/readme.md
21-21: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (1)
Advanced_Projects/Image_resizer/app.py (1)
112-115
: Main entrypoint LGTM.Simple, clear startup sequence.
from PIL import Image | ||
|
||
|
||
class ImageResizerApp: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import needed PIL utilities and add LANCZOS fallback for older Pillow.
Prevents runtime errors on Pillow < 9.1.0 and enables safer handling.
-from PIL import Image
+from PIL import Image, UnidentifiedImageError, ImageOps
+
+# Pillow < 9.1.0 fallback
+try:
+ RESAMPLE = Image.Resampling.LANCZOS
+except AttributeError: # pragma: no cover
+ RESAMPLE = Image.LANCZOS
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
from PIL import Image | |
class ImageResizerApp: | |
from PIL import Image, UnidentifiedImageError, ImageOps | |
# Pillow < 9.1.0 fallback | |
try: | |
RESAMPLE = Image.Resampling.LANCZOS | |
except AttributeError: # pragma: no cover | |
RESAMPLE = Image.LANCZOS | |
class ImageResizerApp: |
🤖 Prompt for AI Agents
In Advanced_Projects/Image_resizer/app.py around lines 4 to 7, add the missing
PIL utility imports and a compatibility fallback for the LANCZOS resampling
constant: import the required PIL modules (e.g., Image and any utilities you
use) and define a module-level LANCZOS constant using a try/except that prefers
Image.Resampling.LANCZOS and falls back to Image.LANCZOS for older Pillow
versions so resampling calls work across Pillow <9.1.0 and newer releases.
- Python 3.8+ | ||
- [Pillow](https://pypi.org/project/pillow/) (PIL fork, for image processing) | ||
|
||
Install dependency: | ||
|
||
```bash | ||
pip install pillow | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick
Pin minimal Pillow version required by code.
Image.Resampling
needs Pillow ≥ 9.1.0.
-```bash
-pip install pillow
-```
+```bash
+pip install "pillow>=9.1.0"
+```
🤖 Prompt for AI Agents
In Advanced_Projects/Image_resizer/readme.md around lines 31 to 38, the
dependency note currently installs Pillow without a version pin even though the
code uses Image.Resampling which requires Pillow >= 9.1.0; update the
installation instruction to pin the minimal required version by replacing the
pip install line with pip install "pillow>=9.1.0" so the correct Pillow API is
available.
@UTSAVS26 please review my pr and merge it . |
Pull Request for PyVerse 💡
Requesting to submit a pull request to the PyVerse repository.
Issue Title
**🚀 New Advanced Project Proposal: "Image Resizer (GUI)" #1802 **
Info about the Related Issue
Goal:
Create a lightweight Python desktop app to resize images (JPG, PNG, BMP, GIF) by dimensions or percentage scale, with a Tkinter GUI and Pillow for image processing. Also serves as an educational project for learning GUI and image handling in Python.
Name
Sowmya Kurapati
GitHub ID
SowmyaKurapati26
Identify Yourself
Contributing as part of GSSOC25
Closes
Closes: #1802
Changes
output/
folder with_resized
suffix.Type of Change
How Has This Been Tested?
app.py
locally on Python 3.output/
folder.Summary by CodeRabbit