🎯 empfohlene Sammlungen
Balanced sample collections from various categories for you to explore
Web Go Bildverarbeitungsbeispiele
Web Go Bildverarbeitungsbeispiele einschließlich Lesen/Schreiben, Skalierung und Formatkonvertierung
💻 Bild-Lesen/Schreiben go
🟢 simple
⭐⭐⭐
Bilder in verschiedenen Formaten (PNG, JPEG, GIF) mit Go-Image-Paketen lesen und speichern
⏱️ 25 min
🏷️ go, web, image processing
Prerequisites:
Intermediate Go, image package
// Web Go Image Read/Save Examples
// Using Go image packages for image I/O operations
package main
import (
"fmt"
"image"
"image/color"
"image/draw"
"image/jpeg"
"image/png"
"os"
"path/filepath"
"strings"
)
// 1. Reading Images
// LoadImage loads an image from file (auto-detects format)
func LoadImage(filePath string) (image.Image, string, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, "", fmt.Errorf("error opening file: %v", err)
}
defer file.Close()
// Decode image format
img, format, err := image.Decode(file)
if err != nil {
return nil, "", fmt.Errorf("error decoding image: %v", err)
}
return img, format, nil
}
// LoadPNG loads a PNG image
func LoadPNG(filePath string) (image.Image, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, fmt.Errorf("error opening file: %v", err)
}
defer file.Close()
img, err := png.Decode(file)
if err != nil {
return nil, fmt.Errorf("error decoding PNG: %v", err)
}
return img, nil
}
// LoadJPEG loads a JPEG image
func LoadJPEG(filePath string) (image.Image, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, fmt.Errorf("error opening file: %v", err)
}
defer file.Close()
img, err := jpeg.Decode(file)
if err != nil {
return nil, fmt.Errorf("error decoding JPEG: %v", err)
}
return img, nil
}
// LoadImageWithOptions loads image with options
func LoadImageWithOptions(filePath string) (image.Image, image.Config, string, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, image.Config{}, "", fmt.Errorf("error opening file: %v", err)
}
defer file.Close()
// Get image config without decoding
config, format, err := image.DecodeConfig(file)
if err != nil {
return nil, image.Config{}, "", fmt.Errorf("error decoding config: %v", err)
}
// Reset file pointer
_, err = file.Seek(0, 0)
if err != nil {
return nil, image.Config{}, "", fmt.Errorf("error seeking file: %v", err)
}
// Decode image
img, _, err := image.Decode(file)
if err != nil {
return nil, image.Config{}, "", fmt.Errorf("error decoding image: %v", err)
}
return img, config, format, nil
}
// 2. Saving Images
// SaveImage saves an image to file (auto-detects format from extension)
func SaveImage(img image.Image, filePath string) error {
// Determine format from extension
ext := strings.ToLower(filepath.Ext(filePath))
var format string
switch ext {
case ".png":
format = "png"
case ".jpg", ".jpeg":
format = "jpeg"
case ".gif":
format = "gif"
default:
return fmt.Errorf("unsupported format: %s", ext)
}
file, err := os.Create(filePath)
if err != nil {
return fmt.Errorf("error creating file: %v", err)
}
defer file.Close()
switch format {
case "png":
err = png.Encode(file, img)
case "jpeg":
err = jpeg.Encode(file, img, &jpeg.Options{Quality: 95})
case "gif":
err = gif.Encode(file, img, nil)
}
if err != nil {
return fmt.Errorf("error encoding image: %v", err)
}
return nil
}
// SavePNG saves an image as PNG
func SavePNG(img image.Image, filePath string) error {
file, err := os.Create(filePath)
if err != nil {
return fmt.Errorf("error creating file: %v", err)
}
defer file.Close()
err = png.Encode(file, img)
if err != nil {
return fmt.Errorf("error encoding PNG: %v", err)
}
return nil
}
// SaveJPEG saves an image as JPEG with quality
func SaveJPEG(img image.Image, filePath string, quality int) error {
file, err := os.Create(filePath)
if err != nil {
return fmt.Errorf("error creating file: %v", err)
}
defer file.Close()
err = jpeg.Encode(file, img, &jpeg.Options{Quality: quality})
if err != nil {
return fmt.Errorf("error encoding JPEG: %v", err)
}
return nil
}
// 3. Image Information
// ImageInfo holds information about an image
type ImageInfo struct {
Width int
Height int
Format string
ColorMode string
FilePath string
}
// GetImageInfo gets information about an image file
func GetImageInfo(filePath string) (*ImageInfo, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, fmt.Errorf("error opening file: %v", err)
}
defer file.Close()
config, format, err := image.DecodeConfig(file)
if err != nil {
return nil, fmt.Errorf("error decoding config: %v", err)
}
colorMode := "RGBA"
if config.ColorModel != nil {
colorMode = config.ColorModel.String()
}
return &ImageInfo{
Width: config.Width,
Height: config.Height,
Format: format,
ColorMode: colorMode,
FilePath: filePath,
}, nil
}
// GetImageDimensions gets width and height of an image
func GetImageDimensions(filePath string) (int, int, error) {
file, err := os.Open(filePath)
if err != nil {
return 0, 0, fmt.Errorf("error opening file: %v", err)
}
defer file.Close()
config, _, err := image.DecodeConfig(file)
if err != nil {
return 0, 0, fmt.Errorf("error decoding config: %v", err)
}
return config.Width, config.Height, nil
}
// 4. Creating New Images
// CreateRGBAImage creates a new RGBA image
func CreateRGBAImage(width, height int) *image.RGBA {
return image.NewRGBA(image.Rect(0, 0, width, height))
}
// CreateSolidColorImage creates an image filled with a solid color
func CreateSolidColorImage(width, height int, color color.Color) image.Image {
img := image.NewRGBA(image.Rect(0, 0, width, height))
draw.Draw(img, img.Bounds(), &image.Uniform{color}, image.Point{}, draw.Src)
return img
}
// CreateGradientImage creates a horizontal gradient image
func CreateGradientImage(width, height int, startColor, endColor color.Color) image.Image {
img := image.NewRGBA(image.Rect(0, 0, width, height))
r1, g1, b1, a1 := startColor.RGBA()
r2, g2, b2, a2 := endColor.RGBA()
for x := 0; x < width; x++ {
r := uint8((r1 + (r2-r1)*uint32(x)/uint32(width)) >> 8)
g := uint8((g1 + (g2-g1)*uint32(x)/uint32(width)) >> 8)
b := uint8((b1 + (b2-b1)*uint32(x)/uint32(width)) >> 8)
a := uint8((a1 + (a2-a1)*uint32(x)/uint32(width)) >> 8)
for y := 0; y < height; y++ {
img.Set(x, y, color.RGBA{r, g, b, a})
}
}
return img
}
// 5. Image Manipulation
// CropImage crops an image to the specified rectangle
func CropImage(img image.Image, rect image.Rectangle) image.Image {
cropped := image.NewRGBA(rect)
draw.Draw(cropped, rect, img, rect.Min, draw.Src)
return cropped
}
// CloneImage creates a copy of an image
func CloneImage(img image.Image) image.Image {
cloned := image.NewRGBA(img.Bounds())
draw.Draw(cloned, img.Bounds(), img, image.Point{}, draw.Src)
return cloned
}
// Rotate180 rotates an image 180 degrees
func Rotate180(img image.Image) image.Image {
srcBounds := img.Bounds()
dst := image.NewRGBA(srcBounds)
for y := 0; y < srcBounds.Dy(); y++ {
for x := 0; x < srcBounds.Dx(); x++ {
dst.Set(srcBounds.Dx()-1-x, srcBounds.Dy()-1-y, img.At(x, y))
}
}
return dst
}
// 6. Batch Operations
// LoadMultipleImages loads multiple images
func LoadMultipleImages(filePaths []string) (map[string]image.Image, error) {
images := make(map[string]image.Image)
for _, path := range filePaths {
img, _, err := LoadImage(path)
if err != nil {
return nil, fmt.Errorf("error loading %s: %v", path, err)
}
images[path] = img
}
return images, nil
}
// SaveMultipleImages saves multiple images
func SaveMultipleImages(images map[string]image.Image, directory string) error {
for filename, img := range images {
filePath := filepath.Join(directory, filename)
if err := SaveImage(img, filePath); err != nil {
return fmt.Errorf("error saving %s: %v", filename, err)
}
}
return nil
}
// ConvertMultipleImages converts multiple images to a different format
func ConvertMultipleImages(inputPaths []string, outputDir, outputFormat string) error {
for _, inputPath := range inputPaths {
// Load image
img, _, err := LoadImage(inputPath)
if err != nil {
return err
}
// Create output filename
baseName := filepath.Base(inputPath)
baseName = strings.TrimSuffix(baseName, filepath.Ext(baseName))
outputPath := filepath.Join(outputDir, baseName+"."+outputFormat)
// Save in new format
if err := SaveImage(img, outputPath); err != nil {
return err
}
}
return nil
}
// 7. Image Validation
// IsValidImage checks if a file is a valid image
func IsValidImage(filePath string) bool {
file, err := os.Open(filePath)
if err != nil {
return false
}
defer file.Close()
_, _, err = image.Decode(file)
return err == nil
}
// GetSupportedFormats returns list of supported image formats
func GetSupportedFormats() []string {
return []string{"png", "jpeg", "gif"}
}
// Usage Examples
func main() {
fmt.Println("=== Web Go Image Read/Save Examples ===\n")
// 1. Load image
fmt.Println("--- 1. Load Image ---")
img, format, err := LoadImage("input.jpg")
if err == nil {
fmt.Printf("Loaded image format: %s\n", format)
fmt.Printf("Bounds: %v\n", img.Bounds())
}
// 2. Get image info
fmt.Println("\n--- 2. Image Info ---")
info, err := GetImageInfo("input.jpg")
if err == nil {
fmt.Printf("Width: %d\n", info.Width)
fmt.Printf("Height: %d\n", info.Height)
fmt.Printf("Format: %s\n", info.Format)
}
// 3. Save image
fmt.Println("\n--- 3. Save Image ---")
err = SavePNG(img, "output.png")
if err == nil {
fmt.Println("Image saved as PNG")
}
// 4. Create new image
fmt.Println("\n--- 4. Create New Image ---")
newImg := CreateSolidColorImage(400, 300, color.RGBA{255, 0, 0, 255})
SavePNG(newImg, "red_square.png")
fmt.Println("Created solid color image")
// 5. Create gradient
fmt.Println("\n--- 5. Create Gradient ---")
gradient := CreateGradientImage(400, 300,
color.RGBA{0, 0, 255, 255},
color.RGBA{255, 0, 0, 255})
SavePNG(gradient, "gradient.png")
fmt.Println("Created gradient image")
// 6. Clone and crop
fmt.Println("\n--- 6. Clone and Crop ---")
cloned := CloneImage(img)
cropped := CropImage(cloned, image.Rect(50, 50, 250, 250))
SavePNG(cropped, "cropped.png")
fmt.Println("Cropped image")
// 7. Batch conversion
fmt.Println("\n--- 7. Batch Conversion ---")
images := []string{"image1.jpg", "image2.jpg"}
err = ConvertMultipleImages(images, "output", "png")
if err == nil {
fmt.Println("Batch conversion completed")
}
// 8. Validation
fmt.Println("\n--- 8. Validation ---")
fmt.Printf("Valid image: %v\n", IsValidImage("input.jpg"))
fmt.Println("\n=== All Image Read/Save Examples Completed ===")
}
💻 Formatkonvertierung go
🟢 simple
⭐⭐⭐
Bilder zwischen PNG, JPEG, GIF und anderen Formaten mit Qualitätssteuerung konvertieren
⏱️ 25 min
🏷️ go, web, image processing
Prerequisites:
Intermediate Go, image package, filepath
// Web Go Image Format Conversion Examples
// Converting between different image formats
package main
import (
"fmt"
"image"
"image/jpeg"
"image/png"
"os"
"path/filepath"
"strings"
)
// 1. Basic Format Conversion
// ConvertFormat converts an image from one format to another
func ConvertFormat(inputPath, outputPath string) error {
// Load image
img, _, err := LoadImage(inputPath)
if err != nil {
return fmt.Errorf("error loading image: %v", err)
}
// Save in new format
return SaveImage(img, outputPath)
}
// ConvertToPNG converts any image to PNG
func ConvertToPNG(inputPath, outputPath string) error {
img, _, err := LoadImage(inputPath)
if err != nil {
return fmt.Errorf("error loading image: %v", err)
}
return SavePNG(img, outputPath)
}
// ConvertToJPEG converts any image to JPEG with quality setting
func ConvertToJPEG(inputPath, outputPath string, quality int) error {
img, _, err := LoadImage(inputPath)
if err != nil {
return fmt.Errorf("error loading image: %v", err)
}
return SaveJPEG(img, outputPath, quality)
}
// 2. Quality Control
// JPEGQualityOptions holds JPEG quality presets
type JPEGQualityOptions struct {
Low int // 50-60
Medium int // 70-80
High int // 85-95
Maximum int // 100
}
// GetJPEGQualityPresets returns quality presets
func GetJPEGQualityPresets() JPEGQualityOptions {
return JPEGQualityOptions{
Low: 60,
Medium: 75,
High: 90,
Maximum: 100,
}
}
// ConvertToJPEGWithQuality converts to JPEG with specified quality
func ConvertToJPEGWithQuality(inputPath, outputPath string, quality int) error {
if quality < 1 || quality > 100 {
return fmt.Errorf("quality must be between 1 and 100")
}
img, _, err := LoadImage(inputPath)
if err != nil {
return fmt.Errorf("error loading image: %v", err)
}
return SaveJPEG(img, outputPath, quality)
}
// ConvertToJPEGMultipleQualities generates JPEG at multiple quality levels
func ConvertToJPEGMultipleQualities(inputPath, outputDir string, qualities []int) error {
img, _, err := LoadImage(inputPath)
if err != nil {
return fmt.Errorf("error loading image: %v", err)
}
baseName := filepath.Base(inputPath)
baseName = strings.TrimSuffix(baseName, filepath.Ext(baseName))
for _, quality := range qualities {
outputPath := filepath.Join(outputDir, fmt.Sprintf("%s_q%d.jpg", baseName, quality))
if err := SaveJPEG(img, outputPath, quality); err != nil {
return err
}
}
return nil
}
// 3. Batch Conversion
// ConversionOptions holds options for batch conversion
type ConversionOptions struct {
InputDir string
OutputDir string
InputFormat string
OutputFormat string
Quality int // For JPEG
}
// ConvertBatch converts all images of input format to output format
func ConvertBatch(options ConversionOptions) ([]string, error) {
var converted []string
// Find all files with input format
pattern := filepath.Join(options.InputDir, "*."+options.InputFormat)
files, err := filepath.Glob(pattern)
if err != nil {
return nil, fmt.Errorf("error finding files: %v", err)
}
for _, filePath := range files {
// Load image
img, _, err := LoadImage(filePath)
if err != nil {
return nil, fmt.Errorf("error loading %s: %v", filePath, err)
}
// Generate output path
baseName := filepath.Base(filePath)
baseName = strings.TrimSuffix(baseName, filepath.Ext(baseName))
outputPath := filepath.Join(options.OutputDir, baseName+"."+options.OutputFormat)
// Save in new format
switch strings.ToLower(options.OutputFormat) {
case "png":
err = SavePNG(img, outputPath)
case "jpg", "jpeg":
err = SaveJPEG(img, outputPath, options.Quality)
default:
err = SaveImage(img, outputPath)
}
if err != nil {
return nil, fmt.Errorf("error saving %s: %v", outputPath, err)
}
converted = append(converted, outputPath)
}
return converted, nil
}
// ConvertDirectoryRecursive converts all images in directory recursively
func ConvertDirectoryRecursive(inputDir, outputDir, outputFormat string) error {
return filepath.Walk(inputDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
// Check if it's an image file
ext := strings.ToLower(filepath.Ext(path))
if ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".gif" {
// Calculate relative path
relPath, err := filepath.Rel(inputDir, path)
if err != nil {
return err
}
// Create output path
outputPath := filepath.Join(outputDir, relPath)
outputPath = strings.TrimSuffix(outputPath, ext) + "." + outputFormat
// Ensure output directory exists
outputDirPath := filepath.Dir(outputPath)
if err := os.MkdirAll(outputDirPath, 0755); err != nil {
return err
}
// Convert
if err := ConvertFormat(path, outputPath); err != nil {
return fmt.Errorf("error converting %s: %v", path, err)
}
}
return nil
})
}
// 4. Format Detection
// DetectFormat detects image format from file
func DetectFormat(filePath string) (string, error) {
file, err := os.Open(filePath)
if err != nil {
return "", fmt.Errorf("error opening file: %v", err)
}
defer file.Close()
_, format, err := image.Decode(file)
if err != nil {
return "", fmt.Errorf("error decoding image: %v", err)
}
return format, nil
}
// DetectFormatFromExtension detects format from file extension
func DetectFormatFromExtension(filePath string) string {
ext := strings.ToLower(filepath.Ext(filePath))
switch ext {
case ".png":
return "png"
case ".jpg", ".jpeg":
return "jpeg"
case ".gif":
return "gif"
default:
return "unknown"
}
}
// 5. Conversion Utilities
// ConvertWithMetadata converts image and preserves metadata
func ConvertWithMetadata(inputPath, outputPath string) error {
img, format, err := LoadImage(inputPath)
if err != nil {
return fmt.Errorf("error loading image: %v", err)
}
// Save in new format
switch strings.ToLower(filepath.Ext(outputPath)) {
case ".png":
err = png.Encode(outputFile, img)
case ".jpg", ".jpeg":
err = jpeg.Encode(outputFile, img, &jpeg.Options{Quality: 95})
}
return err
}
// ConvertAndResize converts and resizes in one operation
func ConvertAndResize(inputPath, outputPath string, width, height int) error {
img, _, err := LoadImage(inputPath)
if err != nil {
return fmt.Errorf("error loading image: %v", err)
}
// Resize
resized := ResizeBilinear(img, width, height)
// Save
return SaveImage(resized, outputPath)
}
// 6. Optimization
// OptimizePNG optimizes PNG by reducing color palette if possible
func OptimizePNG(inputPath, outputPath string) error {
img, _, err := LoadImage(inputPath)
if err != nil {
return fmt.Errorf("error loading image: %v", err)
}
// Save with optimal settings
file, err := os.Create(outputPath)
if err != nil {
return fmt.Errorf("error creating file: %v", err)
}
defer file.Close()
return png.Encode(file, img)
}
// OptimizeJPEG optimizes JPEG by finding optimal quality
func OptimizeJPEG(inputPath, outputPath string, minQuality, maxQuality int) error {
img, _, err := LoadImage(inputPath)
if err != nil {
return fmt.Errorf("error loading image: %v", err)
}
// Try different qualities
bestQuality := minQuality
minSize := int64(^uint64(0) >> 1)
for quality := minQuality; quality <= maxQuality; quality += 5 {
tempPath := outputPath + ".tmp"
file, err := os.Create(tempPath)
if err != nil {
continue
}
err = jpeg.Encode(file, img, &jpeg.Options{Quality: quality})
file.Close()
if err != nil {
continue
}
info, _ := os.Stat(tempPath)
if info.Size() < minSize {
minSize = info.Size()
bestQuality = quality
}
os.Remove(tempPath)
}
// Save with best quality
return SaveJPEG(img, outputPath, bestQuality)
}
// 7. Conversion Statistics
// ConversionStats holds statistics about conversion
type ConversionStats struct {
TotalFiles int
SuccessCount int
FailureCount int
InputSize int64
OutputSize int64
TimeTaken string
}
// ConvertBatchWithStats converts and returns statistics
func ConvertBatchWithStats(options ConversionOptions) (*ConversionStats, error) {
start := time.Now()
stats := &ConversionStats{}
files, _ := filepath.Glob(filepath.Join(options.InputDir, "*."+options.InputFormat))
stats.TotalFiles = len(files)
for _, filePath := range files {
info, _ := os.Stat(filePath)
stats.InputSize += info.Size()
baseName := filepath.Base(filePath)
baseName = strings.TrimSuffix(baseName, filepath.Ext(baseName))
outputPath := filepath.Join(options.OutputDir, baseName+"."+options.OutputFormat)
err := ConvertFormat(filePath, outputPath)
if err != nil {
stats.FailureCount++
} else {
stats.SuccessCount++
info, _ = os.Stat(outputPath)
stats.OutputSize += info.Size()
}
}
stats.TimeTaken = time.Since(start).String()
return stats, nil
}
// Usage Examples
func main() {
fmt.Println("=== Web Go Image Format Conversion Examples ===\n")
// 1. Basic conversion
fmt.Println("--- 1. Basic Conversion ---")
err := ConvertFormat("input.png", "output.jpg")
if err == nil {
fmt.Println("Converted PNG to JPEG")
}
// 2. Convert with quality
fmt.Println("\n--- 2. Convert with Quality ---")
err = ConvertToJPEG("input.png", "output_q80.jpg", 80)
if err == nil {
fmt.Println("Converted with quality 80")
}
// 3. Multiple quality levels
fmt.Println("\n--- 3. Multiple Quality Levels ---")
qualities := []int{60, 75, 90, 100}
err = ConvertToJPEGMultipleQualities("input.png", "output", qualities)
if err == nil {
fmt.Printf("Generated %d quality versions\n", len(qualities))
}
// 4. Batch conversion
fmt.Println("\n--- 4. Batch Conversion ---")
options := ConversionOptions{
InputDir: "input",
OutputDir: "output",
InputFormat: "png",
OutputFormat: "jpg",
Quality: 85,
}
converted, err := ConvertBatch(options)
if err == nil {
fmt.Printf("Converted %d files\n", len(converted))
}
// 5. Format detection
fmt.Println("\n--- 5. Format Detection ---")
format, _ := DetectFormat("input.png")
fmt.Printf("Detected format: %s\n", format)
// 6. Convert and resize
fmt.Println("\n--- 6. Convert and Resize ---")
err = ConvertAndResize("input.png", "output_small.jpg", 200, 200)
if err == nil {
fmt.Println("Converted and resized")
}
// 7. Optimization
fmt.Println("\n--- 7. Optimization ---")
err = OptimizeJPEG("input.jpg", "optimized.jpg", 70, 95)
if err == nil {
fmt.Println("Optimized JPEG")
}
// 8. Statistics
fmt.Println("\n--- 8. Conversion Statistics ---")
stats, _ := ConvertBatchWithStats(options)
fmt.Printf("Total: %d, Success: %d, Failed: %d\n",
stats.TotalFiles, stats.SuccessCount, stats.FailureCount)
fmt.Printf("Size: %d -> %d bytes\n", stats.InputSize, stats.OutputSize)
fmt.Println("\n=== All Format Conversion Examples Completed ===")
}
💻 Bild-Skalierung go
🟡 intermediate
⭐⭐⭐⭐
Bilder mit verschiedenen Interpolationsmethoden und Beibehaltung des Seitenverhältnisses skalieren
⏱️ 35 min
🏷️ go, web, image processing
Prerequisites:
Intermediate Go, image package, math
// Web Go Image Resizing Examples
// Image resizing with different algorithms
package main
import (
"fmt"
"image"
"image/color"
"image/draw"
"math"
)
// 1. Basic Resizing (Nearest Neighbor)
// ResizeNearestNeighbor resizes an image using nearest neighbor algorithm
func ResizeNearestNeighbor(img image.Image, newWidth, newHeight int) image.Image {
srcBounds := img.Bounds()
dst := image.NewRGBA(image.Rect(0, 0, newWidth, newHeight))
xRatio := float64(srcBounds.Dx()) / float64(newWidth)
yRatio := float64(srcBounds.Dy()) / float64(newHeight)
for y := 0; y < newHeight; y++ {
for x := 0; x < newWidth; x++ {
srcX := int(math.Floor(float64(x) * xRatio))
srcY := int(math.Floor(float64(y) * yRatio))
dst.Set(x, y, img.At(srcBounds.Min.X+srcX, srcBounds.Min.Y+srcY))
}
}
return dst
}
// 2. Bilinear Interpolation
// ResizeBilinear resizes an image using bilinear interpolation
func ResizeBilinear(img image.Image, newWidth, newHeight int) image.Image {
srcBounds := img.Bounds()
dst := image.NewRGBA(image.Rect(0, 0, newWidth, newHeight))
xRatio := float64(srcBounds.Dx()-1) / float64(newWidth)
yRatio := float64(srcBounds.Dy()-1) / float64(newHeight)
for y := 0; y < newHeight; y++ {
for x := 0; x < newWidth; x++ {
srcX := float64(x) * xRatio
srcY := float64(y) * yRatio
x1 := int(math.Floor(srcX))
y1 := int(math.Floor(srcY))
x2 := x1 + 1
y2 := y1 + 1
// Clamp coordinates
if x2 >= srcBounds.Dx() {
x2 = srcBounds.Dx() - 1
}
if y2 >= srcBounds.Dy() {
y2 = srcBounds.Dy() - 1
}
// Bilinear interpolation
c1 := img.At(srcBounds.Min.X+x1, srcBounds.Min.Y+y1)
c2 := img.At(srcBounds.Min.X+x2, srcBounds.Min.Y+y1)
c3 := img.At(srcBounds.Min.X+x1, srcBounds.Min.Y+y2)
c4 := img.At(srcBounds.Min.X+x2, srcBounds.Min.Y+y2)
dx := srcX - float64(x1)
dy := srcY - float64(y1)
color := interpolateColor(c1, c2, c3, c4, dx, dy)
dst.Set(x, y, color)
}
}
return dst
}
func interpolateColor(c1, c2, c3, c4 color.Color, dx, dy float64) color.Color {
r1, g1, b1, a1 := c1.RGBA()
r2, g2, b2, a2 := c2.RGBA()
r3, g3, b3, a3 := c3.RGBA()
r4, g4, b4, a4 := c4.RGBA()
// Interpolate top row
rTop := interpolateValue(r1, r2, dx)
gTop := interpolateValue(g1, g2, dx)
bTop := interpolateValue(b1, b2, dx)
aTop := interpolateValue(a1, a2, dx)
// Interpolate bottom row
rBot := interpolateValue(r3, r4, dx)
gBot := interpolateValue(g3, g4, dx)
bBot := interpolateValue(b3, b4, dx)
aBot := interpolateValue(a3, a4, dx)
// Interpolate vertically
r := interpolateValue(rTop, rBot, dy)
g := interpolateValue(gTop, gBot, dy)
b := interpolateValue(bTop, bBot, dy)
a := interpolateValue(aTop, aBot, dy)
return color.RGBA{
R: uint8(r >> 8),
G: uint8(g >> 8),
B: uint8(b >> 8),
A: uint8(a >> 8),
}
}
func interpolateValue(v1, v2 uint32, t float64) uint32 {
return uint32(float64(v1)*(1-t) + float64(v2)*t)
}
// 3. Aspect Ratio Preservation
// ResizeFit resizes image to fit within dimensions while preserving aspect ratio
func ResizeFit(img image.Image, maxWidth, maxHeight int) image.Image {
srcBounds := img.Bounds()
srcWidth := srcBounds.Dx()
srcHeight := srcBounds.Dy()
// Calculate scaling factors
widthRatio := float64(maxWidth) / float64(srcWidth)
heightRatio := float64(maxHeight) / float64(srcHeight)
scale := math.Min(widthRatio, heightRatio)
newWidth := int(float64(srcWidth) * scale)
newHeight := int(float64(srcHeight) * scale)
return ResizeBilinear(img, newWidth, newHeight)
}
// ResizeFill resizes image to fill dimensions while preserving aspect ratio (crops overflow)
func ResizeFill(img image.Image, targetWidth, targetHeight int) image.Image {
srcBounds := img.Bounds()
srcWidth := srcBounds.Dx()
srcHeight := srcBounds.Dy()
// Calculate scaling factors
widthRatio := float64(targetWidth) / float64(srcWidth)
heightRatio := float64(targetHeight) / float64(srcHeight)
scale := math.Max(widthRatio, heightRatio)
resizedWidth := int(float64(srcWidth) * scale)
resizedHeight := int(float64(srcHeight) * scale)
resized := ResizeBilinear(img, resizedWidth, resizedHeight)
// Crop to target size
xOffset := (resizedWidth - targetWidth) / 2
yOffset := (resizedHeight - targetHeight) / 2
return CropImage(resized, image.Rect(xOffset, yOffset, xOffset+targetWidth, yOffset+targetHeight))
}
// ResizeExact resizes image to exact dimensions (may distort)
func ResizeExact(img image.Image, width, height int) image.Image {
return ResizeBilinear(img, width, height)
}
// 4. Thumbnail Generation
// GenerateThumbnail generates a thumbnail with max dimensions
func GenerateThumbnail(img image.Image, maxSize int) image.Image {
srcBounds := img.Bounds()
srcWidth := srcBounds.Dx()
srcHeight := srcBounds.Dy()
// Determine dimensions
var width, height int
if srcWidth > srcHeight {
width = maxSize
height = int(float64(srcHeight) * float64(maxSize) / float64(srcWidth))
} else {
height = maxSize
width = int(float64(srcWidth) * float64(maxSize) / float64(srcHeight))
}
return ResizeBilinear(img, width, height)
}
// GenerateSquareThumbnail generates a square thumbnail (crops center)
func GenerateSquareThumbnail(img image.Image, size int) image.Image {
return ResizeFill(img, size, size)
}
// 5. Scale by Percentage
// ScaleByPercentage scales image by percentage
func ScaleByPercentage(img image.Image, percentage float64) image.Image {
srcBounds := img.Bounds()
newWidth := int(float64(srcBounds.Dx()) * percentage / 100.0)
newHeight := int(float64(srcBounds.Dy()) * percentage / 100.0)
return ResizeBilinear(img, newWidth, newHeight)
}
// ScaleByFactor scales image by factor
func ScaleByFactor(img image.Image, factor float64) image.Image {
srcBounds := img.Bounds()
newWidth := int(float64(srcBounds.Dx()) * factor)
newHeight := int(float64(srcBounds.Dy()) * factor)
return ResizeBilinear(img, newWidth, newHeight)
}
// 6. Batch Resizing
// ResizeBatch resizes multiple images
func ResizeBatch(inputPaths []string, outputDir string, width, height int) error {
for _, inputPath := range inputPaths {
img, _, err := LoadImage(inputPath)
if err != nil {
return err
}
resized := ResizeBilinear(img, width, height)
baseName := filepath.Base(inputPath)
baseName = strings.TrimSuffix(baseName, filepath.Ext(baseName))
outputPath := filepath.Join(outputDir, baseName+"_resized.png")
if err := SavePNG(resized, outputPath); err != nil {
return err
}
}
return nil
}
// GenerateThumbnailsBatch generates thumbnails for multiple images
func GenerateThumbnailsBatch(inputPaths []string, outputDir string, size int) error {
for _, inputPath := range inputPaths {
img, _, err := LoadImage(inputPath)
if err != nil {
return err
}
thumbnail := GenerateThumbnail(img, size)
baseName := filepath.Base(inputPath)
baseName = strings.TrimSuffix(baseName, filepath.Ext(baseName))
outputPath := filepath.Join(outputDir, baseName+"_thumb.png")
if err := SavePNG(thumbnail, outputPath); err != nil {
return err
}
}
return nil
}
// 7. Special Resizing Operations
// ResizeToWidth resizes to specific width (maintains aspect ratio)
func ResizeToWidth(img image.Image, width int) image.Image {
srcBounds := img.Bounds()
srcWidth := srcBounds.Dx()
srcHeight := srcBounds.Dy()
ratio := float64(width) / float64(srcWidth)
height := int(float64(srcHeight) * ratio)
return ResizeBilinear(img, width, height)
}
// ResizeToHeight resizes to specific height (maintains aspect ratio)
func ResizeToHeight(img image.Image, height int) image.Image {
srcBounds := img.Bounds()
srcWidth := srcBounds.Dx()
srcHeight := srcBounds.Dy()
ratio := float64(height) / float64(srcHeight)
width := int(float64(srcWidth) * ratio)
return ResizeBilinear(img, width, height)
}
// ResizeMultipleScales generates multiple scaled versions
func ResizeMultipleScales(img image.Image, scales []float64) map[float64]image.Image {
results := make(map[float64]image.Image)
for _, scale := range scales {
results[scale] = ScaleByFactor(img, scale)
}
return results
}
// Usage Examples
func main() {
fmt.Println("=== Web Go Image Resizing Examples ===\n")
// Load image
img, _, err := LoadImage("input.jpg")
if err != nil {
fmt.Printf("Error loading image: %v\n", err)
return
}
// 1. Nearest neighbor resize
fmt.Println("--- 1. Nearest Neighbor Resize ---")
nearest := ResizeNearestNeighbor(img, 200, 200)
SavePNG(nearest, "nearest.png")
fmt.Println("Resized using nearest neighbor")
// 2. Bilinear resize
fmt.Println("\n--- 2. Bilinear Resize ---")
bilinear := ResizeBilinear(img, 300, 300)
SavePNG(bilinear, "bilinear.png")
fmt.Println("Resized using bilinear interpolation")
// 3. Resize fit
fmt.Println("\n--- 3. Resize Fit ---")
fit := ResizeFit(img, 200, 200)
SavePNG(fit, "fit.png")
fmt.Printf("Fit dimensions: %v\n", fit.Bounds().Dx(), fit.Bounds().Dy())
// 4. Resize fill
fmt.Println("\n--- 4. Resize Fill ---")
fill := ResizeFill(img, 200, 200)
SavePNG(fill, "fill.png")
fmt.Println("Resized with fill (crop)")
// 5. Thumbnail
fmt.Println("\n--- 5. Thumbnail ---")
thumbnail := GenerateThumbnail(img, 150)
SavePNG(thumbnail, "thumbnail.png")
fmt.Printf("Thumbnail dimensions: %v\n", thumbnail.Bounds())
// 6. Square thumbnail
fmt.Println("\n--- 6. Square Thumbnail ---")
squareThumb := GenerateSquareThumbnail(img, 150)
SavePNG(squareThumb, "square_thumb.png")
fmt.Println("Created square thumbnail")
// 7. Scale by percentage
fmt.Println("\n--- 7. Scale by Percentage ---")
scaled := ScaleByPercentage(img, 50.0)
SavePNG(scaled, "scaled_50.png")
fmt.Printf("Scaled to 50%%: %v\n", scaled.Bounds())
// 8. Resize to width
fmt.Println("\n--- 8. Resize to Width ---")
widthResized := ResizeToWidth(img, 300)
SavePNG(widthResized, "width_300.png")
fmt.Printf("Resized to width 300: %v\n", widthResized.Bounds())
// 9. Multiple scales
fmt.Println("\n--- 9. Multiple Scales ---")
scales := []float64{0.25, 0.5, 0.75, 1.5}
multi := ResizeMultipleScales(img, scales)
fmt.Printf("Generated %d scaled versions\n", len(multi))
// 10. Batch resize
fmt.Println("\n--- 10. Batch Resize ---")
images := []string{"img1.jpg", "img2.jpg", "img3.jpg"}
err = ResizeBatch(images, "resized", 200, 200)
if err == nil {
fmt.Println("Batch resize completed")
}
fmt.Println("\n=== All Image Resizing Examples Completed ===")
}