RafaelJaime commited on
Commit
9cfb783
·
1 Parent(s): 417d69b

app add text to image, apply filter. Changed app, description and title in readme

Browse files
README.md CHANGED
@@ -5,9 +5,9 @@ colorFrom: pink
5
  colorTo: red
6
  sdk: gradio
7
  sdk_version: 5.32.0
8
- app_file: gradio_interface/app.py
9
  pinned: false
10
- short_description: a security framework designed for MCP deployments.
11
  tags: [mcp-server-track]
12
  ---
13
 
 
5
  colorTo: red
6
  sdk: gradio
7
  sdk_version: 5.32.0
8
+ app_file: app.py
9
  pinned: false
10
+ short_description: Useful tools for image editing.
11
  tags: [mcp-server-track]
12
  ---
13
 
mcp_server.py → app.py RENAMED
@@ -1,11 +1,10 @@
1
  import gradio as gr
 
2
  from src.utils.change_format import change_format
3
  from src.utils.remove_background import remove_background_from_url
4
  from src.utils.visualize_image import visualize_base64_image
5
  from src.utils.generate_image import generate_image
6
- from src.utils.apply_filter import apply_filter
7
- from src.utils.add_text import add_text_to_image
8
- from src.utils.resize_image import resize_image
9
  from src.utils.watermark import add_watermark, remove_watermark
10
  from src.utils.describe import describe_image
11
  from src.utils.compress import compress_image
@@ -35,60 +34,101 @@ def gradio_remove_background(image):
35
  if image is None:
36
  return None
37
  base64_img = image_to_base64(image)
38
- result = remove_background_from_url(f"data:image/png;base64,{base64_img}")
39
- return base64_to_image(result)
 
 
 
 
40
 
41
  def gradio_describe_image(image):
42
  if image is None:
43
  return "No image provided"
44
- base64_img = image_to_base64(image)
45
- return describe_image(base64_img)
 
 
 
 
46
 
47
  def gradio_change_format(image, format_type):
48
  if image is None:
49
  return None
50
- base64_img = image_to_base64(image)
51
- result = change_format(base64_img, format_type)
52
- return base64_to_image(result)
 
 
 
 
53
 
54
  def gradio_generate_image(prompt, width=512, height=512):
55
- result = generate_image(prompt, width, height)
56
- return base64_to_image(result)
 
 
 
 
 
57
 
58
- def gradio_apply_filter(image, filter_type):
59
  if image is None:
 
60
  return None
61
- base64_img = image_to_base64(image)
62
- result = apply_filter(base64_img, filter_type)
63
- return base64_to_image(result)
64
 
65
- def gradio_add_text(image, text, x=50, y=50, font_size=20, color="white"):
66
  if image is None:
67
  return None
68
- base64_img = image_to_base64(image)
69
- result = add_text_to_image(base64_img, text, x, y, font_size, color)
70
- return base64_to_image(result)
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
  def gradio_add_watermark(image, watermark_text, opacity=0.5):
73
  if image is None:
74
  return None
75
- base64_img = image_to_base64(image)
76
- result = add_watermark(base64_img, watermark_text, opacity)
77
- return base64_to_image(result)
 
 
 
 
78
 
79
  def gradio_remove_watermark(image):
80
  if image is None:
81
  return None
82
- base64_img = image_to_base64(image)
83
- result = remove_watermark(base64_img)
84
- return base64_to_image(result)
 
 
 
 
85
 
86
  def gradio_compress_image(image, quality=80):
87
  if image is None:
88
  return None
89
- base64_img = image_to_base64(image)
90
- result = compress_image(base64_img, quality)
91
- return base64_to_image(result)
 
 
 
 
92
 
93
  def create_gradio_interface():
94
  with gr.Blocks(title="Image Processing Service", theme=gr.themes.Soft()) as demo:
@@ -130,31 +170,89 @@ def create_gradio_interface():
130
  filter_input = gr.Image(label="Upload Image", type="pil")
131
  with gr.Column():
132
  filter_type = gr.Dropdown(
133
- ["blur", "sharpen", "vintage", "black_white", "sepia"],
134
  label="Filter Type",
135
  value="blur"
136
  )
 
 
 
 
 
 
 
 
 
 
137
  filter_output = gr.Image(label="Filtered Image")
138
 
