RafaelJaime commited on
Commit
730b3b2
·
1 Parent(s): 56ea5b1

Added watermark

Browse files
Files changed (2) hide show
  1. app.py +21 -17
  2. src/utils/watermark.py +51 -75
app.py CHANGED
@@ -46,30 +46,24 @@ def base64_to_image(base64_str):
46
  if not base64_str:
47
  return None
48
 
49
- # Remove data URI prefix if present (e.g., "data:image/png;base64,")
50
  if isinstance(base64_str, str) and "base64," in base64_str:
51
  base64_str = base64_str.split("base64,", 1)[1]
52
 
53
  try:
54
- # Strip any whitespace that might be in the base64 string
55
  if isinstance(base64_str, str):
56
  base64_str = base64_str.strip()
57
 
58
- # Decode the base64 data
59
  image_data = base64.b64decode(base64_str)
60
 
61
- # Check if we have data
62
  if not image_data:
63
  print("Decoded base64 data is empty")
64
  return None
65
 
66
- # Attempt to open the image
67
  image = Image.open(io.BytesIO(image_data))
68
 
69
- # Convert the image to ensure it's valid
70
  return image.copy()
71
 
72
- except base64.binascii.Error as e:
73
  print(f"Base64 decoding error: {str(e)}")
74
  if isinstance(base64_str, str):
75
  preview = base64_str[:30] + "..." if len(base64_str) > 30 else base64_str
@@ -79,12 +73,10 @@ def base64_to_image(base64_str):
79
  except Exception as e:
80
  print(f"Error converting base64 to image: {str(e)}")
81
 
82
- # Print preview of the base64 string for debugging
83
  if isinstance(base64_str, str):
84
  preview = base64_str[:30] + "..." if len(base64_str) > 30 else base64_str
85
  print(f"Base64 preview: {preview}")
86
 
87
- # Additional debug information
88
  if 'image_data' in locals() and image_data:
89
  try:
90
  magic_bytes = image_data[:12].hex()
@@ -99,21 +91,28 @@ def url_to_base64(url):
99
  return base64.b64encode(response.content).decode()
100
 
101
  def gradio_remove_background(image):
 
 
 
 
 
 
 
 
 
 
 
102
  if image is None:
103
  return None
104
  base64_img = image_to_base64(image)
105
  result = remove_background(f"data:image/png;base64,{base64_img}")
106
 
107
- # Check if the result is directly a base64 string or has an image_data key
108
  if isinstance(result, str):
109
  return base64_to_image(result)
110
  elif isinstance(result, dict) and "image_data" in result:
111
- # If image_data contains a data URI prefix
112
  if isinstance(result["image_data"], str) and result["image_data"].startswith("data:"):
113
- # The response already contains the full data URI
114
  return base64_to_image(result["image_data"])
115
  else:
116
- # Try to process it as a regular base64 string
117
  try:
118
  return base64_to_image(result["image_data"])
119
  except Exception as e:
@@ -175,14 +174,19 @@ def toggle_intensity_slider(filter_type):
175
  return gr.Slider(interactive=filter_type in intensity_filters)
176
 
177
  def gradio_add_watermark(image, watermark_text, opacity=0.5):
 
 
 
178
  if image is None:
179
  return None
 
 
 
180
  try:
181
- base64_img = image_to_base64(image)
182
- result = add_watermark(base64_img, watermark_text, opacity)
183
- return base64_to_image(result)
184
  except Exception as e:
185
- print(f"Error adding watermark: {e}")
186
  return image
187
 
188
  def gradio_remove_watermark(image):
 
46
  if not base64_str:
47
  return None
48
 
 
49
  if isinstance(base64_str, str) and "base64," in base64_str:
50
  base64_str = base64_str.split("base64,", 1)[1]
51
 
52
  try:
 
53
  if isinstance(base64_str, str):
54
  base64_str = base64_str.strip()
55
 
 
56
  image_data = base64.b64decode(base64_str)
57
 
 
58
  if not image_data:
59
  print("Decoded base64 data is empty")
60
  return None
61
 
 
62
  image = Image.open(io.BytesIO(image_data))
63
 
 
64
  return image.copy()
65
 
66
+ except binascii.Error as e:
67
  print(f"Base64 decoding error: {str(e)}")
68
  if isinstance(base64_str, str):
69
  preview = base64_str[:30] + "..." if len(base64_str) > 30 else base64_str
 
73
  except Exception as e:
74
  print(f"Error converting base64 to image: {str(e)}")
75
 
 
76
  if isinstance(base64_str, str):
77
  preview = base64_str[:30] + "..." if len(base64_str) > 30 else base64_str
78
  print(f"Base64 preview: {preview}")
79
 
 
80
  if 'image_data' in locals() and image_data:
81
  try:
82
  magic_bytes = image_data[:12].hex()
 
91
  return base64.b64encode(response.content).decode()
92
 
93
  def gradio_remove_background(image):
