snapforge 0.2.1__tar.gz → 1.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {snapforge-0.2.1 → snapforge-1.2.0}/PKG-INFO +19 -15
- {snapforge-0.2.1 → snapforge-1.2.0}/README.md +18 -14
- {snapforge-0.2.1 → snapforge-1.2.0}/pyproject.toml +1 -1
- {snapforge-0.2.1 → snapforge-1.2.0}/snapforge/__init__.py +1 -1
- {snapforge-0.2.1 → snapforge-1.2.0}/snapforge/forge.py +95 -3
- {snapforge-0.2.1 → snapforge-1.2.0}/snapforge.egg-info/PKG-INFO +19 -15
- {snapforge-0.2.1 → snapforge-1.2.0}/setup.cfg +0 -0
- {snapforge-0.2.1 → snapforge-1.2.0}/snapforge.egg-info/SOURCES.txt +0 -0
- {snapforge-0.2.1 → snapforge-1.2.0}/snapforge.egg-info/dependency_links.txt +0 -0
- {snapforge-0.2.1 → snapforge-1.2.0}/snapforge.egg-info/requires.txt +0 -0
- {snapforge-0.2.1 → snapforge-1.2.0}/snapforge.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: snapforge
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: Powerful and fast image editor! 😎
|
|
5
5
|
Author: Ali
|
|
6
6
|
Requires-Python: >=3.7
|
|
@@ -47,23 +47,27 @@ resized_img.convert("PNG").save("example_resized.png")
|
|
|
47
47
|
|
|
48
48
|
print("Image processed successfully!")
|
|
49
49
|
|
|
50
|
-
🧾 Feature Showcase (Full Reference)
|
|
51
|
-
|
|
50
|
+
## 🧾 Feature Showcase (Full Reference)
|
|
52
51
|
|
|
53
52
|
Here is the complete list of all available methods in SnapForge:
|
|
54
53
|
|
|
55
|
-
Category
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
| Category | Method | Description | Example |
|
|
55
|
+
| :--- | :--- | :--- | :--- |
|
|
56
|
+
| **Core** | `.convert(fmt)` | Change image format (e.g., PNG, JPG) | `.convert("PNG")` |
|
|
57
|
+
| | `.resize(w, h)` | Change image dimensions | `.resize(800, 600)` |
|
|
58
|
+
| | `.crop(l, t, r, b)` | Crop image to specific boundaries | `.crop(0, 0, 100, 100)` |
|
|
59
|
+
| | `.rotate(a)` | Rotate image by angle | `.rotate(90)` |
|
|
60
|
+
| | `.optimize(q)` | Set compression quality (1-100) | `.optimize(85)` |
|
|
61
|
+
| | `.save(name)` | Save the final forged image | `.save("result.jpg")` |
|
|
62
|
+
| **Lighting** | `.apply_brightness(f)` | Adjust brightness (factor > 1.0 is brighter) | `.apply_brightness(1.2)` |
|
|
63
|
+
| | `.apply_contrast(f)` | Adjust contrast (factor > 1.0 is higher) | `.apply_contrast(1.5)` |
|
|
64
|
+
| **Filters** | `.apply_sepia()` | Apply a classic vintage sepia effect | `.apply_sepia()` |
|
|
65
|
+
| | `.apply_grayscale(f)` | Convert to black & white (0.0 to 1.0) | `.apply_grayscale(1.0)` |
|
|
66
|
+
| | `.apply_blur(r)` | Apply Gaussian blur with radius r | `.apply_blur(5.0)` |
|
|
67
|
+
| | `.apply_sharpen()` | Enhance image sharpness/clarity | `.apply_sharpen()` |
|
|
68
|
+
| | `.apply_camscanner()`| Apply document scanner effect (B&W/Threshold) | `.apply_camscanner()` |
|
|
69
|
+
| **Extras** | `.flip(dir)` | Flip image (horizontal or vertical) | `.flip("horizontal")` |
|
|
70
|
+
| | `.add_watermark(p)` | Add a watermark image | `.add_watermark("logo.png")` |
|
|
67
71
|
|
|
68
72
|
|
|
69
73
|
🛠️ Requirements
|
|
@@ -38,23 +38,27 @@ resized_img.convert("PNG").save("example_resized.png")
|
|
|
38
38
|
|
|
39
39
|
print("Image processed successfully!")
|
|
40
40
|
|
|
41
|
-
🧾 Feature Showcase (Full Reference)
|
|
42
|
-
|
|
41
|
+
## 🧾 Feature Showcase (Full Reference)
|
|
43
42
|
|
|
44
43
|
Here is the complete list of all available methods in SnapForge:
|
|
45
44
|
|
|
46
|
-
Category
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
45
|
+
| Category | Method | Description | Example |
|
|
46
|
+
| :--- | :--- | :--- | :--- |
|
|
47
|
+
| **Core** | `.convert(fmt)` | Change image format (e.g., PNG, JPG) | `.convert("PNG")` |
|
|
48
|
+
| | `.resize(w, h)` | Change image dimensions | `.resize(800, 600)` |
|
|
49
|
+
| | `.crop(l, t, r, b)` | Crop image to specific boundaries | `.crop(0, 0, 100, 100)` |
|
|
50
|
+
| | `.rotate(a)` | Rotate image by angle | `.rotate(90)` |
|
|
51
|
+
| | `.optimize(q)` | Set compression quality (1-100) | `.optimize(85)` |
|
|
52
|
+
| | `.save(name)` | Save the final forged image | `.save("result.jpg")` |
|
|
53
|
+
| **Lighting** | `.apply_brightness(f)` | Adjust brightness (factor > 1.0 is brighter) | `.apply_brightness(1.2)` |
|
|
54
|
+
| | `.apply_contrast(f)` | Adjust contrast (factor > 1.0 is higher) | `.apply_contrast(1.5)` |
|
|
55
|
+
| **Filters** | `.apply_sepia()` | Apply a classic vintage sepia effect | `.apply_sepia()` |
|
|
56
|
+
| | `.apply_grayscale(f)` | Convert to black & white (0.0 to 1.0) | `.apply_grayscale(1.0)` |
|
|
57
|
+
| | `.apply_blur(r)` | Apply Gaussian blur with radius r | `.apply_blur(5.0)` |
|
|
58
|
+
| | `.apply_sharpen()` | Enhance image sharpness/clarity | `.apply_sharpen()` |
|
|
59
|
+
| | `.apply_camscanner()`| Apply document scanner effect (B&W/Threshold) | `.apply_camscanner()` |
|
|
60
|
+
| **Extras** | `.flip(dir)` | Flip image (horizontal or vertical) | `.flip("horizontal")` |
|
|
61
|
+
| | `.add_watermark(p)` | Add a watermark image | `.add_watermark("logo.png")` |
|
|
58
62
|
|
|
59
63
|
|
|
60
64
|
🛠️ Requirements
|
|
@@ -1,11 +1,62 @@
|
|
|
1
1
|
from PIL import Image, ImageEnhance, ImageOps, ImageFilter
|
|
2
2
|
import os
|
|
3
|
+
import requests
|
|
4
|
+
import threading
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from packaging import version
|
|
7
|
+
|
|
8
|
+
class SnapForgeUpdater:
|
|
9
|
+
def __init__(self, package_name: str, current_version: str):
|
|
10
|
+
self.package_name = package_name
|
|
11
|
+
self.current_version = current_version
|
|
12
|
+
self.api_url = f"https://pypi.org/pypi/{package_name}/json"
|
|
13
|
+
|
|
14
|
+
def _check_logic(self):
|
|
15
|
+
"""Perform the update check in the background."""
|
|
16
|
+
try:
|
|
17
|
+
response = requests.get(self.api_url, timeout=5)
|
|
18
|
+
if response.status_code != 200:
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
data = response.json()
|
|
22
|
+
latest_version = data["info"]["version"]
|
|
23
|
+
|
|
24
|
+
if version.parse(latest_version) > version.parse(self.current_version):
|
|
25
|
+
latest_release_data = data["releases"][latest_version][0]
|
|
26
|
+
iso_time = latest_release_data["upload_time_iso_8601"]
|
|
27
|
+
|
|
28
|
+
dt_object = datetime.fromisoformat(iso_time.replace('Z', '+00:00'))
|
|
29
|
+
formatted_time = dt_object.strftime('%Y-%m-%d %H:%M:%S')
|
|
30
|
+
|
|
31
|
+
self._notify_user(latest_version, formatted_time)
|
|
32
|
+
|
|
33
|
+
except Exception:
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
def _notify_user(self, latest_version, upload_time):
|
|
37
|
+
"""Display the update notification to the user."""
|
|
38
|
+
print("\n" + "="*50)
|
|
39
|
+
print(f"🚀 [SnapForge] NEW UPDATE AVAILABLE!")
|
|
40
|
+
print(f"✨ Latest Version: {latest_version}")
|
|
41
|
+
print(f"📅 Released on: {upload_time} (UTC)")
|
|
42
|
+
print(f"🛠️ Your Version: {self.current_version}")
|
|
43
|
+
print(f"👉 Run: pip install --upgrade {self.package_name}")
|
|
44
|
+
print("="*50 + "\n")
|
|
45
|
+
|
|
46
|
+
def start_check(self):
|
|
47
|
+
"""Initialize the update check in a separate thread."""
|
|
48
|
+
thread = threading.Thread(target=self._check_logic, daemon=True)
|
|
49
|
+
thread.start()
|
|
3
50
|
|
|
4
51
|
class SnapForge:
|
|
5
|
-
|
|
52
|
+
__version__ = "1.2.0"
|
|
6
53
|
|
|
7
54
|
def __init__(self, image_path: str):
|
|
8
55
|
""" 😎 Load your image and get ready for the magic! 😎 """
|
|
56
|
+
updater = SnapForgeUpdater("snapforge", self.__version__)
|
|
57
|
+
updater.start_check()
|
|
58
|
+
|
|
59
|
+
print(f"📸 SnapForge initialized (v{self.__version__})")
|
|
9
60
|
if not os.path.exists(image_path):
|
|
10
61
|
raise FileNotFoundError(f"❌ Error: The specified file path does not exist: '{image_path}'")
|
|
11
62
|
|
|
@@ -13,7 +64,7 @@ class SnapForge:
|
|
|
13
64
|
self.image = Image.open(image_path).convert("RGB")
|
|
14
65
|
self.original_format = self.image.format
|
|
15
66
|
self.target_format = self.original_format if self.original_format else "JPEG"
|
|
16
|
-
self.quality = 85
|
|
67
|
+
self.quality = 85
|
|
17
68
|
print(f"🚀 Success: Image loaded successfully. Original format: {self.target_format}")
|
|
18
69
|
except Exception as e:
|
|
19
70
|
raise IOError(f"❌ Error: Failed to open the image. Details: {e}")
|
|
@@ -128,4 +179,45 @@ class SnapForge:
|
|
|
128
179
|
print(f"🎉 Success: Image forged and saved as '{output_name}' 🎉")
|
|
129
180
|
return output_name
|
|
130
181
|
except Exception as e:
|
|
131
|
-
raise IOError(f"❌ Error: Failed to save the image. Details: {e}")
|
|
182
|
+
raise IOError(f"❌ Error: Failed to save the image. Details: {e}")
|
|
183
|
+
|
|
184
|
+
def flip(self, direction: str = "horizontal"):
|
|
185
|
+
""" 😎 Flip the image! direction: 'horizontal' or 'vertical' 😎 """
|
|
186
|
+
if direction.lower() == "horizontal":
|
|
187
|
+
self.image = self.image.transpose(Image.FLIP_LEFT_RIGHT)
|
|
188
|
+
elif direction.lower() == "vertical":
|
|
189
|
+
self.image = self.image.transpose(Image.FLIP_TOP_BOTTOM)
|
|
190
|
+
else:
|
|
191
|
+
raise ValueError("❌ Error: Direction must be 'horizontal' or 'vertical'.")
|
|
192
|
+
print(f"🔄 Success: Image flipped {direction}ly")
|
|
193
|
+
return self
|
|
194
|
+
|
|
195
|
+
def apply_camscanner(self):
|
|
196
|
+
""" 😎 Make it look like a scanned document! 😎 """
|
|
197
|
+
|
|
198
|
+
self.image = self.image.convert("L")
|
|
199
|
+
|
|
200
|
+
threshold = 150
|
|
201
|
+
self.image = self.image.point(lambda p: 255 if p > threshold else 0)
|
|
202
|
+
|
|
203
|
+
self.image = self.image.convert("RGB")
|
|
204
|
+
|
|
205
|
+
print(f"📄 Success: CamScanner effect applied!")
|
|
206
|
+
return self
|
|
207
|
+
|
|
208
|
+
def rotate(self, angle: float, expand: bool = True):
|
|
209
|
+
""" 😎 Rotate the image by any angle! 😎
|
|
210
|
+
angle: degrees (positive is counter-clockwise)
|
|
211
|
+
expand: If True, expands the output image to fit the rotated image.
|
|
212
|
+
"""
|
|
213
|
+
self.image = self.image.rotate(angle, expand=expand)
|
|
214
|
+
print(f"🔄 Success: Image rotated by {angle} degrees")
|
|
215
|
+
return self
|
|
216
|
+
|
|
217
|
+
def crop(self, left: int, top: int, right: int, bottom: int):
|
|
218
|
+
""" 😎 Cut out the unwanted parts! 😎
|
|
219
|
+
Arguments define the box to keep.
|
|
220
|
+
"""
|
|
221
|
+
self.image = self.image.crop((left, top, right, bottom))
|
|
222
|
+
print(f"✂️ Success: Image cropped to ({left}, {top}, {right}, {bottom})")
|
|
223
|
+
return self
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: snapforge
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: Powerful and fast image editor! 😎
|
|
5
5
|
Author: Ali
|
|
6
6
|
Requires-Python: >=3.7
|
|
@@ -47,23 +47,27 @@ resized_img.convert("PNG").save("example_resized.png")
|
|
|
47
47
|
|
|
48
48
|
print("Image processed successfully!")
|
|
49
49
|
|
|
50
|
-
🧾 Feature Showcase (Full Reference)
|
|
51
|
-
|
|
50
|
+
## 🧾 Feature Showcase (Full Reference)
|
|
52
51
|
|
|
53
52
|
Here is the complete list of all available methods in SnapForge:
|
|
54
53
|
|
|
55
|
-
Category
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
| Category | Method | Description | Example |
|
|
55
|
+
| :--- | :--- | :--- | :--- |
|
|
56
|
+
| **Core** | `.convert(fmt)` | Change image format (e.g., PNG, JPG) | `.convert("PNG")` |
|
|
57
|
+
| | `.resize(w, h)` | Change image dimensions | `.resize(800, 600)` |
|
|
58
|
+
| | `.crop(l, t, r, b)` | Crop image to specific boundaries | `.crop(0, 0, 100, 100)` |
|
|
59
|
+
| | `.rotate(a)` | Rotate image by angle | `.rotate(90)` |
|
|
60
|
+
| | `.optimize(q)` | Set compression quality (1-100) | `.optimize(85)` |
|
|
61
|
+
| | `.save(name)` | Save the final forged image | `.save("result.jpg")` |
|
|
62
|
+
| **Lighting** | `.apply_brightness(f)` | Adjust brightness (factor > 1.0 is brighter) | `.apply_brightness(1.2)` |
|
|
63
|
+
| | `.apply_contrast(f)` | Adjust contrast (factor > 1.0 is higher) | `.apply_contrast(1.5)` |
|
|
64
|
+
| **Filters** | `.apply_sepia()` | Apply a classic vintage sepia effect | `.apply_sepia()` |
|
|
65
|
+
| | `.apply_grayscale(f)` | Convert to black & white (0.0 to 1.0) | `.apply_grayscale(1.0)` |
|
|
66
|
+
| | `.apply_blur(r)` | Apply Gaussian blur with radius r | `.apply_blur(5.0)` |
|
|
67
|
+
| | `.apply_sharpen()` | Enhance image sharpness/clarity | `.apply_sharpen()` |
|
|
68
|
+
| | `.apply_camscanner()`| Apply document scanner effect (B&W/Threshold) | `.apply_camscanner()` |
|
|
69
|
+
| **Extras** | `.flip(dir)` | Flip image (horizontal or vertical) | `.flip("horizontal")` |
|
|
70
|
+
| | `.add_watermark(p)` | Add a watermark image | `.add_watermark("logo.png")` |
|
|
67
71
|
|
|
68
72
|
|
|
69
73
|
🛠️ Requirements
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|