139
- filter_input.change(gradio_apply_filter, [filter_input, filter_type], filter_output)
140
- filter_type.change(gradio_apply_filter, [filter_input, filter_type], filter_output)
 
 
 
 
 
 
 
 
141
 
142
  with gr.Tab("📝 Add Text"):
143
  with gr.Row():
144
  text_input = gr.Image(label="Upload Image", type="pil")
145
  with gr.Column():
146
- text_content = gr.Textbox(label="Text", placeholder="Enter text to add")
 
 
 
 
 
 
147
  with gr.Row():
148
- text_x = gr.Number(label="X Position", value=50)
149
- text_y = gr.Number(label="Y Position", value=50)
 
 
 
 
 
 
 
 
 
 
 
150
  with gr.Row():
151
- font_size = gr.Slider(10, 100, 20, label="Font Size")
152
- text_color = gr.ColorPicker(label="Color", value="#FFFFFF")
 
 
 
 
 
 
 
 
 
 
153
  text_output = gr.Image(label="Image with Text")
154
 
155
- inputs = [text_input, text_content, text_x, text_y, font_size, text_color]
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  for inp in inputs:
157
- inp.change(gradio_add_text, inputs, text_output)
158
 
159
  with gr.Tab("💧 Watermark"):
160
  with gr.Tabs():
 
1
  import gradio as gr
2
+ from src.utils.add_text import add_text_to_image_base64
3
  from src.utils.change_format import change_format
4
  from src.utils.remove_background import remove_background_from_url
5
  from src.utils.visualize_image import visualize_base64_image
6
  from src.utils.generate_image import generate_image
7
+ from src.utils.apply_filter import apply_filter_direct
 
 
8
  from src.utils.watermark import add_watermark, remove_watermark
9
  from src.utils.describe import describe_image
10
  from src.utils.compress import compress_image
 
34
  if image is None:
35
  return None
36
  base64_img = image_to_base64(image)
37
+ try:
38
+ result = remove_background_from_url(f"data:image/png;base64,{base64_img}")
39
+ return base64_to_image(result)
40
+ except Exception as e:
41
+ print(f"Error removing background: {e}")
42
+ return image
43
 
44
  def gradio_describe_image(image):
45
  if image is None:
46
  return "No image provided"
47
+ try:
48
+ base64_img = image_to_base64(image)
49
+ return describe_image(base64_img)
50
+ except Exception as e:
51
+ print(f"Error describing image: {e}")
52
+ return f"Error: {str(e)}"
53
 
54
  def gradio_change_format(image, format_type):
55
  if image is None:
56
  return None
57
+ try:
58
+ base64_img = image_to_base64(image)
59
+ result = change_format(base64_img, format_type)
60
+ return base64_to_image(result)
61
+ except Exception as e:
62
+ print(f"Error changing format: {e}")
63
+ return image
64
 
65
  def gradio_generate_image(prompt, width=512, height=512):
66
+ try:
67
+ result = generate_image(prompt, width, height)
68
+ return base64_to_image(result)
69
+ except Exception as e:
70
+ print(f"Error generating image: {e}")
71
+ return None
72
+
73
 
74
+ def gradio_apply_filter(image, filter_type, intensity=1.0):
75
  if image is None:
76
+ print("No image provided")
77
  return None
78
+
79
+ return apply_filter_direct(image, filter_type, intensity)
 
80
 
81
+ def update_text_image(image, text, centered, x, y, font_size, color):
82
  if image is None:
83
  return None
84
+ if not text or text.strip() == "":
85
+ return image
86
+
87
+ result = add_text_to_image_base64(image, text, int(x), int(y), int(font_size), color, centered)
88
+ return result
89
+
90
+ def toggle_position_fields(centered):
91
+ return (
92
+ gr.Number(interactive=not centered),
93
+ gr.Number(interactive=not centered)
94
+ )
95
+
96
+ def toggle_intensity_slider(filter_type):
97
+ intensity_filters = ['blur', 'brightness', 'contrast', 'saturation']
98
+ return gr.Slider(interactive=filter_type in intensity_filters)
99
 
100
  def gradio_add_watermark(image, watermark_text, opacity=0.5):
101
  if image is None:
102
  return None
103
+ try:
104
+ base64_img = image_to_base64(image)
105
+ result = add_watermark(base64_img, watermark_text, opacity)
106
+ return base64_to_image(result)
107
+ except Exception as e:
108
+ print(f"Error adding watermark: {e}")
109
+ return image
110
 
