diff --git a/image-resizer/go.mod b/image-resizer/go.mod new file mode 100644 index 0000000..29d956a --- /dev/null +++ b/image-resizer/go.mod @@ -0,0 +1,5 @@ +module image-resizer + +go 1.21 + +require golang.org/x/image v0.15.0 diff --git a/image-resizer/go.sum b/image-resizer/go.sum new file mode 100644 index 0000000..939e5ae --- /dev/null +++ b/image-resizer/go.sum @@ -0,0 +1,2 @@ +golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= +golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= diff --git a/image-resizer/main.go b/image-resizer/main.go new file mode 100644 index 0000000..85126ce --- /dev/null +++ b/image-resizer/main.go @@ -0,0 +1,188 @@ +package main + +import ( + "fmt" + "image" + "image/jpeg" + "image/png" + "os" + "path/filepath" + "strings" + + _ "image/gif" // Register GIF decoder + _ "image/jpeg" // Register JPEG decoder + _ "image/png" // Register PNG decoder + + "golang.org/x/image/bmp" + "golang.org/x/image/tiff" +) + +// ResizeImage resizes an image to a specified percentage of its original size +func ResizeImage(inputPath, outputPath string, scalePercent int) error { + file, err := os.Open(inputPath) + if err != nil { + return fmt.Errorf("error opening file: %w", err) + } + defer file.Close() + + img, _, err := image.Decode(file) + if err != nil { + return fmt.Errorf("error decoding image: %w", err) + } + + // Get original dimensions + bounds := img.Bounds() + width := bounds.Dx() + height := bounds.Dy() + + // Calculate new dimensions + newWidth := width * scalePercent / 100 + newHeight := height * scalePercent / 100 + + // Create resized image using nearest neighbor (simple approach) + // For better quality, consider using github.com/nfnt/resize + resized := image.NewRGBA(image.Rect(0, 0, newWidth, newHeight)) + + // Simple resampling + for y := 0; y < newHeight; y++ { + for x := 0; x < newWidth; x++ { + srcX := x * width / newWidth + srcY := y * height / newHeight + resized.Set(x, y, img.At(srcX, srcY)) + } + } + + // Create output file + outFile, err := os.Create(outputPath) + if err != nil { + return fmt.Errorf("error creating output file: %w", err) + } + defer outFile.Close() + + // Encode based on format or output extension + ext := strings.ToLower(filepath.Ext(outputPath)) + switch ext { + case ".jpg", ".jpeg": + err = jpeg.Encode(outFile, resized, &jpeg.Options{Quality: 95}) + case ".png": + err = png.Encode(outFile, resized) + case ".gif": + // For GIF, we'd need additional encoding support + err = jpeg.Encode(outFile, resized, &jpeg.Options{Quality: 95}) + case ".bmp": + err = bmp.Encode(outFile, resized) + case ".tiff", ".tif": + err = tiff.Encode(outFile, resized, nil) + case ".webp": + // WebP encoding is complex, save as PNG instead + err = png.Encode(outFile, resized) + default: + // Default to PNG + err = png.Encode(outFile, resized) + } + + if err != nil { + return fmt.Errorf("error encoding image: %w", err) + } + + fmt.Printf("Resized: %s -> %s\n", inputPath, outputPath) + fmt.Printf(" Original: %dx%d, New: %dx%d\n", width, height, newWidth, newHeight) + + return nil +} + +// ResizeImagesInFolder resizes all images in a folder and its subfolders +func ResizeImagesInFolder(folderPath string, scalePercent int, outputFolder string, overwrite bool) error { + // Supported image formats + imageExtensions := map[string]bool{ + ".jpg": true, + ".jpeg": true, + ".png": true, + ".gif": true, + ".bmp": true, + ".tiff": true, + ".webp": true, + } + + folderPath = filepath.Clean(folderPath) + var outputBasePath string + if overwrite { + outputBasePath = folderPath + } else { + if outputFolder == "" { + outputBasePath = filepath.Join(folderPath, "resized") + } else { + outputBasePath = filepath.Clean(outputFolder) + } + } + + // Walk through all files and subdirectories + err := filepath.Walk(folderPath, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + // Skip directories + if info.IsDir() { + return nil + } + + // Check if file has supported image extension + ext := strings.ToLower(filepath.Ext(path)) + if !imageExtensions[ext] { + return nil + } + + // Determine output path + var outputPath string + if overwrite { + outputPath = path + } else { + // Get relative path from folderPath + relPath, err := filepath.Rel(folderPath, path) + if err != nil { + return fmt.Errorf("error getting relative path: %w", err) + } + outputPath = filepath.Join(outputBasePath, relPath) + + // Create output directory if it doesn't exist + outputDir := filepath.Dir(outputPath) + if err := os.MkdirAll(outputDir, 0755); err != nil { + return fmt.Errorf("error creating output directory: %w", err) + } + } + + // Resize the image + if err := ResizeImage(path, outputPath, scalePercent); err != nil { + fmt.Printf("Error processing %s: %v\n", path, err) + } + + return nil + }) + + return err +} + +func main() { + // Configuration + folderPath := `D:\kvtm\kvtm\client\res\common\ui\EventTet2026` // Change to your folder path + scalePercent := 50 // Resize to 50% of original size + overwrite := true // Set to false to save to output folder instead + + fmt.Printf("Image Resizer - Scaling to %d%%\n", scalePercent) + fmt.Printf("Source folder: %s\n", folderPath) + if overwrite { + fmt.Println("Mode: Overwriting original images") + } else { + fmt.Println("Mode: Saving to output folder") + } + fmt.Println(strings.Repeat("-", 50)) + + if err := ResizeImagesInFolder(folderPath, scalePercent, "", overwrite); err != nil { + fmt.Printf("Error: %v\n", err) + os.Exit(1) + } + + fmt.Println(strings.Repeat("-", 50)) + fmt.Println("Done!") +} diff --git a/image-resizer/main.py b/image-resizer/main.py deleted file mode 100644 index e33b925..0000000 --- a/image-resizer/main.py +++ /dev/null @@ -1,98 +0,0 @@ -import os -from pathlib import Path - -from PIL import Image - - -def resize_image(input_path, output_path, scale_percent): - """ - Resize an image to a specified percentage of its original size. - - Args: - input_path: Path to the input image - output_path: Path where the resized image will be saved - scale_percent: Percentage to scale the image (e.g., 50 for 50%) - """ - try: - with Image.open(input_path) as img: - # Calculate new dimensions - width, height = img.size - new_width = int(width * scale_percent / 100) - new_height = int(height * scale_percent / 100) - - # Resize using high-quality resampling - resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) - - # Save the resized image - resized_img.save(output_path) - print(f"Resized: {input_path} -> {output_path}") - print(f" Original: {width}x{height}, New: {new_width}x{new_height}") - except Exception as e: - print(f"Error processing {input_path}: {e}") - - -def resize_images_in_folder( - folder_path, scale_percent, output_folder=None, overwrite=False -): - """ - Resize all images in a folder and its subfolders. - - Args: - folder_path: Path to the folder containing images - scale_percent: Percentage to scale the images (e.g., 50 for 50%) - output_folder: Optional output folder. If None, creates a 'resized' subfolder - overwrite: If True, overwrites original images. If False, saves to output folder - """ - # Supported image formats - image_extensions = {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".webp"} - - # Setup output path - folder_path = Path(folder_path) - if overwrite: - output_base_path = folder_path - else: - if output_folder is None: - output_folder = folder_path / "resized" - else: - output_folder = Path(output_folder) - - # Process all files in folder and subfolders - for root, dirs, files in os.walk(folder_path): - root_path = Path(root) - - # Create relative path structure for output - if not overwrite: - relative_path = root_path.relative_to(folder_path) - current_output_path = output_folder / relative_path - current_output_path.mkdir(parents=True, exist_ok=True) - else: - current_output_path = root_path - - # Process each image file - for file in files: - file_path = root_path / file - file_ext = file_path.suffix.lower() - - if file_ext in image_extensions: - if overwrite: - output_path = file_path - else: - output_path = current_output_path / file - - resize_image(file_path, output_path, scale_percent) - - -if __name__ == "__main__": - # Configuration - FOLDER_PATH = "D:\\kvtm\\kvtm\\client\\res\\common\\ui\\EventTet2026" # Current directory - change to your folder path - SCALE_PERCENT = 50 # Resize to 50% of original size - - print(f"Image Resizer - Scaling to {SCALE_PERCENT}%") - print(f"Source folder: {FOLDER_PATH}") - print("Mode: Overwriting original images") - print("-" * 50) - - resize_images_in_folder(FOLDER_PATH, SCALE_PERCENT, overwrite=True) - - print("-" * 50) - print("Done!")