diff --git a/image-tools/README.md b/image-tools/README.md new file mode 100644 index 0000000..575a235 --- /dev/null +++ b/image-tools/README.md @@ -0,0 +1,101 @@ +# Image Tools + + +Collection of bash scripts for image processing and optimization. + +## Scripts + +### optimize-png.sh + +Script to minimize PNG images + +**Usage:** +```bash +./optimize-png.sh [colors] file1.png file2.png ... +./optimize-png.sh [colors] *.png +``` +Or select files in Nemo file manager and run as script + +**Parameters:** +- `colors` - Number of colors (8-256, default: 256) +- `files` - PNG files to minimize + +**Examples:** +```bash +./optimize-png.sh image1.png image2.png # Minimize specific files with 256 colors +./optimize-png.sh 128 *.png # Minimize all PNG files with 128 colors +./optimize-png.sh 64 graphics/*.png # Minimize PNG files in graphics folder +``` + +**Features:** +- Minimized images will be saved in the 'min' subdirectory +- When used as Nemo script, a dialog will ask for colors +- Dual-mode operation (GUI/Terminal) +- Progress tracking and batch processing +- Quality control with color reduction + +**Dependencies:** +- `pngquant` for PNG optimization +- `zenity` for GUI dialogs (usually pre-installed) + +--- + +### optimize-jpg.sh + +Script to compress JPG images + +**Usage:** +```bash +./optimize-jpg.sh [quality] file1.jpg file2.jpg ... +./optimize-jpg.sh [quality] *.jpg +``` +Or select files in Nemo file manager and run as script + +**Parameters:** +- `quality` - Compression quality (1-100, default: 90) +- `files` - JPG/JPEG files to compress + +**Examples:** +```bash +./optimize-jpg.sh photo1.jpg photo2.jpg # Compress specific files with quality 90 +./optimize-jpg.sh 85 *.jpg # Compress all JPG files with quality 85 +./optimize-jpg.sh 75 vacation/*.jpeg # Compress JPEG files in vacation folder +``` + +**Features:** +- Compressed images will be saved in the 'min' subdirectory +- When used as Nemo script, a dialog will ask for quality +- Dual-mode operation (GUI/Terminal) +- Progress tracking and batch processing +- Quality control with compression levels + +**Dependencies:** +- `imagemagick` for JPG compression (mogrify command) +- `zenity` for GUI dialogs (usually pre-installed) + +## Installation + +1. Install dependencies: +```bash +sudo apt install pngquant imagemagick # Ubuntu/Debian +sudo dnf install pngquant ImageMagick # Fedora +# Note: zenity is usually pre-installed with desktop environments +``` + +2. Make scripts executable: +```bash +chmod +x *.sh +``` + +3. For use as Nemo scripts, copy to: +```bash +~/.local/share/nemo/scripts/ +``` + +## Notes + +All scripts support dual-mode operation: +- **Terminal mode**: When run from command line +- **GUI mode**: When run as Nemo file manager scripts with zenity dialogs + +Both scripts create a 'min' subdirectory for optimized output files to preserve originals. \ No newline at end of file diff --git a/image-tools/optimize-jpg.sh b/image-tools/optimize-jpg.sh new file mode 100644 index 0000000..f3be04d --- /dev/null +++ b/image-tools/optimize-jpg.sh @@ -0,0 +1,297 @@ +#!/bin/bash + +# Script to compress JPG images with progress bar +# Usage: ./minimize-jpg.sh [quality] file1.jpg file2.jpg ... +# Usage: ./minimize-jpg.sh [quality] *.jpg +# Works as Nemo script with selected files +# Default quality: 90 + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Function to get quality from user via dialog (for Nemo) +get_quality_dialog() { + local quality=90 + + # Try zenity + if command -v zenity &> /dev/null; then + quality=$(zenity --entry \ + --title="JPG Compression Quality" \ + --text="Enter compression quality (1-100):" \ + --entry-text="90" \ + 2>/dev/null) + + # Check if user cancelled or entered invalid value + if [ $? -ne 0 ] || [ -z "$quality" ]; then + echo "90" + return + fi + else + # No dialog available, use default + echo "90" + return + fi + + # Validate quality + if [[ "$quality" =~ ^[0-9]+$ ]] && [ "$quality" -ge 1 ] && [ "$quality" -le 100 ]; then + echo "$quality" + else + echo "90" + fi +} +check_imagemagick() { + if ! command -v mogrify &> /dev/null; then + echo -e "${RED}Error: ImageMagick is not installed.${NC}" + echo -e "${YELLOW}Install ImageMagick with:${NC}" + echo " Ubuntu/Debian: sudo apt-get install imagemagick" + echo " CentOS/RHEL: sudo yum install ImageMagick" + echo " Arch: sudo pacman -S imagemagick" + exit 1 + fi +} + +# Main function +main() { + local quality=90 + local file_args=() + local quality_was_explicit=false + + # Parse arguments + for arg in "$@"; do + if [[ "$arg" =~ ^[0-9]+$ ]] && [ "$arg" -ge 1 ] && [ "$arg" -le 100 ]; then + quality="$arg" + quality_was_explicit=true + else + # Add all non-numeric arguments as potential file paths + file_args+=("$arg") + fi + done + + # Check if ImageMagick is installed + check_imagemagick + + # Create output directory + local output_dir="min" + if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" + echo -e "${GREEN}Created output directory: $output_dir${NC}" + fi + + # Get files to process + local jpg_files=() + + # If we have file arguments, process them + if [ ${#file_args[@]} -gt 0 ]; then + # Process file arguments (expand patterns and check files) + for pattern in "${file_args[@]}"; do + # Use shell expansion for patterns like *.jpg + for file in $pattern; do + if [[ -f "$file" ]] && [[ "$file" =~ \.(jpg|jpeg|JPG|JPEG)$ ]]; then + jpg_files+=("$file") + fi + done + done + else + echo -e "${RED}Error: No files specified.${NC}" + echo -e "${YELLOW}Usage from terminal: $0 [quality] file1.jpg file2.jpg ...${NC}" + echo -e "${YELLOW}Usage from terminal: $0 [quality] *.jpg${NC}" + echo -e "${YELLOW}Or select files in Nemo and run as script${NC}" + exit 1 + fi + + if [ ${#jpg_files[@]} -eq 0 ]; then + echo -e "${YELLOW}No JPG files found to process.${NC}" + exit 0 + fi + + local total_files=${#jpg_files[@]} + local total_size_before=0 + local total_size_after=0 + + # Detect if running from Nemo (file manager) or terminal + local use_gui=false + local quality_from_dialog=false + local original_quality=$quality + + # Only use GUI if: + # 1. Quality wasn't explicitly set + # 2. We're likely running from Nemo (NEMO_SCRIPT_SELECTED_FILE_PATHS is set) + # 3. zenity is available + if [ "$quality_was_explicit" = false ] && [ -n "$NEMO_SCRIPT_SELECTED_FILE_PATHS" ] && command -v zenity &> /dev/null; then + local dialog_quality + dialog_quality=$(get_quality_dialog) + if [ -n "$dialog_quality" ]; then + quality="$dialog_quality" + quality_from_dialog=true + use_gui=true + fi + fi + + # Show initial info only for terminal + if [ "$use_gui" = false ]; then + echo -e "${GREEN}JPG compression started${NC}" + echo -e "${BLUE}Quality set to: ${quality}%${NC}" + echo -e "${BLUE}Files to process: ${total_files}${NC}" + echo -e "${BLUE}Output directory: ${output_dir}${NC}" + echo "" + fi + + # Calculate total size before compression + for file in "${jpg_files[@]}"; do + if [ -f "$file" ]; then + size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null) + total_size_before=$((total_size_before + size)) + fi + done + + # Process each file with appropriate progress display + local count=0 + if [ "$use_gui" = true ]; then + # Use zenity progress bar for GUI + ( + for file in "${jpg_files[@]}"; do + if [ -f "$file" ]; then + count=$((count + 1)) + filename=$(basename "$file") + output_file="${output_dir}/${filename}" + + echo "# Compressing $filename... ($count/$total_files)" + + # Copy and compress the file + cp "$file" "$output_file" + mogrify -quality "$quality" "$output_file" + + echo "$((count * 100 / total_files))" + fi + done + ) | zenity --progress --title="JPG Compression" --text="Initializing..." --percentage=0 --auto-close + + # Check if user cancelled + if [ $? -ne 0 ]; then + zenity --error --text="Compression was cancelled." + exit 1 + fi + else + # Use terminal progress bar + for file in "${jpg_files[@]}"; do + if [ -f "$file" ]; then + count=$((count + 1)) + filename=$(basename "$file") + output_file="${output_dir}/${filename}" + + # Show terminal progress + local percentage=$((count * 100 / total_files)) + printf "\r${BLUE}[%3d%%] Processing $filename ($count/$total_files)${NC}" "$percentage" + + # Copy and compress the file + cp "$file" "$output_file" + mogrify -quality "$quality" "$output_file" + fi + done + echo "" # New line after progress + fi + + # Calculate total size after compression + for file in "${jpg_files[@]}"; do + filename=$(basename "$file") + output_file="${output_dir}/${filename}" + if [ -f "$output_file" ]; then + size=$(stat -f%z "$output_file" 2>/dev/null || stat -c%s "$output_file" 2>/dev/null) + total_size_after=$((total_size_after + size)) + fi + done + + # Calculate statistics + local saved_bytes=$((total_size_before - total_size_after)) + local saved_percentage=0 + if [ "$total_size_before" -gt 0 ]; then + saved_percentage=$((saved_bytes * 100 / total_size_before)) + fi + + # Convert bytes to readable format with automatic KB/MB selection + local size_before_display + local size_after_display + local saved_display + local unit_before="MB" + local unit_after="MB" + local unit_saved="MB" + + # Check if sizes are less than 1MB to display in KB + if [ "$total_size_before" -lt 1048576 ]; then + size_before_display=$((total_size_before / 1024)) + unit_before="KB" + else + size_before_display=$((total_size_before / 1024 / 1024)) + fi + + if [ "$total_size_after" -lt 1048576 ]; then + size_after_display=$((total_size_after / 1024)) + unit_after="KB" + else + size_after_display=$((total_size_after / 1024 / 1024)) + fi + + if [ "$saved_bytes" -lt 1048576 ]; then + saved_display=$((saved_bytes / 1024)) + unit_saved="KB" + else + saved_display=$((saved_bytes / 1024 / 1024)) + fi + + # Show final report + if [ "$use_gui" = true ]; then + # Show report with zenity + local report_message="✓ Compression completed!\n\n" + report_message+="Files processed: ${total_files}\n" + report_message+="Original size: ${size_before_display} ${unit_before}\n" + report_message+="Compressed size: ${size_after_display} ${unit_after}\n" + report_message+="Space saved: ${saved_display} ${unit_saved} (${saved_percentage}%)\n" + report_message+="Quality used: ${quality}%\n" + report_message+="Output directory: ${output_dir}/" + + zenity --info --title="JPG Compression Complete" --text="$report_message" + else + # Show report in terminal + echo "" + echo -e "${GREEN}✓ Compression completed!${NC}" + echo "" + echo -e "${BLUE}Statistics:${NC}" + echo -e " Files processed: ${total_files}" + echo -e " Original size: ${size_before_display} ${unit_before}" + echo -e " Compressed size: ${size_after_display} ${unit_after}" + echo -e " Space saved: ${saved_display} ${unit_saved} (${saved_percentage}%)" + echo -e " Quality used: ${quality}%" + echo -e " Output directory: ${output_dir}/" + fi +} + +# Show help if requested +if [[ "$1" == "-h" || "$1" == "--help" ]]; then + echo -e "${GREEN}Script to compress JPG images${NC}" + echo "" + echo -e "${YELLOW}Usage:${NC}" + echo " $0 [quality] file1.jpg file2.jpg ..." + echo " $0 [quality] *.jpg" + echo " Or select files in Nemo file manager and run as script" + echo "" + echo -e "${YELLOW}Parameters:${NC}" + echo " quality Compression quality (1-100, default: 90)" + echo " files JPG/JPEG files to compress" + echo "" + echo -e "${YELLOW}Examples:${NC}" + echo " $0 photo1.jpg photo2.jpg # Compress specific files with quality 90" + echo " $0 85 *.jpg # Compress all JPG files with quality 85" + echo " $0 75 vacation/*.jpeg # Compress JPEG files in vacation folder" + echo "" + echo -e "${BLUE}Note: Compressed images will be saved in the 'min' subdirectory${NC}" + echo -e "${BLUE} When used as Nemo script, a dialog will ask for quality${NC}" + echo -e "${BLUE} Requires zenity for GUI dialog${NC}" + exit 0 +fi + +# Execute main +main "$@" \ No newline at end of file diff --git a/image-tools/optimize-png.sh b/image-tools/optimize-png.sh new file mode 100644 index 0000000..dfdb9c8 --- /dev/null +++ b/image-tools/optimize-png.sh @@ -0,0 +1,297 @@ +#!/bin/bash + +# Script to minimize PNG images with progress bar +# Usage: ./minimize-png.sh [colors] file1.png file2.png ... +# Usage: ./minimize-png.sh [colors] *.png +# Works as Nemo script with selected files +# Default colors: 256 + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Function to get colors from user via dialog (for Nemo) +get_colors_dialog() { + local colors=256 + + # Try zenity + if command -v zenity &> /dev/null; then + colors=$(zenity --entry \ + --title="PNG Color Reduction" \ + --text="Enter number of colors (8-256):" \ + --entry-text="256" \ + 2>/dev/null) + + # Check if user cancelled or entered invalid value + if [ $? -ne 0 ] || [ -z "$colors" ]; then + echo "256" + return + fi + else + # No dialog available, use default + echo "256" + return + fi + + # Validate colors + if [[ "$colors" =~ ^[0-9]+$ ]] && [ "$colors" -ge 8 ] && [ "$colors" -le 256 ]; then + echo "$colors" + else + echo "256" + fi +} + +# Function to check if pngquant is installed +check_pngquant() { + if ! command -v pngquant &> /dev/null; then + echo -e "${RED}Error: pngquant is not installed.${NC}" + echo -e "${YELLOW}Install pngquant with:${NC}" + echo " Ubuntu/Debian: sudo apt-get install pngquant" + echo " CentOS/RHEL: sudo yum install pngquant" + echo " Arch: sudo pacman -S pngquant" + exit 1 + fi +} + +# Main function +main() { + local colors=256 + local file_args=() + local colors_was_explicit=false + + # Parse arguments + for arg in "$@"; do + if [[ "$arg" =~ ^[0-9]+$ ]] && [ "$arg" -ge 8 ] && [ "$arg" -le 256 ]; then + colors="$arg" + colors_was_explicit=true + else + # Add all non-numeric arguments as potential file paths + file_args+=("$arg") + fi + done + + # Check pngquant + check_pngquant + + # Create output directory + local output_dir="min" + if [ ! -d "$output_dir" ]; then + mkdir -p "$output_dir" + echo -e "${GREEN}Created output directory: $output_dir${NC}" + fi + + # Get files to process + local png_files=() + + # If we have file arguments, process them + if [ ${#file_args[@]} -gt 0 ]; then + # Process file arguments (expand patterns and check files) + for pattern in "${file_args[@]}"; do + # Use shell expansion for patterns like *.png + for file in $pattern; do + if [[ -f "$file" ]] && [[ "$file" =~ \.(png|PNG)$ ]]; then + png_files+=("$file") + fi + done + done + else + echo -e "${RED}Error: No files specified.${NC}" + echo -e "${YELLOW}Usage from terminal: $0 [colors] file1.png file2.png ...${NC}" + echo -e "${YELLOW}Usage from terminal: $0 [colors] *.png${NC}" + echo -e "${YELLOW}Or select files in Nemo and run as script${NC}" + exit 1 + fi + + if [ ${#png_files[@]} -eq 0 ]; then + echo -e "${YELLOW}No PNG files found to process.${NC}" + exit 0 + fi + + local total_files=${#png_files[@]} + local total_size_before=0 + local total_size_after=0 + + # Detect if running from Nemo (file manager) or terminal + local use_gui=false + local colors_from_dialog=false + local original_colors=$colors + + # Only use GUI if: + # 1. Colors wasn't explicitly set + # 2. We're likely running from Nemo (NEMO_SCRIPT_SELECTED_FILE_PATHS is set) + # 3. zenity is available + if [ "$colors_was_explicit" = false ] && [ -n "$NEMO_SCRIPT_SELECTED_FILE_PATHS" ] && command -v zenity &> /dev/null; then + local dialog_colors + dialog_colors=$(get_colors_dialog) + if [ -n "$dialog_colors" ]; then + colors="$dialog_colors" + colors_from_dialog=true + use_gui=true + fi + fi + + # Show initial info only for terminal + if [ "$use_gui" = false ]; then + echo -e "${GREEN}PNG minimization started${NC}" + echo -e "${BLUE}Colors set to: ${colors}${NC}" + echo -e "${BLUE}Files to process: ${total_files}${NC}" + echo -e "${BLUE}Output directory: ${output_dir}${NC}" + echo "" + fi + + # Calculate total size before compression + for file in "${png_files[@]}"; do + if [ -f "$file" ]; then + size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null) + total_size_before=$((total_size_before + size)) + fi + done + + # Process each file with appropriate progress display + local count=0 + if [ "$use_gui" = true ]; then + # Use zenity progress bar for GUI + ( + for file in "${png_files[@]}"; do + if [ -f "$file" ]; then + count=$((count + 1)) + filename=$(basename "$file") + output_file="${output_dir}/${filename}" + + echo "# Minimizing $filename... ($count/$total_files)" + + # Minimize the file + pngquant --output "$output_file" --force "$colors" "$file" + + echo "$((count * 100 / total_files))" + fi + done + ) | zenity --progress --title="PNG Minimization" --text="Initializing..." --percentage=0 --auto-close + + # Check if user cancelled + if [ $? -ne 0 ]; then + zenity --error --text="Minimization was cancelled." + exit 1 + fi + else + # Use terminal progress bar + for file in "${png_files[@]}"; do + if [ -f "$file" ]; then + count=$((count + 1)) + filename=$(basename "$file") + output_file="${output_dir}/${filename}" + + # Show terminal progress + local percentage=$((count * 100 / total_files)) + printf "\r${BLUE}[%3d%%] Processing $filename ($count/$total_files)${NC}" "$percentage" + + # Minimize the file + pngquant --output "$output_file" --force "$colors" "$file" + fi + done + echo "" # New line after progress + fi + + # Calculate total size after compression + for file in "${png_files[@]}"; do + filename=$(basename "$file") + output_file="${output_dir}/${filename}" + if [ -f "$output_file" ]; then + size=$(stat -f%z "$output_file" 2>/dev/null || stat -c%s "$output_file" 2>/dev/null) + total_size_after=$((total_size_after + size)) + fi + done + + # Calculate statistics + local saved_bytes=$((total_size_before - total_size_after)) + local saved_percentage=0 + if [ "$total_size_before" -gt 0 ]; then + saved_percentage=$((saved_bytes * 100 / total_size_before)) + fi + + # Convert bytes to readable format with automatic KB/MB selection + local size_before_display + local size_after_display + local saved_display + local unit_before="MB" + local unit_after="MB" + local unit_saved="MB" + + # Check if sizes are less than 1MB to display in KB + if [ "$total_size_before" -lt 1048576 ]; then + size_before_display=$((total_size_before / 1024)) + unit_before="KB" + else + size_before_display=$((total_size_before / 1024 / 1024)) + fi + + if [ "$total_size_after" -lt 1048576 ]; then + size_after_display=$((total_size_after / 1024)) + unit_after="KB" + else + size_after_display=$((total_size_after / 1024 / 1024)) + fi + + if [ "$saved_bytes" -lt 1048576 ]; then + saved_display=$((saved_bytes / 1024)) + unit_saved="KB" + else + saved_display=$((saved_bytes / 1024 / 1024)) + fi + + # Show final report + if [ "$use_gui" = true ]; then + # Show report with zenity + local report_message="✓ Minimization completed!\n\n" + report_message+="Files processed: ${total_files}\n" + report_message+="Original size: ${size_before_display} ${unit_before}\n" + report_message+="Minimized size: ${size_after_display} ${unit_after}\n" + report_message+="Space saved: ${saved_display} ${unit_saved} (${saved_percentage}%)\n" + report_message+="Colors used: ${colors}\n" + report_message+="Output directory: ${output_dir}/" + + zenity --info --title="PNG Minimization Complete" --text="$report_message" + else + # Show report in terminal + echo "" + echo -e "${GREEN}✓ Minimization completed!${NC}" + echo "" + echo -e "${BLUE}Statistics:${NC}" + echo -e " Files processed: ${total_files}" + echo -e " Original size: ${size_before_display} ${unit_before}" + echo -e " Minimized size: ${size_after_display} ${unit_after}" + echo -e " Space saved: ${saved_display} ${unit_saved} (${saved_percentage}%)" + echo -e " Colors used: ${colors}" + echo -e " Output directory: ${output_dir}/" + fi +} + +# Show help if requested +if [[ "$1" == "-h" || "$1" == "--help" ]]; then + echo -e "${GREEN}Script to minimize PNG images${NC}" + echo "" + echo -e "${YELLOW}Usage:${NC}" + echo " $0 [colors] file1.png file2.png ..." + echo " $0 [colors] *.png" + echo " Or select files in Nemo file manager and run as script" + echo "" + echo -e "${YELLOW}Parameters:${NC}" + echo " colors Number of colors (8-256, default: 256)" + echo " files PNG files to minimize" + echo "" + echo -e "${YELLOW}Examples:${NC}" + echo " $0 image1.png image2.png # Minimize specific files with 256 colors" + echo " $0 128 *.png # Minimize all PNG files with 128 colors" + echo " $0 64 graphics/*.png # Minimize PNG files in graphics folder" + echo "" + echo -e "${BLUE}Note: Minimized images will be saved in the 'min' subdirectory${NC}" + echo -e "${BLUE} When used as Nemo script, a dialog will ask for colors${NC}" + echo -e "${BLUE} Requires pngquant for PNG optimization${NC}" + exit 0 +fi + +# Execute main +main "$@"