111
  def gradio_remove_watermark(image):
112
  if image is None:
113
  return None
114
+ try:
115
+ base64_img = image_to_base64(image)
116
+ result = remove_watermark(base64_img)
117
+ return base64_to_image(result)
118
+ except Exception as e:
119
+ print(f"Error removing watermark: {e}")
120
+ return image
121
 
122
  def gradio_compress_image(image, quality=80):
123
  if image is None:
124
  return None
125
+ try:
126
+ base64_img = image_to_base64(image)
127
+ result = compress_image(base64_img, quality)
128
+ return base64_to_image(result)
129
+ except Exception as e:
130
+ print(f"Error compressing image: {e}")
131
+ return image
132
 
133
  def create_gradio_interface():
134
  with gr.Blocks(title="Image Processing Service", theme=gr.themes.Soft()) as demo:
 
170
  filter_input = gr.Image(label="Upload Image", type="pil")
171
  with gr.Column():
172
  filter_type = gr.Dropdown(
173
+ ["blur", "sharpen", "vintage", "black_white", "sepia", "emboss", "edge", "smooth", "brightness", "contrast", "saturation", "grayscale"],
174
  label="Filter Type",
175
  value="blur"
176
  )
177
+
178
+ intensity_slider = gr.Slider(
179
+ minimum=0.1,
180
+ maximum=300.0,
181
+ value=1.0,
182
+ step=0.1,
183
+ label="Intensity",
184
+ interactive=True
185
+ )
186
+
187
  filter_output = gr.Image(label="Filtered Image")
188
 
189
+ filter_type.change(
190
+ toggle_intensity_slider,
191
+ filter_type,
192
+ intensity_slider
193
+ )
194
+
195
+ filter_inputs = [filter_input, filter_type, intensity_slider]
196
+
197
+ for inp in filter_inputs:
198
+ inp.change(gradio_apply_filter, filter_inputs, filter_output)
199
 
200
  with gr.Tab("📝 Add Text"):
201
  with gr.Row():
202
  text_input = gr.Image(label="Upload Image", type="pil")
203
  with gr.Column():
204
+ text_content = gr.Textbox(
205
+ label="Text",
206
+ placeholder="Enter text to add",
207
+ value=""
208
+ )
209
+ text_centered = gr.Checkbox(label="Center Text", value=False)
210
+
211
  with gr.Row():
212
+ text_x = gr.Number(
213
+ label="X Position",
214
+ value=50,
215
+ interactive=True,
216
+ minimum=0
217
+ )
218
+ text_y = gr.Number(
219
+ label="Y Position",
220
+ value=50,
221
+ interactive=True,
222
+ minimum=0
223
+ )
224
+
225
  with gr.Row():
226
+ font_size = gr.Slider(
227
+ minimum=10,
228
+ maximum=100,
229
+ value=20,
230
+ label="Font Size"
231
+ )
232
+ text_color = gr.ColorPicker(
233
+ label="Color",
234
+ value="#FFFFFF"
235
+ )
236
+
237
+ add_text_btn = gr.Button("Add Text", variant="primary")
238
  text_output = gr.Image(label="Image with Text")
239
 
240
+ text_centered.change(
241
+ toggle_position_fields,
242
+ text_centered,
243
+ [text_x, text_y]
244
+ )
245
+
246
+ inputs = [text_input, text_content, text_centered, text_x, text_y, font_size, text_color]
247
+
248
+ add_text_btn.click(
249
+ update_text_image,
250
+ inputs,
251
+ text_output
252
+ )
253
+
254
  for inp in inputs:
255
+ inp.change(update_text_image, inputs, text_output)
256
 
257
  with gr.Tab("💧 Watermark"):
258
  with gr.Tabs():
src/utils/add_text.py CHANGED
@@ -2,12 +2,25 @@ from PIL import Image, ImageDraw, ImageFont
2
  import os
3
  from typing import Optional, Tuple, Dict, Any
4
 
5
- def add_text_to_image(
6
- image_path: str,
7
- text: str,
8
- color: Optional[Tuple[int, int, int]] = None,
9
- output_name: Optional[str] = None
10
- ) -> Dict[str, Any]:
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  """
12
  Adds centered text to an image and saves the result in the same folder.
13
  If no output_name is provided, '_edited' is appended to the original filename.
@@ -22,47 +35,28 @@ def add_text_to_image(
22
  Returns:
23
  Dictionary with success status and info.
24
  """
 
 
 
 
 
 