94
+ """
95
+ Attempt to remove watermarks from an image using contrast and brightness adjustment.
96
+
97
+ Args:
98
+ image_input: PIL Image object or base64 string
99
+ alpha: Contrast control (1.0-3.0, default 2.0). Higher values increase contrast.
100
+ beta: Brightness control (-255 to 255, default -160). Negative values decrease brightness.
101
+
102
+ Returns:
103
+ PIL Image object with watermark removal attempted
104
+ """
105
  if image is None:
106
  return None
107
  base64_img = image_to_base64(image)
108
  result = remove_background(f"data:image/png;base64,{base64_img}")
109
 
 
110
  if isinstance(result, str):
111
  return base64_to_image(result)
112
  elif isinstance(result, dict) and "image_data" in result:
 
113
  if isinstance(result["image_data"], str) and result["image_data"].startswith("data:"):
 
114
  return base64_to_image(result["image_data"])
115
  else:
 
116
  try:
117
  return base64_to_image(result["image_data"])
118
  except Exception as e:
 
174
  return gr.Slider(interactive=filter_type in intensity_filters)
175
 
176
  def gradio_add_watermark(image, watermark_text, opacity=0.5):
177
+ """
178
+ Gradio wrapper for add_watermark function
179
+ """
180
  if image is None:
181
  return None
182
+ if not watermark_text or watermark_text.strip() == "":
183
+ return image
184
+
185
  try:
186
+ result = add_watermark(image, watermark_text, opacity)
187
+ return result
 
188
  except Exception as e:
189
+ print(f"Error in gradio_add_watermark: {e}")
190
  return image
191
 
192
  def gradio_remove_watermark(image):
src/utils/watermark.py CHANGED
@@ -3,22 +3,36 @@ import os
3
  from typing import Dict, Any
4
  import cv2
5
  import numpy as np
 
 
 
 
6
 
7
- def add_watermark(image_path: str, watermark_text: str) -> Dict[str, Any]:
8
  """
9
  Add a semi-transparent text watermark to an image.
10
 
11
  Args:
12
- image_path: The path to the input image file.
13
- watermark_text: The text to be used as watermark.
 
14
 
15
  Returns:
16
- A dictionary containing success status, file paths, and operation details.
17
- On success: success=True, input_path, output_path, output_size_bytes, watermark_text, message.
18
- On failure: success=False, error message, input_path, output_path=None.
19
  """
20
  try:
21
- image = Image.open(image_path)
 
 
 
 
 
 
 
 
 
 
 
22
 
23
  overlay = Image.new('RGBA', image.size, (255, 255, 255, 0))
24
  draw = ImageDraw.Draw(overlay)
@@ -27,7 +41,10 @@ def add_watermark(image_path: str, watermark_text: str) -> Dict[str, Any]:
27
  font_size = min(image.width, image.height) // 20
28
  font = ImageFont.truetype("arial.ttf", font_size)
29
  except:
30
- font = ImageFont.load_default()
 
 
 
31
 
32
  bbox = draw.textbbox((0, 0), watermark_text, font=font)
33
  text_width = bbox[2] - bbox[0]
@@ -36,84 +53,43 @@ def add_watermark(image_path: str, watermark_text: str) -> Dict[str, Any]:
36
  x = (image.width - text_width) // 2
37
  y = (image.height - text_height) // 2
38
 
39
- text_color = (255, 255, 255, 128)
 
 
40
 
41
- draw.text((x-2, y-2), watermark_text, fill=(0, 0, 0, 64), font=font)
42
  draw.text((x, y), watermark_text, fill=text_color, font=font)
43
 
44
- watermarked = Image.alpha_composite(image.convert('RGBA'), overlay)
45
  final_image = watermarked.convert('RGB')
46
 
47
- base_dir = os.path.dirname(image_path)
48
- base_name, ext = os.path.splitext(os.path.basename(image_path))
49
- new_filename = f"{base_name}_watermarked{ext}"
50
- new_path = os.path.join(base_dir, new_filename)
51
-
52
- final_image.save(new_path, quality=95)
53
- output_size = os.path.getsize(new_path)
54
-
55
- return {
56
- "success": True,
57
- "message": "Watermark added successfully",
58
- "input_path": image_path,
59
- "output_path": new_path,
60
- "output_size_bytes": output_size,
61
- "watermark_text": watermark_text
62
- }
63
 
64
  except Exception as e:
65
- return {
66
- "success": False,
67
- "error": str(e),
68
- "input_path": image_path,
69
- "output_path": None
70
- }
71
 
72
- def remove_watermark(image_path: str, alpha: float = 2.0, beta: float = -160) -> Dict[str, Any]:
73
- """
74
- Attempt to remove watermarks from an image using contrast and brightness adjustment.
75
-
76
- Args:
77
- image_path: The path to the input image file.
78
- alpha: Contrast control (1.0-3.0, default 2.0). Higher values increase contrast.
79
- beta: Brightness control (-255 to 255, default -160). Negative values decrease brightness.
80
-
81
- Returns:
82
- A dictionary containing success status, file paths, and operation details.
83
- On success: success=True, input_path, output_path, output_size_bytes, alpha, beta, message.
84
- On failure: success=False, error message, input_path, output_path=None.
85
- """
86
  try:
