Backlinking tool & Img optimization, PIL & Tinify API

This commit is contained in:
ajaysi
2024-08-15 09:47:12 +05:30
parent 43bba7e73e
commit fe59ec07cc
6 changed files with 206 additions and 116 deletions

View File

@@ -1,4 +1,4 @@
> [!NOTE] <p><em>ALwrity is in Work in Progress (WIP). All in One Content platform > [!NOTE] <p><em>ALwrity is All in One Content platform for content writers, without AI tooling knowledge. WIP.
Not just AI Writers, ALwrity is a complete content life cycle platform with **Content planning & Research, Personlized Content Generation, Content SEO audits, Content Scheduling/publishing, Analytics & monitoring & more**. We are busy building blocks for each phase of content life cycle with AI. We'd love your feedback or contributions.</em></p> Not just AI Writers, ALwrity is a complete content life cycle platform with **Content planning & Research, Personlized Content Generation, Content SEO audits, Content Scheduling/publishing, Analytics & monitoring & more**. We are busy building blocks for each phase of content life cycle with AI. We'd love your feedback or contributions.</em></p>
# How to ALwrity - Getting Started # How to ALwrity - Getting Started
@@ -6,7 +6,15 @@ Not just AI Writers, ALwrity is a complete content life cycle platform with **Co
ALwrity assists content creators and digital marketers in keyword web research, ![AI writers](https://www.alwrity.com/ai-writing-tools) & ![Social media content generation](https://www.alwrity.com/ai-youtube-script-writer) & ![AI Copywriting](https://www.alwrity.com/ai-copywriting-formula-generator). ALwrity assists content creators and digital marketers in keyword web research, ![AI writers](https://www.alwrity.com/ai-writing-tools) & ![Social media content generation](https://www.alwrity.com/ai-youtube-script-writer) & ![AI Copywriting](https://www.alwrity.com/ai-copywriting-formula-generator).
Our toolkit integrates **(OpenAI, Gemini, Anthropic)** AI models for text generation, image creation **(Stability.ai), STT(whisper, AssemblyAI)** and AI Web research **(Tavily AI, exa AI, Serper.dev)**, streamlining your content creation pipeline and ensuring high-quality output with minimal effort. Our toolkit integrates **(OpenAI, Gemini, Anthropic)** AI models for text generation, image creation **(Stability.ai), STT(whisper, AssemblyAI)** and AI Web research **(Tavily AI, exa AI, Serper.dev)**, streamlining your content creation pipeline and ensuring high-quality output with minimal effort.
![](https://github.com/AJaySi/AI-Writer/blob/main/lib/workspace/keyword_blog.gif) - ![Generate Content Calender for Months](https://www.alwrity.com/post/automating-content-calendars-with-ai-agents)
- ![Specilized AI writers for every need & platform](https://github.com/AJaySi/AI-Writer/wiki/Features-of-ALwrity-AI-writer)
- ![ALwrity AI SEO Tools](https://github.com/AJaySi/AI-Writer/wiki/ALwrity-AI-SEO-Tools)
- ![ALwrity Web Researcher](https://github.com/AJaySi/AI-Writer/wiki/Alwrity-AI-Web-Research-Details-for-content-writing)
- RoadMap - Coming Soon..
---
> ![](https://github.com/AJaySi/AI-Writer/blob/main/lib/workspace/keyword_blog.gif)
---
### Option 1: Get Started Now, [Visit alwrity.com](https://www.alwrity.com/ai-writing-tools) ### Option 1: Get Started Now, [Visit alwrity.com](https://www.alwrity.com/ai-writing-tools)
> [!NOTE] <p>You will find AI content writing tools, which are Free & No-Signup. > [!NOTE] <p>You will find AI content writing tools, which are Free & No-Signup.

View File

@@ -0,0 +1,190 @@
import os
import sys
import tinify
from PIL import Image
from loguru import logger
from dotenv import load_dotenv
import streamlit as st
# Load environment variables
load_dotenv()
# Set Tinyfy API key from environment variable
tinify_key = os.getenv('TINIFY_API_KEY')
if tinify_key:
tinify.key = tinify_key
# Configure logger
logger.remove()
logger.add(
sys.stdout,
colorize=True,
format="<level>{level}</level>|<green>{file}:{line}:{function}</green>| {message}"
)
def compress_image(image, quality=45, resize=None, preserve_exif=False):
"""
Compress and optionally resize an image.
Args:
image (PIL.Image): Image object to compress.
quality (int): Quality of the output image (1-100).
resize (tuple): Tuple (width, height) to resize the image.
preserve_exif (bool): Preserve EXIF data if True.
Returns:
PIL.Image: The compressed and resized image object.
"""
try:
# Ensure image is in a compatible mode for JPEG/WebP
if image.mode == 'RGBA':
logger.info("Converting RGBA image to RGB.")
image = image.convert('RGB')
exif = image.info.get('exif') if preserve_exif and 'exif' in image.info else None
# Resize image if needed
if resize:
image = image.resize(resize, Image.LANCZOS)
logger.info(f"Resized image to {resize}")
# Save compressed image
try:
logger.info("Attempting to save the compressed image with EXIF data (if any).")
image.save("temp.jpg", optimize=True, quality=quality, exif=exif)
except Exception as exif_error:
logger.warning(f"Error saving image with EXIF: {exif_error}. Saving without EXIF.")
image.save("temp.jpg", optimize=True, quality=quality)
logger.info("Image compression successful.")
return Image.open("temp.jpg")
except Exception as e:
logger.error(f"Error compressing image: {e}")
st.error("Failed to compress the image. Please try again.")
return None
def convert_to_webp(image, image_path):
"""
Convert an image to WebP format.
Args:
image (PIL.Image): Image object to convert.
image_path (str): Path to save the WebP image.
Returns:
str: Path to the WebP image.
"""
try:
webp_path = os.path.splitext(image_path)[0] + '.webp'
image.save(webp_path, 'WEBP', quality=80, method=6)
return webp_path
except Exception as e:
logger.error(f"Error converting image to WebP: {e}")
st.error("Failed to convert the image to WebP format. Please try again.")
return None
def compress_image_tinyfy(image_path):
"""
Compress an image using Tinyfy API.
Args:
image_path (str): Path to the image to be compressed.
Returns:
None
"""
try:
if not tinify.key:
logger.warning("Tinyfy API key is not set. Skipping Tinyfy compression.")
return
source = tinify.from_file(image_path)
source.to_file(image_path)
logger.info("Tinyfy compression successful.")
except Exception as e:
logger.error(f"Error during Tinyfy compression: {e}")
st.warning("Tinyfy compression failed. Ensure the API key is set.")
def optimize_image(image, image_path, quality, resize, preserve_exif):
"""
Optimize the image by compressing and converting it to WebP, with optional Tinyfy compression.
Args:
image (PIL.Image): The original image.
image_path (str): The path to the image file.
quality (int): Quality level for compression.
resize (tuple): Dimensions to resize the image.
preserve_exif (bool): Whether to preserve EXIF data.
Returns:
str: Path to the optimized WebP image, or None if failed.
"""
logger.info("Starting image optimization process...")
# Compress the image using Pillow
compressed_image = compress_image(image, quality, resize, preserve_exif)
if compressed_image is None:
return None
# Convert image to WebP format
webp_path = convert_to_webp(compressed_image, image_path)
if webp_path is None:
return None
# Optionally compress the WebP image using Tinyfy API
if tinify.key:
compress_image_tinyfy(webp_path)
else:
logger.info("Tinyfy key not provided, skipping Tinyfy compression.")
return webp_path
def main_img_optimizer():
st.title("ALwrity Image Optimizer")
st.markdown("## Upload an image to optimize its size and format.")
# API Key Input (Optional)
input_tinify_key = st.text_input("Optional: Enter your Tinyfy API Key")
if input_tinify_key:
tinify.key = input_tinify_key
# File Upload
uploaded_file = st.file_uploader("Upload an image", type=['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'])
if uploaded_file:
image = Image.open(uploaded_file)
st.image(image, caption="Original Image", use_column_width=True)
# Image Compression Options
quality = st.slider("Compression Quality", 1, 100, 45)
preserve_exif = st.checkbox("Preserve EXIF Data", value=False)
resize = st.checkbox("Resize Image")
if resize:
width = st.number_input("Width", value=image.width)
height = st.number_input("Height", value=image.height)
resize_dims = (width, height)
else:
resize_dims = None
# Optimize Image
if st.button("Optimize Image"):
with st.spinner("Optimizing..."):
if tinify.key:
st.info("Tinyfy compression will be applied.")
webp_path = optimize_image(image, uploaded_file.name, quality, resize_dims, preserve_exif)
if webp_path:
st.image(webp_path, caption="Optimized Image (WebP)", use_column_width=True)
st.success("Image optimization completed!")
# Provide download link
with open(webp_path, "rb") as file:
st.download_button(
label="Download Optimized Image",
data=file,
file_name=os.path.basename(webp_path),
mime="image/webp"
)

View File

@@ -43,6 +43,7 @@ from lib.ai_seo_tools.content_title_generator import ai_title_generator
from lib.ai_seo_tools.meta_desc_generator import metadesc_generator_main from lib.ai_seo_tools.meta_desc_generator import metadesc_generator_main
from lib.ai_seo_tools.image_alt_text_generator import alt_text_gen from lib.ai_seo_tools.image_alt_text_generator import alt_text_gen
from lib.ai_seo_tools.opengraph_generator import og_tag_generator from lib.ai_seo_tools.opengraph_generator import og_tag_generator
from lib.ai_seo_tools.optimize_images_for_upload import main_img_optimizer
from lib.gpt_providers.text_to_image_generation.main_generate_image_from_prompt import generate_image from lib.gpt_providers.text_to_image_generation.main_generate_image_from_prompt import generate_image
from lib.content_planning_calender.content_planning_agents_alwrity_crew import ai_agents_planner from lib.content_planning_calender.content_planning_agents_alwrity_crew import ai_agents_planner
from ..gpt_providers.text_generation.main_text_generation import llm_text_gen from ..gpt_providers.text_generation.main_text_generation import llm_text_gen
@@ -127,7 +128,8 @@ def ai_seo_tools():
"Generate SEO optimized Blog Titles", "Generate SEO optimized Blog Titles",
"Generate Meta Description for SEO", "Generate Meta Description for SEO",
"Generate Image Alt Text", "Generate Image Alt Text",
"Generate OpenGraph Tags" "Generate OpenGraph Tags",
"Optimize/Resize Image"
] ]
choice = st.selectbox("**👇Select AI SEO Tool:**", options, index=0, format_func=lambda x: f"📝 {x}") choice = st.selectbox("**👇Select AI SEO Tool:**", options, index=0, format_func=lambda x: f"📝 {x}")
@@ -141,6 +143,8 @@ def ai_seo_tools():
alt_text_gen() alt_text_gen()
elif choice == "Generate OpenGraph Tags": elif choice == "Generate OpenGraph Tags":
og_tag_generator() og_tag_generator()
elif choice == "Optimize/Resize Image":
main_img_optimizer()

View File

@@ -1,112 +0,0 @@
import sys
import os
import tinify
from PIL import Image
from loguru import logger
from tqdm import tqdm
from dotenv import load_dotenv
#default directory for .env file is the current directory
#if you set .env in different directory, put the directory address load_dotenv("directory_of_.env)
load_dotenv()
# Retrieve Tinyfy API key from environment variable
tinify.key = os.getenv('TINIFY_API_KEY')
# Configure logger
logger.remove()
logger.add(sys.stdout, colorize=True, format="<level>{level}</level>|<green>{file}:{line}:{function}</green>| {message}")
def compress_image(image_path, quality=45, resize=None, preserve_exif=False):
"""
Compress and optionally resize an image, and overwrite the original image.
Args:
image_path (str): Path to the original image.
quality (int): Quality of the output image (1-100).
resize (tuple): Tuple (width, height) to resize image.
preserve_exif (bool): Preserve EXIF data if True.
"""
if not os.path.exists(image_path):
logger.error(f"Image path does not exist: {image_path}")
return
original_size = os.path.getsize(image_path)
try:
with Image.open(image_path) as img:
img_format = img.format
exif = img.info['exif'] if preserve_exif and 'exif' in img.info else None
if resize:
img = img.resize(resize, Image.ANTIALIAS)
img.save(image_path, format=img_format, quality=quality, optimize=True, exif=exif)
compressed_size = os.path.getsize(image_path)
reduction = (1 - (compressed_size / original_size)) * 100
logger.info(f"Compressed {image_path}, Reduction: {reduction:.2f}%")
except Exception as e:
logger.error(f"Error compressing image {image_path}: {e}")
def is_image_file(filename):
"""
Check if a file is an image based on its extension.
Args:
filename (str): Name of the file to check.
Returns:
bool: True if the file is an image, False otherwise.
"""
valid_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']
return any(filename.lower().endswith(ext) for ext in valid_extensions)
def convert_to_webp(image_path):
"""
Convert an image to WebP format.
Args:
image_path (str): Path to the original image.
Returns:
str: Path to the WebP image.
"""
if not os.path.exists(image_path):
logger.error(f"Image path does not exist: {image_path}")
return
try:
with Image.open(image_path) as img:
webp_path = os.path.splitext(image_path)[0] + '.webp'
img.save(webp_path, 'WEBP')
logger.info(f"Converted {image_path} to WebP")
return webp_path
except Exception as e:
logger.error(f"Error converting image to WebP: {e}")
def compress_image_tinyfy(image_path):
"""
Compress the image using Tinyfy API.
Args:
image_path (str): Path to the original image.
"""
if not os.path.exists(image_path):
logger.error(f"Image path does not exist: {image_path}")
return
try:
source = tinify.from_file(image_path)
source.to_file(image_path)
logger.info(f"Compressed {image_path} using Tinyfy API")
except tinify.Error as e:
logger.error(f"Tinyfy API error: {e}")
def optimize_image(image_path):
image_path = convert_to_webp(image_path)
compress_image_tinyfy(image_path)
compress_image(image_path)
return image_path

View File

@@ -35,4 +35,4 @@ pandas_ta
firecrawl-py firecrawl-py
gTTS gTTS
streamlit-mic-recorder streamlit-mic-recorder
tinify