25
  try:
26
- if color is None:
27
- color = (0, 0, 0)
28
-
29
- image = Image.open(image_path)
30
- draw = ImageDraw.Draw(image)
31
- font = ImageFont.load_default()
32
-
33
- text_width = draw.textlength(text, font=font)
34
- x = (image.width - text_width) / 2
35
- y = image.height / 2
36
-
37
- draw.text((x, y), text, fill=color, font=font)
38
-
39
- base_dir = os.path.dirname(image_path)
40
- base_name, ext = os.path.splitext(os.path.basename(image_path))
41
-
42
- if output_name:
43
- new_filename = f"{output_name}{ext}"
44
- else:
45
- new_filename = f"{base_name}_edited{ext}"
46
-
47
- new_path = os.path.join(base_dir, new_filename)
48
-
49
- image.save(new_path)
50
- output_size = os.path.getsize(new_path)
51
-
52
- return {
53
- "success": True,
54
- "message": "Text added successfully to the image",
55
- "input_path": image_path,
56
- "output_path": new_path,
57
- "output_size_bytes": output_size,
58
- "text": text,
59
- "color": color
60
- }
61
-
62
- except Exception as e:
63
- return {
64
- "success": False,
65
- "error": str(e),
66
- "input_path": image_path,
67
- "output_path": None
68
- }
 
2
  import os
3
  from typing import Optional, Tuple, Dict, Any
4
 
5
+ def parse_color(color_str):
6
+ if color_str.startswith('rgba('):
7
+ values = color_str[5:-1].split(',')
8
+ r = int(float(values[0]))
9
+ g = int(float(values[1]))
10
+ b = int(float(values[2]))
11
+ return (r, g, b)
12
+ elif color_str.startswith('rgb('):
13
+ values = color_str[4:-1].split(',')
14
+ r = int(float(values[0]))
15
+ g = int(float(values[1]))
16
+ b = int(float(values[2]))
17
+ return (r, g, b)
18
+ elif color_str.startswith('#'):
19
+ return color_str
20
+ else:
21
+ return color_str
22
+
23
+ def add_text_to_image_base64(image, text, x, y, font_size, color, centered=False):
24
  """
25
  Adds centered text to an image and saves the result in the same folder.
26
  If no output_name is provided, '_edited' is appended to the original filename.
 
35
  Returns:
36
  Dictionary with success status and info.
37
  """
38
+ if image is None:
39
+ return None
40
+
41
+ img = image.copy()
42
+ draw = ImageDraw.Draw(img)
43
+
44
  try:
45
+ font = ImageFont.truetype("arial.ttf", font_size)
46
+ except:
47
+ try:
48
+ font = ImageFont.truetype("/System/Library/Fonts/Arial.ttf", font_size)
49
+ except:
50
+ font = ImageFont.load_default()
51
+
52
+ parsed_color = parse_color(color)
53
+
54
+ if centered:
55
+ bbox = draw.textbbox((0, 0), text, font=font)
56
+ text_width = bbox[2] - bbox[0]
57
+ text_height = bbox[3] - bbox[1]
58
+ x = (img.width - text_width) // 2
59
+ y = (img.height - text_height) // 2
60
+
61
+ draw.text((x, y), text, fill=parsed_color, font=font)
62
+ return img
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/utils/apply_filter.py CHANGED
@@ -3,74 +3,100 @@ from io import BytesIO
3
  import requests
4
  import base64
5
 
6
- def apply_filter(image_url: str, filter_type: str, intensity: float = 1.0, output_format: str = 'JPEG') -> str:
7
  """
8
- Apply various filters to an image from a URL.
9
-
10
- Args:
11
- image_url: The URL of the input image.
12
- filter_type: Type of filter to apply ('blur', 'sharpen', 'emboss', 'edge', 'smooth',
13
- 'brightness', 'contrast', 'saturation', 'sepia', 'grayscale').
14
- intensity: Filter intensity (0.1 to 3.0, default 1.0).
15
- output_format: The desired output format (e.g., 'JPEG', 'PNG').
16
-
17
- Returns:
18
- The filtered image as a base64-encoded string.
19
  """
 
 
20
 
21
- response = requests.get(image_url, timeout=30)
22
- response.raise_for_status()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
- img = Image.open(BytesIO(response.content))
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
- if img.mode != 'RGB':
27
- img = img.convert('RGB')
 
 
 
 
28
 