87
- img = cv2.imread(image_path)
88
-
89
- if img is None:
90
- raise ValueError("Could not load image")
91
-
92
- new = alpha * img + beta
 
 
 
 
 
 
 
93
  new = np.clip(new, 0, 255).astype(np.uint8)
94
 
95
- base_dir = os.path.dirname(image_path)
96
- base_name, ext = os.path.splitext(os.path.basename(image_path))
97
- new_filename = f"{base_name}_cleaned{ext}"
98
- new_path = os.path.join(base_dir, new_filename)
99
-
100
- cv2.imwrite(new_path, new)
101
- output_size = os.path.getsize(new_path)
102
 
103
- return {
104
- "success": True,
105
- "message": "Watermark removal attempted successfully",
106
- "input_path": image_path,
107
- "output_path": new_path,
108
- "output_size_bytes": output_size,
109
- "alpha": alpha,
110
- "beta": beta
111
- }
112
 
113
  except Exception as e:
114
- return {
115
- "success": False,
116
- "error": str(e),
117
- "input_path": image_path,
118
- "output_path": None
119
- }
 
3
  from typing import Dict, Any
4
  import cv2
5
  import numpy as np
6
+ import binascii
7
+ from typing import Union
8
+ import base64
9
+ import io
10
 
11
+ def add_watermark(image_input: Union[str, Image.Image], watermark_text: str, opacity: float = 0.5) -> Union[str, Image.Image]:
12
  """
13
  Add a semi-transparent text watermark to an image.
14
 
15
  Args:
16
+ image_input: PIL Image object or base64 string
17
+ watermark_text: The text to be used as watermark
18
+ opacity: Opacity of the watermark (0.1 to 1.0)
19
 
20
  Returns:
21
+ PIL Image object with watermark applied
 
 
22
  """
23
  try:
24
+ if isinstance(image_input, str):
25
+ if image_input.startswith('data:image'):
26
+ base64_data = image_input.split(',')[1]
27
+ else:
28
+ base64_data = image_input
29
+ image_data = base64.b64decode(base64_data)
30
+ image = Image.open(io.BytesIO(image_data))
31
+ else:
32
+ image = image_input
33
+
34
+ if image.mode != 'RGBA':
35
+ image = image.convert('RGBA')
36
 
37
  overlay = Image.new('RGBA', image.size, (255, 255, 255, 0))
38
  draw = ImageDraw.Draw(overlay)
 
41
  font_size = min(image.width, image.height) // 20
42
  font = ImageFont.truetype("arial.ttf", font_size)
43
  except:
44
+ try:
45
+ font = ImageFont.load_default()
46
+ except:
47
+ font = ImageFont.load_default()
48
 
49
  bbox = draw.textbbox((0, 0), watermark_text, font=font)
50
  text_width = bbox[2] - bbox[0]
 
53
  x = (image.width - text_width) // 2
54
  y = (image.height - text_height) // 2
55
 
56
+ alpha_value = int(255 * opacity)
57
+ text_color = (255, 255, 255, alpha_value)
58
+ shadow_color = (0, 0, 0, int(alpha_value * 0.5))
59
 
60
+ draw.text((x-2, y-2), watermark_text, fill=shadow_color, font=font)
61
  draw.text((x, y), watermark_text, fill=text_color, font=font)
62
 
63
+ watermarked = Image.alpha_composite(image, overlay)
64
  final_image = watermarked.convert('RGB')
65
 
66
+ return final_image
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
  except Exception as e:
69
+ print(f"Error adding watermark: {e}")
70
+ return image_input if isinstance(image_input, Image.Image) else None
 
 
 
 
71
 
72
+ def remove_watermark(image_input: Union[str, Image.Image], alpha: float = 2.0, beta: float = -160) -> Union[str, Image.Image]:
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  try:
74
+ if isinstance(image_input, str):
75
+ if image_input.startswith('data:image'):
76
+ base64_data = image_input.split(',')[1]
77
+ else:
78
+ base64_data = image_input
79
+ image_data = base64.b64decode(base64_data)
80
+ image = Image.open(io.BytesIO(image_data))
81
+ else:
82
+ image = image_input
83
+
84
+ img_array = np.array(image)
85
+
86
+ new = alpha * img_array + beta
87
  new = np.clip(new, 0, 255).astype(np.uint8)
88
 
89
+ result_image = Image.fromarray(new)
 
 
 
 
 
 
90
 
91
+ return result_image
 
 
 
 
 
 
 
 
92
 
93
  except Exception as e:
94
+ print(f"Error removing watermark: {e}")
95
+ return image_input if isinstance(image_input, Image.Image) else None