{ "cells": [ { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "from PIL import Image, ImageDraw\n", "import imageio\n", "import numpy as np\n", "from io import BytesIO\n", "import cairosvg\n", "from lxml import etree\n", "\n", "# Assuming WATERMARK and WATERMARK_SIZE are defined elsewhere, e.g.,\n", "WATERMARK = \"\"\"\n", "\n", " \n", "\n", "\"\"\"\n", "WATERMARK_SIZE = 40\n", "\n", "# def add_watermark_to_image_sequence(pil_images, base_blob_name):\n", "# \"\"\"\n", "# Adds a watermark to a sequence of PIL images.\n", "\n", "# Args:\n", "# pil_images: A list of PIL Image objects.\n", "# base_blob_name: The base name of the blob (used for naming the output).\n", "\n", "# Returns:\n", "# A list of bytes objects representing the watermarked images.\n", "# \"\"\"\n", "\n", "# watermarked_images = []\n", "# for img in pil_images:\n", "# img = add_watermark_to_image(img)\n", " \n", "# # Save the image to a bytes buffer\n", "# buffer = BytesIO()\n", "# img.save(buffer, format=\"JPEG\")\n", "# watermarked_images.append(buffer.getvalue())\n", "\n", "# return watermarked_images\n", " \n", " \n", "def add_watermark_to_image_sequence(pil_images, base_blob_name):\n", " \"\"\"\n", " Adds a watermark to a sequence of PIL images and saves as a WEBP animation.\n", "\n", " Args:\n", " pil_images: A list of PIL Image objects.\n", " base_blob_name: The base name of the blob (used for naming the output).\n", "\n", " Returns:\n", " The filename of the saved WEBP animation.\n", " \"\"\"\n", "\n", " watermarked_images = []\n", " for img in pil_images:\n", " img = add_watermark_to_image(img)\n", " watermarked_images.append(img)\n", "\n", " # Save the images as a WEBP animation\n", " output_filename = f\"{base_blob_name.split('.')[0]}_watermarked.webp\"\n", " imageio.mimsave(output_filename, watermarked_images, fps=24) # Adjust fps as needed\n", "\n", " return output_filename\n", "\n", "def add_watermark_to_image(img):\n", " \"\"\"\n", " Adds a watermark to a single PIL Image.\n", "\n", " Args:\n", " img: A PIL Image object.\n", "\n", " Returns:\n", " A PIL Image object with the watermark added.\n", " \"\"\"\n", "\n", " # Calculate position (bottom right corner)\n", " padding = 12\n", " x = img.width - WATERMARK_SIZE - padding\n", " y = img.height - WATERMARK_SIZE - padding\n", "\n", " background_brightness = analyze_background_brightness(img, x, y, WATERMARK_SIZE)\n", " print(f\"background_brightness: {background_brightness}\")\n", "\n", " # Generate watermark image (replace this with your actual watermark generation)\n", " watermark = generate_watermark(WATERMARK_SIZE, background_brightness)\n", "\n", " # Overlay the watermark\n", " img.paste(watermark, (x, y), watermark)\n", "\n", " return img\n", "\n", "\n", "def analyze_background_brightness(img, x, y, size):\n", " \"\"\"\n", " Analyzes the average brightness of a region in the image.\n", "\n", " Args:\n", " img: A PIL Image object.\n", " x: The x-coordinate of the top-left corner of the region.\n", " y: The y-coordinate of the top-left corner of the region.\n", " size: The size of the region (square).\n", "\n", " Returns:\n", " The average brightness of the region as an integer.\n", " \"\"\"\n", " region = img.crop((x, y, x + size, y + size))\n", " pixels = np.array(region)\n", " total_brightness = np.sum(\n", " 0.299 * pixels[:, :, 0] + 0.587 * pixels[:, :, 1] + 0.114 * pixels[:, :, 2]\n", " ) / 1000\n", " print(f\"total_brightness: {total_brightness}\")\n", " return max(0, min(255, total_brightness)) \n", "\n", "def generate_watermark(size, background_brightness):\n", " \"\"\"\n", " Generates a watermark image from an SVG string.\n", "\n", " Args:\n", " size: The size of the watermark (square).\n", " background_brightness: The background brightness at the watermark position.\n", "\n", " Returns:\n", " A PIL Image object representing the watermark.\n", " \"\"\"\n", "\n", " # Determine watermark color based on background brightness\n", " watermark_color = (0, 0, 0, 165) if background_brightness > 128 else (255, 255, 255, 165)\n", "\n", " # Parse the SVG string\n", " svg_tree = etree.fromstring(WATERMARK)\n", "\n", " # Find the path element and set its fill attribute\n", " path_element = svg_tree.find(\".//{http://www.w3.org/2000/svg}path\")\n", " if path_element is not None:\n", " r, g, b, a = watermark_color\n", " fill_color = f\"rgba({r},{g},{b},{a/255})\" # Convert to rgba string\n", " path_element.set(\"fill\", fill_color)\n", "\n", " # Convert the modified SVG tree back to a string\n", " modified_svg = etree.tostring(svg_tree, encoding=\"unicode\")\n", "\n", " # Render the modified SVG to a PNG image with a transparent background\n", " png_data = cairosvg.svg2png(\n", " bytestring=modified_svg,\n", " output_width=size,\n", " output_height=size,\n", " background_color=\"transparent\"\n", " )\n", " watermark_img = Image.open(BytesIO(png_data))\n", "\n", " # Convert the watermark to RGBA to handle transparency\n", " watermark_img = watermark_img.convert(\"RGBA\")\n", "\n", " return watermark_img" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "ename": "AttributeError", "evalue": "'numpy.ndarray' object has no attribute 'width'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[35], line 15\u001b[0m\n\u001b[1;32m 13\u001b[0m start_time \u001b[38;5;241m=\u001b[39m time\u001b[38;5;241m.\u001b[39mtime()\n\u001b[1;32m 14\u001b[0m \u001b[38;5;66;03m# Add the watermark\u001b[39;00m\n\u001b[0;32m---> 15\u001b[0m watermarked_img \u001b[38;5;241m=\u001b[39m \u001b[43madd_watermark_to_image_sequence\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43marray\u001b[49m\u001b[43m(\u001b[49m\u001b[43mimg\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mvideo_72b0b56c_0c40_40ff_89d2_2dd1cb01a163_2fbca50b_3e1b_42e6_9391_c2b3efa091ad\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 16\u001b[0m end_time \u001b[38;5;241m=\u001b[39m time\u001b[38;5;241m.\u001b[39mtime()\n\u001b[1;32m 17\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mTime taken: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mend_time\u001b[38;5;250m \u001b[39m\u001b[38;5;241m-\u001b[39m\u001b[38;5;250m \u001b[39mstart_time\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m seconds\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", "Cell \u001b[0;32mIn[34], line 54\u001b[0m, in \u001b[0;36madd_watermark_to_image_sequence\u001b[0;34m(pil_images, base_blob_name)\u001b[0m\n\u001b[1;32m 52\u001b[0m watermarked_images \u001b[38;5;241m=\u001b[39m []\n\u001b[1;32m 53\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m img \u001b[38;5;129;01min\u001b[39;00m pil_images:\n\u001b[0;32m---> 54\u001b[0m img \u001b[38;5;241m=\u001b[39m \u001b[43madd_watermark_to_image\u001b[49m\u001b[43m(\u001b[49m\u001b[43mimg\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 55\u001b[0m watermarked_images\u001b[38;5;241m.\u001b[39mappend(img)\n\u001b[1;32m 57\u001b[0m \u001b[38;5;66;03m# Save the images as a WEBP animation\u001b[39;00m\n", "Cell \u001b[0;32mIn[34], line 77\u001b[0m, in \u001b[0;36madd_watermark_to_image\u001b[0;34m(img)\u001b[0m\n\u001b[1;32m 75\u001b[0m \u001b[38;5;66;03m# Calculate position (bottom right corner)\u001b[39;00m\n\u001b[1;32m 76\u001b[0m padding \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m12\u001b[39m\n\u001b[0;32m---> 77\u001b[0m x \u001b[38;5;241m=\u001b[39m \u001b[43mimg\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mwidth\u001b[49m \u001b[38;5;241m-\u001b[39m WATERMARK_SIZE \u001b[38;5;241m-\u001b[39m padding\n\u001b[1;32m 78\u001b[0m y \u001b[38;5;241m=\u001b[39m img\u001b[38;5;241m.\u001b[39mheight \u001b[38;5;241m-\u001b[39m WATERMARK_SIZE \u001b[38;5;241m-\u001b[39m padding\n\u001b[1;32m 80\u001b[0m background_brightness \u001b[38;5;241m=\u001b[39m analyze_background_brightness(img, x, y, WATERMARK_SIZE)\n", "\u001b[0;31mAttributeError\u001b[0m: 'numpy.ndarray' object has no attribute 'width'" ] } ], "source": [ "# Load the webp image using the requests library\n", "import time\n", "import requests\n", "\n", "\n", "image_url = \"https://media.memedeck.xyz/memes/user:d38ee417_a500_4cd4_a455_432c3cbb61fe/video_gen/video_72b0b56c_0c40_40ff_89d2_2dd1cb01a163_2fbca50b_3e1b_42e6_9391_c2b3efa091ad.webp\" # Example webp image URL\n", "response = requests.get(image_url, stream=True)\n", "response.raise_for_status() # Raise an exception for bad status codes\n", "\n", "# Open the image using PIL\n", "img = Image.open(response.raw)\n", "\n", "# img_to_tensor = img_to_tensor(img)\n", "\n", "start_time = time.time()\n", "# Add the watermark\n", "\n", "watermarked_img = add_watermark_to_image_sequence(img, 'video_72b0b56c_0c40_40ff_89d2_2dd1cb01a163_2fbca50b_3e1b_42e6_9391_c2b3efa091ad')\n", "end_time = time.time()\n", "print(f\"Time taken: {end_time - start_time} seconds\")\n", "\n", "# Save the watermarked image (optional)\n", "# watermarked_img.save(\"watermarked_image.webp\")" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: lxml in /home/holium/ComfyUI/comfy-venv/lib/python3.12/site-packages (5.3.0)\n" ] } ], "source": [ "!pip install lxml" ] } ], "metadata": { "kernelspec": { "display_name": "comfy-venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 2 }