29
- if filter_type == 'blur':
30
- img = img.filter(ImageFilter.GaussianBlur(radius=intensity))
31
- elif filter_type == 'sharpen':
32
- img = img.filter(ImageFilter.UnsharpMask(radius=2, percent=int(intensity * 150), threshold=3))
33
- elif filter_type == 'emboss':
34
- img = img.filter(ImageFilter.EMBOSS)
35
- elif filter_type == 'edge':
36
- img = img.filter(ImageFilter.FIND_EDGES)
37
- elif filter_type == 'smooth':
38
- img = img.filter(ImageFilter.SMOOTH_MORE)
39
- elif filter_type == 'brightness':
40
- enhancer = ImageEnhance.Brightness(img)
41
- img = enhancer.enhance(intensity)
42
- elif filter_type == 'contrast':
43
- enhancer = ImageEnhance.Contrast(img)
44
- img = enhancer.enhance(intensity)
45
- elif filter_type == 'saturation':
46
- enhancer = ImageEnhance.Color(img)
47
- img = enhancer.enhance(intensity)
48
- elif filter_type == 'sepia':
49
- img = apply_sepia_filter(img)
50
- elif filter_type == 'grayscale':
51
- img = img.convert('L').convert('RGB')
52
 
53
- output = BytesIO()
54
- img.save(output, format=output_format, quality=95)
55
- output.seek(0)
56
 
57
- encoded_image = base64.b64encode(output.getvalue()).decode('utf-8')
58
 
59
- return encoded_image
60
 
61
- def apply_sepia_filter(img: Image.Image) -> Image.Image:
62
- """
63
- Apply sepia tone effect to an image.
64
-
65
- Args:
66
- img: PIL Image object.
67
-
68
- Returns:
69
- Image with sepia effect applied.
70
- """
71
-
72
- pixels = img.load()
73
  width, height = img.size
 
74
 
75
  for y in range(height):
76
  for x in range(width):
@@ -80,44 +106,24 @@ def apply_sepia_filter(img: Image.Image) -> Image.Image:
80
  tg = int(0.349 * r + 0.686 * g + 0.168 * b)
81
  tb = int(0.272 * r + 0.534 * g + 0.131 * b)
82
 
83
- pixels[x, y] = (min(255, tr), min(255, tg), min(255, tb))
 
 
 
 
84
 
85
  return img
86
 
87
- def apply_vintage_filter(image_url: str, output_format: str = 'JPEG') -> str:
88
- """
89
- Apply a vintage effect combining multiple filters.
90
-
91
- Args:
92
- image_url: The URL of the input image.
93
- output_format: The desired output format.
94
-
95
- Returns:
96
- The vintage-filtered image as a base64-encoded string.
97
- """
98
-
99
- response = requests.get(image_url, timeout=30)
100
- response.raise_for_status()
101
-
102
- img = Image.open(BytesIO(response.content))
103
-
104
- if img.mode != 'RGB':
105
- img = img.convert('RGB')
106
-
107
  contrast_enhancer = ImageEnhance.Contrast(img)
108
  img = contrast_enhancer.enhance(0.8)
109
 
110
  brightness_enhancer = ImageEnhance.Brightness(img)
111
  img = brightness_enhancer.enhance(1.1)
112
 
113
- img = apply_sepia_filter(img)
114
 
115
  img = img.filter(ImageFilter.GaussianBlur(radius=0.5))
116
 
117
- output = BytesIO()
118
- img.save(output, format=output_format, quality=90)
119
- output.seek(0)
120
-
121
- encoded_image = base64.b64encode(output.getvalue()).decode('utf-8')
122
-
123
- return encoded_image
 
3
  import requests
4
  import base64
5
 
6
+ def apply_filter_direct(image, filter_type, intensity=1.0):
7
  """
8
+ Apply filters directly to PIL image without base64 conversion
 
 
 
 
 
 
 
 
 
 
9
  """
10
+ if image is None:
11
+ return None
12
 
13
+ try:
14
+ print(f"Applying filter: {filter_type} with intensity: {intensity}")
15
+ img = image.copy()
16
+
17
+ if img.mode != 'RGB':
18
+ img = img.convert('RGB')
19
+
20
+ if filter_type == 'blur':
21
+ img = img.filter(ImageFilter.GaussianBlur(radius=max(0.1, intensity)))
22
+ elif filter_type == 'sharpen':
23
+ if intensity <= 1.0:
24
+ img = img.filter(ImageFilter.SHARPEN)
25
+ else:
26
+ img = img.filter(ImageFilter.UnsharpMask(radius=2, percent=int(intensity * 150), threshold=3))
27
+ elif filter_type == 'emboss':
28
+ img = img.filter(ImageFilter.EMBOSS)
29
+ elif filter_type == 'edge':
30
+ img = img.filter(ImageFilter.FIND_EDGES)
31
+ elif filter_type == 'smooth':
32
+ img = img.filter(ImageFilter.SMOOTH_MORE)
33
+ elif filter_type == 'brightness':
34
+ enhancer = ImageEnhance.Brightness(img)
35
+ img = enhancer.enhance(max(0.1, intensity))
36
+ elif filter_type == 'contrast':
37
+ enhancer = ImageEnhance.Contrast(img)
38
+ img = enhancer.enhance(max(0.1, intensity))
39
+ elif filter_type == 'saturation':
40
+ enhancer = ImageEnhance.Color(img)
41
+ img = enhancer.enhance(max(0.1, intensity))
42
+ elif filter_type == 'sepia':
43
+ img = apply_sepia_filter_direct(img)
44
+ elif filter_type == 'grayscale' or filter_type == 'black_white':
45
+ img = img.convert('L').convert('RGB')
46
+ elif filter_type == 'vintage':
47
+ img = apply_vintage_effect_direct(img)
48
+ else:
49
+ print(f"Unknown filter type: {filter_type}")
50
+ return image
51
+
52
+ print(f"Filter applied successfully")
53
+ return img
54
+
55
+ except Exception as e:
56
+ print(f"Error applying filter: {e}")
57
+ import traceback
58
+ traceback.print_exc()
59
+ return image
60
+
61
+ def apply_sepia_filter_direct(img):
62
+ """Apply sepia tone effect to an image."""
63
+ width, height = img.size
64
+ pixels = img.load()
65
 
66
+ for y in range(height):
67
+ for x in range(width):
68
+ r, g, b = pixels[x, y]
69
+
70
+ tr = int(0.393 * r + 0.769 * g + 0.189 * b)
71
+ tg = int(0.349 * r + 0.686 * g + 0.168 * b)
72
+ tb = int(0.272 * r + 0.534 * g + 0.131 * b)
73
+
74
+ tr = min(255, tr)
75
+ tg = min(255, tg)
76
+ tb = min(255, tb)
77
+
78
+ pixels[x, y] = (tr, tg, tb)
79
 
80
+ return img
81
+
82
+ def apply_vintage_effect_direct(img):
83
+ """Apply a vintage effect combining multiple filters."""
84
+ contrast_enhancer = ImageEnhance.Contrast(img)
85
+ img = contrast_enhancer.enhance(0.8)
86
 
87
+ brightness_enhancer = ImageEnhance.Brightness(img)
88
+ img = brightness_enhancer.enhance(1.1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
+ img = apply_sepia_filter_direct(img)
 
 
91
 
92
+ img = img.filter(ImageFilter.GaussianBlur(radius=0.5))
93
 
94
+ return img
95
 
96
+ def apply_sepia_filter_direct(img):
97
+ """Apply sepia tone effect to an image."""
 
 
 
 
 
 
 
 
 
 
98
  width, height = img.size
99
+ pixels = img.load()
100
 
101
  for y in range(height):
102
  for x in range(width):
 
106
  tg = int(0.349 * r + 0.686 * g + 0.168 * b)
107
  tb = int(0.272 * r + 0.534 * g + 0.131 * b)
108
 
109
+ tr = min(255, tr)
110
+ tg = min(255, tg)
111
+ tb = min(255, tb)
112
+
113
+ pixels[x, y] = (tr, tg, tb)
114
 
115
  return img
116
 
117
+ def apply_vintage_effect_direct(img):
118
+ """Apply a vintage effect combining multiple filters."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  contrast_enhancer = ImageEnhance.Contrast(img)
120
  img = contrast_enhancer.enhance(0.8)
121
 
122
  brightness_enhancer = ImageEnhance.Brightness(img)
123
  img = brightness_enhancer.enhance(1.1)
124
 
125
+ img = apply_sepia_filter_direct(img)
126
 
127
  img = img.filter(ImageFilter.GaussianBlur(radius=0.5))
128
 
129
+ return img