imgx

package module
v1.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 20, 2025 License: MIT Imports: 28 Imported by: 0

README

imgx

PkgGoDev

Package imgx provides comprehensive image processing functions (resize, rotate, crop, brightness/contrast adjustments, effects) and AI-powered object detection using Google Gemini, AWS Rekognition, and OpenAI Vision APIs.

All the image processing functions provided by the package accept any image type that implements image.Image interface as an input, and return a new image of *image.NRGBA type (32bit RGBA colors, non-premultiplied alpha).

Table of Contents

Installation

As a Library
go get -u github.com/razzkumar/imgx
As a CLI Tool
# Install via go install (Recommended)
go install github.com/razzkumar/imgx/cmd/imgx@latest

# Or build from source
go build -o imgx ./cmd/imgx

Quick CLI Examples:

# Resize an image
imgx resize photo.jpg -w 800 -o resized.jpg

# Create a thumbnail
imgx thumbnail photo.jpg -s 150 -o thumb.jpg

# Adjust colors
imgx adjust photo.jpg --brightness 10 --contrast 20 -o adjusted.jpg

# Apply blur effect
imgx blur photo.jpg --sigma 2.5 -o blurred.jpg

# Detect objects using AI (local Ollama by default)
imgx detect photo.jpg

# Extract image metadata (requires exiftool for extended data)
imgx metadata photo.jpg

For complete CLI documentation with all commands, options, and examples, see CLI Documentation.

Documentation

Library API: https://pkg.go.dev/github.com/razzkumar/imgx CLI Tool: CLI.md Object Detection: DETECTION.md - AI vision with Ollama, Google Gemini, AWS Rekognition, OpenAI

Library Usage Examples

A few usage examples can be found below. See the documentation for the full list of supported functions.

Quick Start - Using as a Library
package main

import (
    "log"
    "github.com/razzkumar/imgx"
)

func main() {
    // Load an image file
    img, err := imgx.Load("input.jpg")
    if err != nil {
        log.Fatalf("failed to load image: %v", err)
    }

    // Resize to width 800px, maintaining aspect ratio
    img = img.Resize(800, 0, imgx.Lanczos)

    // Save the result (with automatic metadata tracking)
    err = img.Save("output.jpg")
    if err != nil {
        log.Fatalf("failed to save image: %v", err)
    }
}
Loading Options

You can customize image loading by passing an Options struct:

// Load with auto-orientation
img, err := imgx.Load("photo.jpg", imgx.Options{
    AutoOrient: true,  // Apply EXIF orientation
})

// Load with custom author
img, err := imgx.Load("photo.jpg", imgx.Options{
    Author: "Your Name",  // Override default author in metadata
})

// Load with multiple options
img, err := imgx.Load("photo.jpg", imgx.Options{
    AutoOrient:      true,
    Author:          "John Doe",
    DisableMetadata: false,  // Enable/disable metadata tracking
})

// Or just use defaults (no options needed)
img, err := imgx.Load("photo.jpg")

Available Options:

  • AutoOrient (bool) - Automatically correct image orientation from EXIF data
  • Author (string) - Set custom artist/creator name for metadata (empty = use default)
  • DisableMetadata (bool) - Disable automatic metadata tracking for this image
Image resizing
// Load an image
img, _ := imgx.Load("input.jpg")

// Resize to size = 128x128px using the Lanczos filter.
img128 := img.Resize(128, 128, imgx.Lanczos)

// Resize to width = 800px preserving the aspect ratio.
img800 := img.Resize(800, 0, imgx.Lanczos)

// Scale down to fit the 800x600px bounding box.
imgFit := img.Fit(800, 600, imgx.Lanczos)

// Resize and crop to fill the 100x100px area.
imgFill := img.Fill(100, 100, imgx.Center, imgx.Lanczos)

Example Output:

Original Image (1280×853):

Original flower

After Resize(src, 200, 0, imgx.Lanczos) - Resized to width 200px, height auto:

Resized flower 200

After Fill(src, 300, 300, imgx.Center, imgx.Lanczos) - Square thumbnail 300×300:

Thumbnail flower 300x300

Imaging supports image resizing using various resampling filters. The most notable ones:

  • Lanczos - A high-quality resampling filter for photographic images yielding sharp results.
  • CatmullRom - A sharp cubic filter that is faster than Lanczos filter while providing similar results.
  • MitchellNetravali - A cubic filter that produces smoother results with less ringing artifacts than CatmullRom.
  • Linear - Bilinear resampling filter, produces smooth output. Faster than cubic filters.
  • Box - Simple and fast averaging filter appropriate for downscaling. When upscaling it's similar to NearestNeighbor.
  • NearestNeighbor - Fastest resampling filter, no antialiasing.

The full list of supported filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali, CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. Custom filters can be created using ResampleFilter struct.

Resampling filters comparison

The same image can be resized using different resampling filters. From faster (lower quality) to slower (higher quality): NearestNeighbor, Linear, CatmullRom, Lanczos.

Image Rotation
// Load an image
img, _ := imgx.Load("branch.jpg")

// Rotate 90 degrees clockwise
rotated := img.Rotate90()

Original Image:

Original branch

After Rotate90(src):

Rotated branch

Image Flipping
// Load an image
img, _ := imgx.Load("branch.jpg")

// Flip horizontally
flipped := img.FlipH()

After FlipH(src):

Flipped branch

Gaussian Blur
// Load an image
img, _ := imgx.Load("input.jpg")

// Apply Gaussian blur with sigma 2.0
blurred := img.Blur(2.0)

After Blur(src, 2.0) - Gaussian blur with sigma=2.0:

Blurred flower

Sharpening
// Load an image
img, _ := imgx.Load("input.jpg")

// Light sharpening
lightSharp := img.Sharpen(0.5)

// Medium sharpening
mediumSharp := img.Sharpen(1.0)

// Heavy sharpening
heavySharp := img.Sharpen(2.0)

Sharpen uses unsharp mask technique internally. Sigma parameter controls the strength of the sharpening effect.

Example Output:

Original Image:

Original flower

After Sharpen(src, 1.5) - Sharpened with sigma=1.5:

Sharpened flower

Color Adjustments
Gamma Correction
// Load an image
img, _ := imgx.Load("input.jpg")

// Darken image (gamma < 1.0)
darker := img.AdjustGamma(0.5)

// Lighten image (gamma > 1.0)
lighter := img.AdjustGamma(1.5)
Contrast Adjustment
// Load an image
img, _ := imgx.Load("input.jpg")

// Decrease contrast
lowContrast := img.AdjustContrast(-20)

// Increase contrast
highContrast := img.AdjustContrast(20)

Range: -100 (min contrast) to 100 (max contrast)

Example Output:

Original Image:

Original flower

After AdjustContrast(src, 30) - Increased contrast:

Contrast adjusted

Brightness Adjustment
// Load an image
img, _ := imgx.Load("input.jpg")

// Decrease brightness
darker := img.AdjustBrightness(-20)

// Increase brightness
brighter := img.AdjustBrightness(20)

Range: -100 (darkest) to 100 (brightest)

Example Output:

Original Image:

Original flower

After AdjustBrightness(src, 30) - Increased brightness:

Brightness adjusted

Saturation Adjustment
// Load an image
img, _ := imgx.Load("input.jpg")

// Desaturate (move towards grayscale)
desaturated := img.AdjustSaturation(-50)

// Increase saturation (more vivid colors)
saturated := img.AdjustSaturation(50)

// Complete desaturation
grayscale := img.AdjustSaturation(-100)

Range: -100 (grayscale) to 500 (highly saturated)

Example Output:

Original Image:

Original flower

After AdjustSaturation(src, 50) - Increased saturation:

Saturation adjusted

Hue Adjustment
// Load an image
img, _ := imgx.Load("input.jpg")

// Shift hue by 20 degrees
shifted := img.AdjustHue(20)

// Shift hue by 180 degrees (complementary colors)
inverted := img.AdjustHue(180)

Range: -180 to 180 degrees

Grayscale Conversion
// Load an image
img, _ := imgx.Load("input.jpg")

// Convert image to grayscale
gray := img.Grayscale()

Example Output:

Original Image:

Original flower

After Grayscale(src) - Converted to grayscale:

Grayscale flower

Example: Complete color adjustment pipeline with method chaining

// Load and process image with method chaining
img, _ := imgx.Load("input.jpg")

// Adjust multiple properties by chaining methods
result := img.AdjustBrightness(10).
    AdjustContrast(20).
    AdjustSaturation(30)

result.Save("output_adjusted.jpg")

More Library Usage Examples

package main

import (
    "log"
    "github.com/razzkumar/imgx"
)

func main() {
    // Load source image
    img, err := imgx.Load("photo.jpg")
    if err != nil {
        log.Fatal(err)
    }

    // Create different thumbnail sizes
    thumb100 := img.Thumbnail(100, 100, imgx.Lanczos)
    thumb200 := img.Thumbnail(200, 200, imgx.Lanczos)
    thumb400 := img.Thumbnail(400, 400, imgx.Lanczos)

    // Save thumbnails
    thumb100.Save("thumb_100.jpg")
    thumb200.Save("thumb_200.jpg")
    thumb400.Save("thumb_400.jpg")
}
Example 2: Batch Image Processing
package main

import (
    "log"
    "os"
    "path/filepath"
    "strings"
    "github.com/razzkumar/imgx"
)

func main() {
    // Process all JPG files in a directory
    files, _ := filepath.Glob("input/*.jpg")

    for _, file := range files {
        // Load image
        img, err := imgx.Load(file)
        if err != nil {
            log.Printf("Failed to load %s: %v", file, err)
            continue
        }

        // Process with method chaining: resize, enhance contrast, and sharpen
        processed := img.Resize(1920, 0, imgx.Lanczos).
            AdjustContrast(10).
            Sharpen(0.5)

        // Save with new name
        basename := filepath.Base(file)
        outname := "output/" + strings.TrimSuffix(basename, ".jpg") + "_processed.jpg"

        if err := processed.Save(outname); err != nil {
            log.Printf("Failed to save %s: %v", outname, err)
        }
    }
}
Example 3: Add Watermark
package main

import (
    "image"
    "log"
    "github.com/razzkumar/imgx"
)

func main() {
    // Load main image
    img, err := imgx.Load("photo.jpg")
    if err != nil {
        log.Fatal(err)
    }

    // Load watermark
    watermark, err := imgx.Load("watermark.png")
    if err != nil {
        log.Fatal(err)
    }

    // Resize watermark to 20% of image width
    bounds := img.Bounds()
    wmWidth := bounds.Dx() / 5
    watermark = watermark.Resize(wmWidth, 0, imgx.Lanczos)

    // Position watermark in bottom-right corner
    wmBounds := watermark.Bounds()
    position := image.Pt(
        bounds.Dx()-wmBounds.Dx()-20,
        bounds.Dy()-wmBounds.Dy()-20,
    )

    // Overlay watermark with transparency and save
    result := img.Overlay(watermark, position, 0.6)
    result.Save("watermarked.jpg")
}

Example Output:

Original Image:

Original flower

After adding watermark with Overlay() - Watermark in bottom-right corner with 60% opacity:

Watermarked flower

Example 4: Image Transformations
package main

import (
    "log"
    "github.com/razzkumar/imgx"
)

func main() {
    img, err := imgx.Load("photo.jpg")
    if err != nil {
        log.Fatal(err)
    }

    // Rotate 90 degrees
    img.Rotate90().Save("rotated_90.jpg")

    // Rotate 45 degrees with white background
    img.Rotate(45, imgx.White).Save("rotated_45.jpg")

    // Flip horizontal
    img.FlipH().Save("flipped_h.jpg")

    // Flip vertical
    img.FlipV().Save("flipped_v.jpg")

    // Transpose (flip + rotate)
    img.Transpose().Save("transposed.jpg")
}
Example 5: Image Effects and Filters
package main

import (
    "log"
    "github.com/razzkumar/imgx"
)

func main() {
    img, err := imgx.Load("photo.jpg")
    if err != nil {
        log.Fatal(err)
    }

    // Convert to grayscale
    img.Grayscale().Save("grayscale.jpg")

    // Invert colors
    img.Invert().Save("inverted.jpg")

    // Apply custom convolution (edge detection)
    img.Convolve3x3(
        [9]float64{
            -1, -1, -1,
            -1,  8, -1,
            -1, -1, -1,
        },
        nil,
    ).Save("edges.jpg")

    // Emboss effect
    img.Convolve3x3(
        [9]float64{
            -1, -1, 0,
            -1,  1, 1,
             0,  1, 1,
        },
        nil,
    ).Save("embossed.jpg")
}
Example 6: Working with Different Image Formats
package main

import (
    "log"
    "github.com/razzkumar/imgx"
)

func main() {
    // Load with auto-orientation from EXIF
    img, err := imgx.Load("photo.jpg", imgx.Options{AutoOrient: true})
    if err != nil {
        log.Fatal(err)
    }

    // Process
    processed := img.Resize(800, 0, imgx.Lanczos)

    // Save as different formats (format auto-detected from extension)
    processed.Save("output.jpg")  // JPEG
    processed.Save("output.png")  // PNG
    processed.Save("output.gif")  // GIF
    processed.Save("output.tiff") // TIFF
    processed.Save("output.bmp")  // BMP
}
Example 7: Extract Image Metadata
package main

import (
    "fmt"
    "log"
    "github.com/razzkumar/imgx"
)

func main() {
    // Extract metadata (uses exiftool if available, falls back to basic metadata)
    metadata, err := imgx.Metadata("photo.jpg")
    if err != nil {
        log.Fatal(err)
    }

    // Display basic information (always available)
    fmt.Printf("File: %s\n", metadata.FilePath)
    fmt.Printf("Format: %s\n", metadata.Format)
    fmt.Printf("Dimensions: %dx%d\n", metadata.Width, metadata.Height)
    fmt.Printf("Megapixels: %.2f MP\n", metadata.Megapixels)

    // Display extended metadata if available (requires exiftool)
    if metadata.HasExtended {
        fmt.Println("\nExtended Metadata:")
        if metadata.CameraMake != "" {
            fmt.Printf("Camera: %s %s\n", metadata.CameraMake, metadata.CameraModel)
        }
        if metadata.DateTimeOriginal != "" {
            fmt.Printf("Date Taken: %s\n", metadata.DateTimeOriginal)
        }
        if metadata.ISO != "" {
            fmt.Printf("ISO: %s\n", metadata.ISO)
        }
        if metadata.GPSLatitude != "" {
            fmt.Printf("GPS: %s, %s\n", metadata.GPSLatitude, metadata.GPSLongitude)
        }
    } else {
        fmt.Println("\nNote: Install exiftool for comprehensive metadata")
    }

    // Extract basic metadata only (skip exiftool check)
    basicMeta, err := imgx.Metadata("photo.jpg", imgx.WithBasicOnly())
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("\nFile Size: %d bytes\n", basicMeta.FileSize)
}
Example 8: AI Object Detection
package main

import (
    "context"
    "fmt"
    "log"
    "github.com/razzkumar/imgx"
    "github.com/razzkumar/imgx/detection"
)

func main() {
    // Load image
    img, err := imgx.Load("photo.jpg")
    if err != nil {
        log.Fatal(err)
    }

    // Detect objects using the local Ollama model
    ctx := context.Background()
    result, err := img.Detect(ctx, "ollama")
    if err != nil {
        log.Fatal(err)
    }

    // Display detected labels
    fmt.Println("Detected objects:")
    for _, label := range result.Labels {
        fmt.Printf("- %s (%.1f%% confidence)\n", label.Name, label.Confidence*100)
    }

    // Use AWS Rekognition for image properties
    opts := &detection.DetectOptions{
        Features: []detection.Feature{detection.FeatureProperties},
    }
    result, err = img.Detect(ctx, "aws", opts)
    if err != nil {
        log.Fatal(err)
    }

    // Display image properties
    fmt.Printf("\nBrightness: %s\n", result.Properties["brightness"])
    fmt.Printf("Dominant colors: %s\n", result.Properties["dominant_colors"])
}

For complete detection API documentation including all providers, features, and examples, see Detection Documentation.

Automatic Processing Metadata Tracking

imgx automatically tracks all processing operations applied to images and can embed this information as XMP metadata when saving. This feature provides full transparency about how images were processed.

How It Works

When you use the instance-based API (imgx.Load(), method chaining), imgx automatically:

  1. Records every operation (resize, rotate, adjust, etc.)
  2. Tracks parameters for each operation
  3. Timestamps each operation
  4. Embeds this information as XMP metadata when saving (if exiftool is available)
Basic Usage
// Load an image - metadata tracking starts automatically
img, _ := imgx.Load("photo.jpg")

// Apply operations - each operation is recorded
result := img.Resize(800, 0, imgx.Lanczos).
    AdjustBrightness(10).
    AdjustContrast(20).
    Sharpen(1.0)

// Save - metadata is automatically embedded in the output file
result.Save("output.jpg")

// The output.jpg file now contains XMP metadata with:
// - Software: imgx v1.0.0
// - Processing history: resize, adjust brightness, adjust contrast, sharpen
// - Parameters for each operation
// - Timestamps for each operation
Disabling Metadata

There are three ways to disable metadata tracking:

1. Per-Image (at load time):

// Disable metadata for a specific image
img, _ := imgx.Load("photo.jpg", imgx.Options{DisableMetadata: true})
img.Resize(800, 0, imgx.Lanczos).Save("output.jpg")  // No metadata written

2. Per-Save Operation:

// Process with metadata tracking, but don't write it
img, _ := imgx.Load("photo.jpg")
result := img.Resize(800, 0, imgx.Lanczos)
result.Save("output.jpg", imgx.WithoutMetadata())  // Skip metadata on save

3. Globally (environment variable):

# Disable metadata for all operations
export IMGX_ADD_METADATA=false

# Or in code:
imgx.SetAddMetadata(false)
Working with Standard Library

The instance-based API is fully compatible with Go's standard image.Image interface:

// Load from standard library image
var stdImg image.Image = loadFromSomewhere()
img := imgx.FromImage(stdImg)

// Process with metadata tracking
result := img.Resize(800, 0, imgx.Lanczos)

// Convert back to standard library type if needed
nrgba := result.ToNRGBA()
Method Chaining

All processing methods return new *imgx.Image instances, allowing for clean method chaining:

img, _ := imgx.Load("photo.jpg")

// Chain multiple operations
result := img.
    Resize(1920, 0, imgx.Lanczos).
    CropCenter(1200, 800).
    AdjustBrightness(10).
    AdjustContrast(15).
    AdjustSaturation(20).
    Sharpen(1.0)

result.Save("processed.jpg")
Migration from Functional API

If you're migrating from the older functional API (imgx.Open, imgx.Resize, etc.), both APIs are still available:

Old (Functional API):

img, _ := imgx.Open("input.jpg")
img = imgx.Resize(img, 800, 0, imgx.Lanczos)
img = imgx.AdjustContrast(img, 20)
imgx.Save(img, "output.jpg")

New (Instance-Based API with metadata):

img, _ := imgx.Load("input.jpg")
img = img.Resize(800, 0, imgx.Lanczos).AdjustContrast(20)
img.Save("output.jpg")

The functional API remains available for backward compatibility but does not include automatic metadata tracking.

FAQ

Incorrect image orientation after processing (e.g. an image appears rotated after resizing)

Most probably, the given image contains the EXIF orientation tag. The standard image/* packages do not support loading and saving this kind of information. To fix the issue, try opening images with the AutoOrientation decode option. If this option is set to true, the image orientation is changed after decoding, according to the orientation tag (if present). Here's the example:

img, err := imgx.Load("test.jpg", imgx.Options{AutoOrient: true})
What's the difference between imaging and gift packages?

imaging is designed to be a lightweight and simple image manipulation package. It provides basic image processing functions and a few helper functions such as Open and Save. It consistently returns *image.NRGBA image type (8 bits per channel, RGBA).

Advanced Example: Image Collage

This example demonstrates creating a 2x2 collage with different effects applied to each quadrant:

package main

import (
	"image"
	"image/color"
	"log"

	"github.com/razzkumar/imgx"
)

func main() {
	// Load a test image.
	img, err := imgx.Load("testdata/flower.jpg")
	if err != nil {
		log.Fatalf("failed to load image: %v", err)
	}

	// Crop and resize using method chaining
	src := img.CropAnchor(300, 300, imgx.Center).Resize(200, 0, imgx.Lanczos)

	// Create a blurred version of the image.
	img1 := src.Blur(5)

	// Create a grayscale version with higher contrast and sharpness.
	img2 := src.Grayscale().AdjustContrast(20).Sharpen(2)

	// Create an inverted version of the image.
	img3 := src.Invert()

	// Create an embossed version using a convolution filter.
	img4 := src.Convolve3x3(
		[9]float64{
			-1, -1, 0,
			-1, 1, 1,
			0, 1, 1,
		},
		nil,
	)

	// Create a new 400x400px image and paste the four produced images into it.
	dst := imgx.NewImage(400, 400, color.NRGBA{0, 0, 0, 0})
	dst = dst.Paste(img1, image.Pt(0, 0))      // Top-left: Blurred
	dst = dst.Paste(img2, image.Pt(0, 200))    // Bottom-left: Grayscale + Enhanced
	dst = dst.Paste(img3, image.Pt(200, 0))    // Top-right: Inverted
	dst = dst.Paste(img4, image.Pt(200, 200))  // Bottom-right: Embossed

	// Save the resulting image as JPEG.
	err = dst.Save("testdata/out_example.jpg")
	if err != nil {
		log.Fatalf("failed to save image: %v", err)
	}

	log.Println("Collage created successfully: testdata/out_example.jpg")
}

Output: A 2x2 grid showing the same image with four different effects applied.

Features

imgx provides a comprehensive set of image processing capabilities:

Resizing & Transformations:

  • Multiple resampling filters (Lanczos, CatmullRom, Linear, Box, NearestNeighbor, etc.)
  • Resize, Fit, Fill, Thumbnail operations
  • Rotate (90°, 180°, 270°, arbitrary angles)
  • Flip horizontal/vertical, Transpose, Transverse
  • Crop with anchor points

Color Adjustments:

  • Brightness, Contrast, Gamma correction
  • Saturation, Hue adjustments
  • Grayscale conversion
  • Color inversion

Effects & Filters:

  • Gaussian blur
  • Unsharp mask sharpening
  • Custom 3x3 and 5x5 convolution kernels
  • Edge detection, emboss, and custom effects

Image Composition:

  • Paste images together
  • Overlay with alpha blending
  • Watermarking support
  • Create collages and thumbnails

I/O & Format Support:

  • Formats: JPEG, PNG, GIF, TIFF, BMP
  • EXIF auto-orientation for JPEG files
  • Encode/Decode with custom options
  • Format auto-detection from file extensions
  • Metadata extraction (EXIF, IPTC, XMP with exiftool)
  • Automatic processing metadata tracking and XMP embedding

AI Object Detection:

  • Support for Google Gemini, AWS Rekognition, and OpenAI Vision
  • Label/object detection with confidence scores
  • Text extraction (OCR)
  • Face detection with attributes
  • Image quality analysis (brightness, sharpness, contrast)
  • Dominant color extraction
  • Natural language descriptions
  • See Detection Documentation for details

API Design:

  • Instance-based API with method chaining for clean, readable code
  • Automatic operation tracking and metadata embedding
  • Functional API still available for backward compatibility
  • Interoperable with Go's standard image.Image interface

Performance:

  • Parallel processing across CPU cores
  • Optimized scanners for common image formats
  • Separable filter approach for resize and blur
  • Memory-efficient streaming operations

Performance

imgx is designed for high performance with parallel processing and optimized algorithms.

Running Benchmarks
# Run all benchmarks
go test -bench=.

# Run specific benchmark with memory stats
go test -bench=BenchmarkResize -benchmem

# Run benchmarks multiple times for accuracy
go test -bench=. -benchtime=10s -count=3
Example Benchmark Results
BenchmarkResize-8        100   12.3 ms/op   8.2 MB/s   4.5 MB/op
BenchmarkBlur-8          50    24.5 ms/op   4.1 MB/s   6.2 MB/op
BenchmarkRotate90-8      200   5.8 ms/op    17.2 MB/s  2.1 MB/op
BenchmarkGrayscale-8     300   4.2 ms/op    23.8 MB/s  1.8 MB/op

The library automatically utilizes all available CPU cores for operations on large images. You can control parallelism using:

imgx.SetMaxProcs(4)  // Limit to 4 CPU cores

Acknowledgments

imgx is a brand new image processing library designed from the ground up with modern Go practices. We drew inspiration from:

  • imaging by Grigory Dryapak - for foundational image processing algorithms and API design patterns
  • go-exiftool - for metadata handling approaches and exiftool integration concepts
What Makes imgx Different?

imgx is a complete reimagination with a modern architecture:

  • Instance-based API: Fluent method-chaining design for intuitive, readable code
  • Automatic metadata tracking: Built-in operation history with XMP embedding
  • Modern Go 1.21+ features:
    • Range over integers, built-in min/max
    • WaitGroup.Go() for goroutines
    • Latest benchmarking patterns
  • Comprehensive CLI: Full-featured command-line tool with metadata support
  • Clean architecture: Modular design with clear separation of concerns
  • Developer-friendly: Extensive documentation, examples, and type safety
Incorrect image orientation after processing (e.g. an image appears rotated after resizing)

Most probably, the given image contains the EXIF orientation tag. The standard image/* packages do not support loading and saving this kind of information. To fix the issue, try opening images with the AutoOrientation decode option. If this option is set to true, the image orientation is changed after decoding, according to the orientation tag (if present). Here's the example:

img, err := imgx.Load("test.jpg", imgx.Options{AutoOrient: true})
What's the difference between imaging and gift packages?

imaging is designed to be a lightweight and simple image manipulation package. It provides basic image processing functions and a few helper functions such as Open and Save. It consistently returns *image.NRGBA image type (8 bits per channel, RGBA).

Advanced Example: Image Collage

This example demonstrates creating a 2x2 collage with different effects applied to each quadrant:

package main

import (
	"image"
	"image/color"
	"log"

	"github.com/razzkumar/imgx"
)

func main() {
	// Load a test image.
	img, err := imgx.Load("testdata/flower.jpg")
	if err != nil {
		log.Fatalf("failed to load image: %v", err)
	}

	// Crop and resize using method chaining
	src := img.CropAnchor(300, 300, imgx.Center).Resize(200, 0, imgx.Lanczos)

	// Create a blurred version of the image.
	img1 := src.Blur(5)

	// Create a grayscale version with higher contrast and sharpness.
	img2 := src.Grayscale().AdjustContrast(20).Sharpen(2)

	// Create an inverted version of the image.
	img3 := src.Invert()

	// Create an embossed version using a convolution filter.
	img4 := src.Convolve3x3(
		[9]float64{
			-1, -1, 0,
			-1, 1, 1,
			0, 1, 1,
		},
		nil,
	)

	// Create a new 400x400px image and paste the four produced images into it.
	dst := imgx.NewImage(400, 400, color.NRGBA{0, 0, 0, 0})
	dst = dst.Paste(img1, image.Pt(0, 0))      // Top-left: Blurred
	dst = dst.Paste(img2, image.Pt(0, 200))    // Bottom-left: Grayscale + Enhanced
	dst = dst.Paste(img3, image.Pt(200, 0))    // Top-right: Inverted
	dst = dst.Paste(img4, image.Pt(200, 200))  // Bottom-right: Embossed

	// Save the resulting image as JPEG.
	err = dst.Save("testdata/out_example.jpg")
	if err != nil {
		log.Fatalf("failed to save image: %v", err)
	}

	log.Println("Collage created successfully: testdata/out_example.jpg")
}

Output: A 2x2 grid showing the same image with four different effects applied.

Features

imgx provides a comprehensive set of image processing capabilities:

Resizing & Transformations:

  • Multiple resampling filters (Lanczos, CatmullRom, Linear, Box, NearestNeighbor, etc.)
  • Resize, Fit, Fill, Thumbnail operations
  • Rotate (90°, 180°, 270°, arbitrary angles)
  • Flip horizontal/vertical, Transpose, Transverse
  • Crop with anchor points

Color Adjustments:

  • Brightness, Contrast, Gamma correction
  • Saturation, Hue adjustments
  • Grayscale conversion
  • Color inversion

Effects & Filters:

  • Gaussian blur
  • Unsharp mask sharpening
  • Custom 3x3 and 5x5 convolution kernels
  • Edge detection, emboss, and custom effects

Image Composition:

  • Paste images together
  • Overlay with alpha blending
  • Watermarking support
  • Create collages and thumbnails

I/O & Format Support:

  • Formats: JPEG, PNG, GIF, TIFF, BMP
  • EXIF auto-orientation for JPEG files
  • Encode/Decode with custom options
  • Format auto-detection from file extensions
  • Metadata extraction (EXIF, IPTC, XMP with exiftool)
  • Automatic processing metadata tracking and XMP embedding

AI Object Detection:

  • Support for Google Gemini, AWS Rekognition, and OpenAI Vision
  • Label/object detection with confidence scores
  • Text extraction (OCR)
  • Face detection with attributes
  • Image quality analysis (brightness, sharpness, contrast)
  • Dominant color extraction
  • Natural language descriptions
  • See Detection Documentation for details

API Design:

  • Instance-based API with method chaining for clean, readable code
  • Automatic operation tracking and metadata embedding
  • Functional API still available for backward compatibility
  • Interoperable with Go's standard image.Image interface

Performance:

  • Parallel processing across CPU cores
  • Optimized scanners for common image formats
  • Separable filter approach for resize and blur
  • Memory-efficient streaming operations

Performance

imgx is designed for high performance with parallel processing and optimized algorithms.

Running Benchmarks
# Run all benchmarks
go test -bench=.

# Run specific benchmark with memory stats
go test -bench=BenchmarkResize -benchmem

# Run benchmarks multiple times for accuracy
go test -bench=. -benchtime=10s -count=3
Example Benchmark Results
BenchmarkResize-8        100   12.3 ms/op   8.2 MB/s   4.5 MB/op
BenchmarkBlur-8          50    24.5 ms/op   4.1 MB/s   6.2 MB/op
BenchmarkRotate90-8      200   5.8 ms/op    17.2 MB/s  2.1 MB/op
BenchmarkGrayscale-8     300   4.2 ms/op    23.8 MB/s  1.8 MB/op

The library automatically utilizes all available CPU cores for operations on large images. You can control parallelism using:

imgx.SetMaxProcs(4)  // Limit to 4 CPU cores

Acknowledgments

imgx is a brand new image processing library designed from the ground up with modern Go practices. We drew inspiration from:

  • imaging by Grigory Dryapak - for foundational image processing algorithms and API design patterns
  • go-exiftool - for metadata handling approaches and exiftool integration concepts
What Makes imgx Different?

imgx is a complete reimagination with a modern architecture:

  • Instance-based API: Fluent method-chaining design for intuitive, readable code
  • Automatic metadata tracking: Built-in operation history with XMP embedding
  • Modern Go 1.21+ features:
    • Range over integers, built-in min/max
    • WaitGroup.Go() for goroutines
    • Latest benchmarking patterns
  • Comprehensive CLI: Full-featured command-line tool with metadata support
  • Clean architecture: Modular design with clear separation of concerns
  • Developer-friendly: Extensive documentation, examples, and type safety

Thank you to the Go community and these projects for the inspiration!

License

This project is licensed under the MIT License. See the- License file for details.

Copyright (c) 2025 razzkumar

Documentation

Overview

Package imgx provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.).

All the image processing functions provided by the package accept any image type that implements image.Image interface as an input, and return a new image of *image.NRGBA type (32bit RGBA colors, non-premultiplied alpha).

Installation

To install the CLI tool:

go install github.com/razzkumar/imgx/cmd/imgx@latest
Example
package main

import (
	"image"
	"image/color"
	"log"

	"github.com/razzkumar/imgx"
)

func main() {
	// Load a test image.
	src, err := imgx.Load("testdata/flower.jpg")
	if err != nil {
		log.Fatalf("failed to load image: %v", err)
	}

	// Crop the original image to 300x300px size using the center anchor.
	src = src.CropAnchor(300, 300, imgx.Center)

	// Resize the cropped image to width = 200px preserving the aspect ratio.
	src = src.Resize(200, 0, imgx.Lanczos)

	// Create a blurred version of the image.
	img1 := src.Blur(5)

	// Create a grayscale version of the image with higher contrast and sharpness.
	img2 := src.Grayscale().AdjustContrast(20).Sharpen(2)

	// Create an inverted version of the image.
	img3 := src.Invert()

	// Create an embossed version of the image using a convolution filter.
	img4 := src.Convolve3x3(
		[9]float64{
			-1, -1, 0,
			-1, 1, 1,
			0, 1, 1,
		},
		nil,
	)

	// Create a new image and paste the four produced images into it.
	dst := imgx.NewImage(400, 400, color.NRGBA{0, 0, 0, 0})
	dst = dst.Paste(img1, image.Pt(0, 0))
	dst = dst.Paste(img2, image.Pt(0, 200))
	dst = dst.Paste(img3, image.Pt(200, 0))
	dst = dst.Paste(img4, image.Pt(200, 200))

	// Save the resulting image as JPEG.
	err = dst.Save("testdata/out_example.jpg")
	if err != nil {
		log.Fatalf("failed to save image: %v", err)
	}
}

Index

Examples

Constants

View Source
const Author = "razzkumar"

Author is the default author for imgx

View Source
const ProjectURL = "https://github.com/razzkumar/imgx"

ProjectURL is the GitHub URL of the project

View Source
const Version = "1.2.2"

Version is the current version of imgx This is the single source of truth for versioning Update this when releasing new versions

Variables

View Source
var ErrUnsupportedFormat = errors.New("imaging: unsupported image format")

ErrUnsupportedFormat means the given image format is not supported.

Functions

func AdjustBrightness

func AdjustBrightness(img image.Image, percentage float64) *image.NRGBA

AdjustBrightness changes the brightness of the image using the percentage parameter and returns the adjusted image. The percentage must be in range (-100, 100). The percentage = 0 gives the original image. The percentage = -100 gives solid black image. The percentage = 100 gives solid white image.

Examples:

dstImage = imaging.AdjustBrightness(srcImage, -15) // Decrease image brightness by 15%.
dstImage = imaging.AdjustBrightness(srcImage, 10) // Increase image brightness by 10%.

func AdjustContrast

func AdjustContrast(img image.Image, percentage float64) *image.NRGBA

AdjustContrast changes the contrast of the image using the percentage parameter and returns the adjusted image. The percentage must be in range (-100, 100). The percentage = 0 gives the original image. The percentage = -100 gives solid gray image.

Examples:

dstImage = imaging.AdjustContrast(srcImage, -10) // Decrease image contrast by 10%.
dstImage = imaging.AdjustContrast(srcImage, 20) // Increase image contrast by 20%.

func AdjustFunc

func AdjustFunc(img image.Image, fn func(c color.NRGBA) color.NRGBA) *image.NRGBA

AdjustFunc applies the fn function to each pixel of the img image and returns the adjusted image.

Example:

dstImage = imaging.AdjustFunc(
	srcImage,
	func(c color.NRGBA) color.NRGBA {
		// Shift the red channel by 16.
		r := int(c.R) + 16
		if r > 255 {
			r = 255
		}
		return color.NRGBA{uint8(r), c.G, c.B, c.A}
	}
)

func AdjustGamma

func AdjustGamma(img image.Image, gamma float64) *image.NRGBA

AdjustGamma performs a gamma correction on the image and returns the adjusted image. Gamma parameter must be positive. Gamma = 1.0 gives the original image. Gamma less than 1.0 darkens the image and gamma greater than 1.0 lightens it.

Example:

dstImage = imaging.AdjustGamma(srcImage, 0.7)

func AdjustHue

func AdjustHue(img image.Image, shift float64) *image.NRGBA

AdjustHue changes the hue of the image using the shift parameter (measured in degrees) and returns the adjusted image. The shift = 0 (or 360 / -360 / etc.) gives the original image. The shift = 180 (or -180) corresponds to a 180° degree rotation of the color wheel and thus gives the image with its hue inverted for each pixel.

Examples:

dstImage = imaging.AdjustHue(srcImage, 90) // Shift Hue by 90°.
dstImage = imaging.AdjustHue(srcImage, -30) // Shift Hue by -30°.

func AdjustSaturation

func AdjustSaturation(img image.Image, percentage float64) *image.NRGBA

AdjustSaturation changes the saturation of the image using the percentage parameter and returns the adjusted image. The percentage must be in the range (-100, 100). The percentage = 0 gives the original image. The percentage = 100 gives the image with the saturation value doubled for each pixel. The percentage = -100 gives the image with the saturation value zeroed for each pixel (grayscale).

Examples:

dstImage = imaging.AdjustSaturation(srcImage, 25) // Increase image saturation by 25%.
dstImage = imaging.AdjustSaturation(srcImage, -10) // Decrease image saturation by 10%.

func AdjustSigmoid

func AdjustSigmoid(img image.Image, midpoint, factor float64) *image.NRGBA

AdjustSigmoid changes the contrast of the image using a sigmoidal function and returns the adjusted image. It's a non-linear contrast change useful for photo adjustments as it preserves highlight and shadow detail. The midpoint parameter is the midpoint of contrast that must be between 0 and 1, typically 0.5. The factor parameter indicates how much to increase or decrease the contrast, typically in range (-10, 10). If the factor parameter is positive the image contrast is increased otherwise the contrast is decreased.

Examples:

dstImage = imaging.AdjustSigmoid(srcImage, 0.5, 3.0) // Increase the contrast.
dstImage = imaging.AdjustSigmoid(srcImage, 0.5, -3.0) // Decrease the contrast.

func Blur

func Blur(img image.Image, sigma float64) *image.NRGBA

Blur produces a blurred version of the image using a Gaussian function. Sigma parameter must be positive and indicates how much the image will be blurred.

Example:

dstImage := imaging.Blur(srcImage, 3.5)

func Clone

func Clone(img image.Image) *image.NRGBA

Clone returns a copy of the given image.

func Convolve3x3

func Convolve3x3(img image.Image, kernel [9]float64, options *ConvolveOptions) *image.NRGBA

Convolve3x3 convolves the image with the specified 3x3 convolution kernel. Default parameters are used if a nil *ConvolveOptions is passed.

func Convolve5x5

func Convolve5x5(img image.Image, kernel [25]float64, options *ConvolveOptions) *image.NRGBA

Convolve5x5 convolves the image with the specified 5x5 convolution kernel. Default parameters are used if a nil *ConvolveOptions is passed.

func Crop

func Crop(img image.Image, rect image.Rectangle) *image.NRGBA

Crop cuts out a rectangular region with the specified bounds from the image and returns the cropped image.

func CropAnchor

func CropAnchor(img image.Image, width, height int, anchor Anchor) *image.NRGBA

CropAnchor cuts out a rectangular region with the specified size from the image using the specified anchor point and returns the cropped image.

func CropCenter

func CropCenter(img image.Image, width, height int) *image.NRGBA

CropCenter cuts out a rectangular region with the specified size from the center of the image and returns the cropped image.

func Decode

func Decode(r io.Reader, opts ...DecodeOption) (image.Image, error)

Decode reads an image from r.

func Encode

func Encode(w io.Writer, img image.Image, format Format, opts ...EncodeOption) error

Encode writes the image img to w in the specified format (JPEG, PNG, GIF, TIFF or BMP).

func Fill

func Fill(img image.Image, width, height int, anchor Anchor, filter ResampleFilter) *image.NRGBA

Fill creates an image with the specified dimensions and fills it with the scaled source image. To achieve the correct aspect ratio without stretching, the source image will be cropped.

Example:

dstImage := imaging.Fill(srcImage, 800, 600, imaging.Center, imaging.Lanczos)

func Fit

func Fit(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA

Fit scales down the image using the specified resample filter to fit the specified maximum width and height and returns the transformed image.

Example:

dstImage := imaging.Fit(srcImage, 800, 600, imaging.Lanczos)

func FlipH

func FlipH(img image.Image) *image.NRGBA

FlipH flips the image horizontally (from left to right) and returns the transformed image.

func FlipV

func FlipV(img image.Image) *image.NRGBA

FlipV flips the image vertically (from top to bottom) and returns the transformed image.

func GetAddMetadata added in v1.0.0

func GetAddMetadata() bool

GetAddMetadata returns the global metadata setting

func GetDefaultAuthor added in v1.0.0

func GetDefaultAuthor() string

GetDefaultAuthor returns the global default author setting

func Grayscale

func Grayscale(img image.Image) *image.NRGBA

Grayscale produces a grayscale version of the image.

func Histogram

func Histogram(img image.Image) [256]float64

Histogram returns a normalized histogram of an image.

Resulting histogram is represented as an array of 256 floats, where histogram[i] is a probability of a pixel being of a particular luminance i.

func Invert

func Invert(img image.Image) *image.NRGBA

Invert produces an inverted (negated) version of the image.

func New

func New(width, height int, fillColor color.Color) *image.NRGBA

New creates a new image with the specified width and height, and fills it with the specified color.

func Overlay

func Overlay(background, img image.Image, pos image.Point, opacity float64) *image.NRGBA

Overlay draws the img image over the background image at given position and returns the combined image. Opacity parameter is the opacity of the img image layer, used to compose the images, it must be from 0.0 to 1.0.

Examples:

// Draw spriteImage over backgroundImage at the given position (x=50, y=50).
dstImage := imaging.Overlay(backgroundImage, spriteImage, image.Pt(50, 50), 1.0)

// Blend two opaque images of the same size.
dstImage := imaging.Overlay(imageOne, imageTwo, image.Pt(0, 0), 0.5)

func OverlayCenter

func OverlayCenter(background, img image.Image, opacity float64) *image.NRGBA

OverlayCenter overlays the img image to the center of the background image and returns the combined image. Opacity parameter is the opacity of the img image layer, used to compose the images, it must be from 0.0 to 1.0.

func Paste

func Paste(background, img image.Image, pos image.Point) *image.NRGBA

Paste pastes the img image to the background image at the specified position and returns the combined image.

func PasteCenter

func PasteCenter(background, img image.Image) *image.NRGBA

PasteCenter pastes the img image to the center of the background image and returns the combined image.

func Resize

func Resize(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA

Resize resizes the image to the specified width and height using the specified resampling filter and returns the transformed image. If one of width or height is 0, the image aspect ratio is preserved.

Example:

dstImage := imaging.Resize(srcImage, 800, 600, imaging.Lanczos)

func Rotate

func Rotate(img image.Image, angle float64, bgColor color.Color) *image.NRGBA

Rotate rotates an image by the given angle counter-clockwise . The angle parameter is the rotation angle in degrees. The bgColor parameter specifies the color of the uncovered zone after the rotation.

func Rotate180

func Rotate180(img image.Image) *image.NRGBA

Rotate180 rotates the image 180 degrees counter-clockwise and returns the transformed image.

func Rotate270

func Rotate270(img image.Image) *image.NRGBA

Rotate270 rotates the image 270 degrees counter-clockwise and returns the transformed image.

func Rotate90

func Rotate90(img image.Image) *image.NRGBA

Rotate90 rotates the image 90 degrees counter-clockwise and returns the transformed image.

func SetAddMetadata added in v1.0.0

func SetAddMetadata(enabled bool)

SetAddMetadata configures whether to add metadata globally

func SetDefaultAuthor added in v1.0.0

func SetDefaultAuthor(author string)

SetDefaultAuthor sets the default artist/creator name globally This can be overridden per-image using WithAuthor() or SetAuthor() Empty string means use the default "razzkumar"

func SetMaxProcs

func SetMaxProcs(value int)

SetMaxProcs limits the number of concurrent processing goroutines to the given value. A value <= 0 clears the limit.

func Sharpen

func Sharpen(img image.Image, sigma float64) *image.NRGBA

Sharpen produces a sharpened version of the image. Sigma parameter must be positive and indicates how much the image will be sharpened.

Example:

dstImage := imaging.Sharpen(srcImage, 3.5)

func Thumbnail

func Thumbnail(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA

Thumbnail scales the image up or down using the specified resample filter, crops it to the specified width and hight and returns the transformed image.

Example:

dstImage := imaging.Thumbnail(srcImage, 100, 100, imaging.Lanczos)

func Transpose

func Transpose(img image.Image) *image.NRGBA

Transpose flips the image horizontally and rotates 90 degrees counter-clockwise.

func Transverse

func Transverse(img image.Image) *image.NRGBA

Transverse flips the image vertically and rotates 90 degrees counter-clockwise.

func Watermark

func Watermark(img image.Image, opts WatermarkOptions) *image.NRGBA

Watermark adds a text watermark to an image and returns the result.

Example:

opts := imaging.WatermarkOptions{
	Text:     "Copyright 2025",
	Position: imaging.BottomRight,
	Opacity:  0.5,
}
watermarkedImage := imaging.Watermark(srcImage, opts)

Types

type Anchor

type Anchor int

Anchor is the anchor point for image alignment.

const (
	Center Anchor = iota
	TopLeft
	Top
	TopRight
	Left
	Right
	BottomLeft
	Bottom
	BottomRight
)

Anchor point positions.

type Config added in v1.0.0

type Config struct {
	AddMetadata   bool
	DefaultAuthor string
	// contains filtered or unexported fields
}

Config holds global configuration for imgx

type ConvolveOptions

type ConvolveOptions struct {
	// If Normalize is true the kernel is normalized before convolution.
	Normalize bool

	// If Abs is true the absolute value of each color channel is taken after convolution.
	Abs bool

	// Bias is added to each color channel value after convolution.
	Bias int
}

ConvolveOptions are convolution parameters.

type DecodeOption

type DecodeOption func(*decodeConfig)

DecodeOption sets an optional parameter for the Decode and Open functions.

func AutoOrientation

func AutoOrientation(enabled bool) DecodeOption

AutoOrientation returns a DecodeOption that sets the auto-orientation mode. If auto-orientation is enabled, the image will be transformed after decoding according to the EXIF orientation tag (if present). By default it's disabled.

type EncodeOption

type EncodeOption func(*encodeConfig)

EncodeOption sets an optional parameter for the Encode and Save functions.

func GIFDrawer

func GIFDrawer(drawer draw.Drawer) EncodeOption

GIFDrawer returns an EncodeOption that sets the drawer that is used to convert the source image to the desired palette of the GIF-encoded image.

func GIFNumColors

func GIFNumColors(numColors int) EncodeOption

GIFNumColors returns an EncodeOption that sets the maximum number of colors used in the GIF-encoded image. It ranges from 1 to 256. Default is 256.

func GIFQuantizer

func GIFQuantizer(quantizer draw.Quantizer) EncodeOption

GIFQuantizer returns an EncodeOption that sets the quantizer that is used to produce a palette of the GIF-encoded image.

func JPEGQuality

func JPEGQuality(quality int) EncodeOption

JPEGQuality returns an EncodeOption that sets the output JPEG quality. Quality ranges from 1 to 100 inclusive, higher is better. Default is 95.

func PNGCompressionLevel

func PNGCompressionLevel(level png.CompressionLevel) EncodeOption

PNGCompressionLevel returns an EncodeOption that sets the compression level of the PNG-encoded image. Default is png.DefaultCompression.

type Format

type Format int

Format is an image file format.

const (
	JPEG Format = iota
	PNG
	GIF
	TIFF
	BMP
)

Image file formats.

func FormatFromExtension

func FormatFromExtension(ext string) (Format, error)

FormatFromExtension parses image format from filename extension: "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported.

func FormatFromFilename

func FormatFromFilename(filename string) (Format, error)

FormatFromFilename parses image format from filename: "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported.

func (Format) String

func (f Format) String() string

type Image added in v1.0.0

type Image struct {
	// contains filtered or unexported fields
}

Image represents an image with processing metadata

func FromImage added in v1.0.0

func FromImage(img image.Image, opts ...Options) *Image

FromImage creates an Image instance from an existing image.Image Optionally pass Options to configure metadata

Examples:

img := imgx.FromImage(stdImg)  // use defaults
img := imgx.FromImage(stdImg, imgx.Options{Author: "Jane Doe"})

func Load added in v1.0.0

func Load(path string, opts ...Options) (*Image, error)

Load loads an image from a file path and returns an Image instance Optionally pass Options to configure loading behavior

Examples:

img, err := imgx.Load("photo.jpg")  // use defaults
img, err := imgx.Load("photo.jpg", imgx.Options{AutoOrient: true})
img, err := imgx.Load("photo.jpg", imgx.Options{Author: "John Doe"})

func NewImage added in v1.0.0

func NewImage(width, height int, fillColor color.Color, opts ...Options) *Image

NewImage creates a new blank Image with the specified dimensions and fill color Optionally pass Options to configure metadata

Examples:

img := imgx.NewImage(800, 600, color.White)  // use defaults
img := imgx.NewImage(800, 600, color.White, imgx.Options{Author: "Bob"})

func (*Image) AdjustBrightness added in v1.0.0

func (img *Image) AdjustBrightness(percentage float64) *Image

AdjustBrightness adjusts the brightness of the image

func (*Image) AdjustContrast added in v1.0.0

func (img *Image) AdjustContrast(percentage float64) *Image

AdjustContrast adjusts the contrast of the image

func (*Image) AdjustGamma added in v1.0.0

func (img *Image) AdjustGamma(gamma float64) *Image

AdjustGamma adjusts the gamma of the image

func (*Image) AdjustHue added in v1.0.0

func (img *Image) AdjustHue(shift float64) *Image

AdjustHue adjusts the hue of the image

func (*Image) AdjustSaturation added in v1.0.0

func (img *Image) AdjustSaturation(percentage float64) *Image

AdjustSaturation adjusts the saturation of the image

func (*Image) AdjustSigmoid added in v1.0.0

func (img *Image) AdjustSigmoid(midpoint, factor float64) *Image

AdjustSigmoid applies a sigmoid function to the image

func (*Image) Blur added in v1.0.0

func (img *Image) Blur(sigma float64) *Image

Blur applies Gaussian blur to the image

func (*Image) Bounds added in v1.0.0

func (img *Image) Bounds() image.Rectangle

Bounds returns the bounds of the image

func (*Image) Convolve3x3 added in v1.0.0

func (img *Image) Convolve3x3(kernel [9]float64, options *ConvolveOptions) *Image

Convolve3x3 applies a 3x3 convolution kernel to the image

func (*Image) Convolve5x5 added in v1.0.0

func (img *Image) Convolve5x5(kernel [25]float64, options *ConvolveOptions) *Image

Convolve5x5 applies a 5x5 convolution kernel to the image

func (*Image) Crop added in v1.0.0

func (img *Image) Crop(rect image.Rectangle) *Image

Crop cuts out a rectangular region from the image

func (*Image) CropAnchor added in v1.0.0

func (img *Image) CropAnchor(width, height int, anchor Anchor) *Image

CropAnchor cuts out a rectangular region with the specified size using the anchor point

func (*Image) CropCenter added in v1.0.0

func (img *Image) CropCenter(width, height int) *Image

CropCenter cuts out a rectangular region from the center of the image

func (*Image) Detect added in v1.1.0

func (img *Image) Detect(ctx context.Context, provider string, opts ...*detection.DetectOptions) (*detection.DetectionResult, error)

Detect performs object detection on the image using the specified provider and returns detection results.

Supported providers:

  • "ollama" or "gemma3" - Local Ollama server (default, uses gemma3 model)
  • "gemini" or "google" - Google Gemini API (requires GEMINI_API_KEY)
  • "aws" - AWS Rekognition (uses AWS credential chain: env vars, ~/.aws/credentials, IAM roles, etc.)
  • "openai" - OpenAI Vision (requires OPENAI_API_KEY)

Example:

img, err := imgx.Load("photo.jpg")
if err != nil {
	log.Fatal(err)
}

ctx := context.Background()
result, err := img.Detect(ctx, "ollama")
if err != nil {
	log.Fatal(err)
}

// Access detection results
for _, label := range result.Labels {
	fmt.Printf("Found: %s (%.2f%% confidence)\n", label.Name, label.Confidence*100)
}

With custom options:

opts := &detection.DetectOptions{
	Features:      []detection.Feature{detection.FeatureLabels, detection.FeatureText},
	MaxResults:    15,
	MinConfidence: 0.7,
	CustomPrompt:  "Is there a dog in this image?",
}
result, err := img.Detect(ctx, "ollama", opts)

func (*Image) Fill added in v1.0.0

func (img *Image) Fill(width, height int, anchor Anchor, filter ResampleFilter) *Image

Fill resizes and crops the image to fill the specified dimensions using the specified anchor point.

func (*Image) Fit added in v1.0.0

func (img *Image) Fit(width, height int, filter ResampleFilter) *Image

Fit scales the image down to fit within the specified maximum width and height while preserving aspect ratio.

func (*Image) FlipH added in v1.0.0

func (img *Image) FlipH() *Image

FlipH flips the image horizontally

func (*Image) FlipV added in v1.0.0

func (img *Image) FlipV() *Image

FlipV flips the image vertically

func (*Image) GetMetadata added in v1.0.0

func (img *Image) GetMetadata() *ProcessingMetadata

GetMetadata returns the processing metadata

func (*Image) Grayscale added in v1.0.0

func (img *Image) Grayscale() *Image

Grayscale converts the image to grayscale

func (*Image) Invert added in v1.0.0

func (img *Image) Invert() *Image

Invert inverts the colors of the image

func (*Image) Overlay added in v1.0.0

func (img *Image) Overlay(src *Image, pos image.Point, opacity float64) *Image

Overlay overlays another image on top of this image with the specified opacity

func (*Image) OverlayCenter added in v1.0.0

func (img *Image) OverlayCenter(src *Image, opacity float64) *Image

OverlayCenter overlays another image at the center with the specified opacity

func (*Image) Paste added in v1.0.0

func (img *Image) Paste(src *Image, pos image.Point) *Image

Paste pastes another image onto this image at the specified position

func (*Image) PasteCenter added in v1.0.0

func (img *Image) PasteCenter(src *Image) *Image

PasteCenter pastes another image at the center of this image

func (*Image) Resize added in v1.0.0

func (img *Image) Resize(width, height int, filter ResampleFilter) *Image

Resize resizes the image to the specified width and height using the specified resampling filter. If width or height is 0, it will be calculated to preserve the aspect ratio.

func (*Image) Rotate added in v1.0.0

func (img *Image) Rotate(angle float64, bgColor color.Color) *Image

Rotate rotates the image by the given angle counter-clockwise. The angle parameter is the rotation angle in degrees. The bgColor parameter specifies the color of the uncovered areas after rotation.

func (*Image) Rotate180 added in v1.0.0

func (img *Image) Rotate180() *Image

Rotate180 rotates the image 180°

func (*Image) Rotate270 added in v1.0.0

func (img *Image) Rotate270() *Image

Rotate270 rotates the image 270° counter-clockwise (90° clockwise)

func (*Image) Rotate90 added in v1.0.0

func (img *Image) Rotate90() *Image

Rotate90 rotates the image 90° counter-clockwise

func (*Image) Save added in v1.0.0

func (img *Image) Save(path string, opts ...SaveOption) error

Save saves the image to the specified path with optional metadata injection

func (*Image) SetAuthor added in v1.0.0

func (img *Image) SetAuthor(author string) *Image

SetAuthor sets the artist/creator name for the image metadata This overrides the default author but keeps creator_tool unchanged

func (*Image) Sharpen added in v1.0.0

func (img *Image) Sharpen(sigma float64) *Image

Sharpen sharpens the image

func (*Image) Thumbnail added in v1.0.0

func (img *Image) Thumbnail(width, height int, filter ResampleFilter) *Image

Thumbnail creates a square thumbnail by cropping and resizing the image.

func (*Image) ToNRGBA added in v1.0.0

func (img *Image) ToNRGBA() *image.NRGBA

ToNRGBA returns the underlying NRGBA image data

func (*Image) Transpose added in v1.0.0

func (img *Image) Transpose() *Image

Transpose flips the image horizontally and rotates 90° counter-clockwise

func (*Image) Transverse added in v1.0.0

func (img *Image) Transverse() *Image

Transverse flips the image vertically and rotates 90° counter-clockwise

func (*Image) Watermark added in v1.0.0

func (img *Image) Watermark(opts WatermarkOptions) *Image

Watermark adds a text watermark to the image

type ImageMetadata added in v1.0.0

type ImageMetadata struct {
	// File Information
	FilePath    string `json:"file_path"`
	FileName    string `json:"file_name"`
	Format      string `json:"format"`
	ContentType string `json:"content_type"` // MIME type (e.g., "image/jpeg", "image/png")
	FileSize    int64  `json:"file_size"`

	// Image Properties
	Width       int     `json:"width"`
	Height      int     `json:"height"`
	AspectRatio string  `json:"aspect_ratio"` // Formatted as "16:9" (Width:Height)
	Megapixels  float64 `json:"megapixels"`
	ColorModel  string  `json:"color_model"`
	Orientation int     `json:"orientation,omitempty"`

	// Image Technical Details
	BitDepth         int     `json:"bit_depth,omitempty"`
	ColorSpace       string  `json:"color_space,omitempty"`
	Compression      string  `json:"compression,omitempty"`
	XResolution      float64 `json:"x_resolution,omitempty"`
	YResolution      float64 `json:"y_resolution,omitempty"`
	ResolutionUnit   string  `json:"resolution_unit,omitempty"`
	ImageDescription string  `json:"image_description,omitempty"`
	UserComment      string  `json:"user_comment,omitempty"`

	// Extended Metadata
	Extended    map[string]any `json:"extended,omitempty"`
	HasExtended bool           `json:"has_extended"`

	// Camera Information
	CameraMake         string `json:"camera_make,omitempty"`
	CameraModel        string `json:"camera_model,omitempty"`
	CameraSerialNumber string `json:"camera_serial_number,omitempty"`
	LensMake           string `json:"lens_make,omitempty"`
	LensModel          string `json:"lens_model,omitempty"`
	LensSerialNumber   string `json:"lens_serial_number,omitempty"`
	LensFocalLengthMin string `json:"lens_focal_length_min,omitempty"`
	LensFocalLengthMax string `json:"lens_focal_length_max,omitempty"`
	FirmwareVersion    string `json:"firmware_version,omitempty"`

	// Camera Settings
	FocalLength          string `json:"focal_length,omitempty"`
	Aperture             string `json:"aperture,omitempty"` // F-number
	ShutterSpeed         string `json:"shutter_speed,omitempty"`
	ISO                  string `json:"iso,omitempty"`
	ExposureCompensation string `json:"exposure_compensation,omitempty"`
	ExposureMode         string `json:"exposure_mode,omitempty"`
	ExposureProgram      string `json:"exposure_program,omitempty"`
	MeteringMode         string `json:"metering_mode,omitempty"`
	WhiteBalance         string `json:"white_balance,omitempty"`
	Flash                string `json:"flash,omitempty"`
	FlashMode            string `json:"flash_mode,omitempty"`
	LightSource          string `json:"light_source,omitempty"`
	SceneCaptureType     string `json:"scene_capture_type,omitempty"`
	SubjectDistance      string `json:"subject_distance,omitempty"`
	FocusMode            string `json:"focus_mode,omitempty"`
	DigitalZoomRatio     string `json:"digital_zoom_ratio,omitempty"`

	// Timestamps
	DateTime          string `json:"date_time,omitempty"`
	DateTimeOriginal  string `json:"date_time_original,omitempty"`
	DateTimeDigitized string `json:"date_time_digitized,omitempty"`
	CreateDate        string `json:"create_date,omitempty"`
	ModifyDate        string `json:"modify_date,omitempty"`
	TimeZone          string `json:"time_zone,omitempty"`

	// GPS Location
	GPSLatitude   string `json:"gps_latitude,omitempty"`
	GPSLongitude  string `json:"gps_longitude,omitempty"`
	GPSAltitude   string `json:"gps_altitude,omitempty"`
	GPSTimestamp  string `json:"gps_timestamp,omitempty"`
	GPSSpeed      string `json:"gps_speed,omitempty"`
	GPSDirection  string `json:"gps_direction,omitempty"`
	GPSSatellites string `json:"gps_satellites,omitempty"`
	GPSDatum      string `json:"gps_datum,omitempty"`

	// Content & Authorship
	Title       string `json:"title,omitempty"`
	Subject     string `json:"subject,omitempty"`
	Keywords    string `json:"keywords,omitempty"`
	Rating      int    `json:"rating,omitempty"`
	Artist      string `json:"artist,omitempty"`
	Copyright   string `json:"copyright,omitempty"`
	Creator     string `json:"creator,omitempty"`
	CreatorTool string `json:"creator_tool,omitempty"`
	Software    string `json:"software,omitempty"`
}

ImageMetadata contains comprehensive image metadata information

func Metadata added in v1.0.0

func Metadata(src string, options ...MetadataOption) (*ImageMetadata, error)

Metadata extracts metadata from an image file. If exiftool is available on the system, returns comprehensive EXIF/IPTC/XMP data. Otherwise, returns basic metadata extracted using Go's image package.

Example:

metadata, err := imgx.Metadata("photo.jpg")
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Dimensions: %dx%d\n", metadata.Width, metadata.Height)
if metadata.HasExtended {
    fmt.Printf("Camera: %s\n", metadata.CameraMake)
}

type MetadataOption added in v1.0.0

type MetadataOption func(*metadataConfig)

MetadataOption configures metadata extraction

func WithBasicOnly added in v1.0.0

func WithBasicOnly() MetadataOption

WithBasicOnly forces basic metadata extraction only (skip exiftool check)

type OperationRecord added in v1.0.0

type OperationRecord struct {
	Action     string
	Parameters string
	Timestamp  time.Time
}

OperationRecord represents a single image processing operation

type Options added in v1.0.0

type Options struct {
	// AutoOrient enables automatic orientation correction based on EXIF data
	AutoOrient bool

	// DisableMetadata disables metadata tracking for this image instance
	DisableMetadata bool

	// Author sets a custom artist/creator name for the image metadata
	// Empty string uses the default author
	Author string
}

Options holds configuration for loading and processing images

type ProcessingMetadata added in v1.0.0

type ProcessingMetadata struct {
	SourcePath  string
	Operations  []OperationRecord
	Software    string // Fixed: "imgx"
	Version     string // Fixed: version from load.go
	Author      string // Customizable: artist/creator name
	ProjectURL  string // Fixed: project URL
	AddMetadata bool

	DetectionResult *detection.DetectionResult `json:"detection_result,omitempty"` // Object detection results
}

ProcessingMetadata contains information about image processing operations

func (*ProcessingMetadata) AddOperation added in v1.0.0

func (m *ProcessingMetadata) AddOperation(action, parameters string)

AddOperation adds a new operation record to the metadata

func (*ProcessingMetadata) Clone added in v1.0.0

Clone creates a deep copy of ProcessingMetadata

type ResampleFilter

type ResampleFilter struct {
	Support float64
	Kernel  func(float64) float64
}

ResampleFilter specifies a resampling filter to be used for image resizing.

General filter recommendations:

- Lanczos
	A high-quality resampling filter for photographic images yielding sharp results.

- CatmullRom
	A sharp cubic filter that is faster than Lanczos filter while providing similar results.

- MitchellNetravali
	A cubic filter that produces smoother results with less ringing artifacts than CatmullRom.

- Linear
	Bilinear resampling filter, produces a smooth output. Faster than cubic filters.

- Box
	Simple and fast averaging filter appropriate for downscaling.
	When upscaling it's similar to NearestNeighbor.

- NearestNeighbor
	Fastest resampling filter, no antialiasing.
var BSpline ResampleFilter

BSpline is a smooth cubic filter (BC-spline; B=1; C=0).

var Bartlett ResampleFilter

Bartlett is a Bartlett-windowed sinc filter (3 lobes).

var Blackman ResampleFilter

Blackman is a Blackman-windowed sinc filter (3 lobes).

var Box ResampleFilter

Box filter (averaging pixels).

var CatmullRom ResampleFilter

CatmullRom is a Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5).

var Cosine ResampleFilter

Cosine is a Cosine-windowed sinc filter (3 lobes).

var Gaussian ResampleFilter

Gaussian is a Gaussian blurring filter.

var Hamming ResampleFilter

Hamming is a Hamming-windowed sinc filter (3 lobes).

var Hann ResampleFilter

Hann is a Hann-windowed sinc filter (3 lobes).

var Hermite ResampleFilter

Hermite cubic spline filter (BC-spline; B=0; C=0).

var Lanczos ResampleFilter

Lanczos filter (3 lobes).

var Linear ResampleFilter

Linear filter.

var MitchellNetravali ResampleFilter

MitchellNetravali is Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3).

var NearestNeighbor ResampleFilter

NearestNeighbor is a nearest-neighbor filter (no anti-aliasing).

var Welch ResampleFilter

Welch is a Welch-windowed sinc filter (parabolic window, 3 lobes).

type SaveConfig added in v1.0.0

type SaveConfig struct {
	DisableMetadata bool
	JPEGQuality     int
	PNGCompression  png.CompressionLevel
	GIFNumColors    int
}

SaveConfig holds configuration for saving images

type SaveOption added in v1.0.0

type SaveOption func(*SaveConfig)

SaveOption configures image saving

func WithGIFNumColors added in v1.0.0

func WithGIFNumColors(numColors int) SaveOption

WithGIFNumColors sets the number of colors for GIF encoding

func WithJPEGQuality added in v1.0.0

func WithJPEGQuality(quality int) SaveOption

WithJPEGQuality sets the JPEG quality (1-100)

func WithPNGCompression added in v1.0.0

func WithPNGCompression(level png.CompressionLevel) SaveOption

WithPNGCompression sets the PNG compression level

func WithoutMetadata added in v1.0.0

func WithoutMetadata() SaveOption

WithoutMetadata disables metadata writing for this save operation

type WatermarkOptions

type WatermarkOptions struct {
	// Text is the watermark text to be rendered on the image.
	Text string

	// Position specifies where to place the watermark (e.g., BottomRight, TopLeft).
	// Default is BottomRight.
	Position Anchor

	// Opacity controls the transparency of the watermark text (0.0 to 1.0).
	// 0.0 is fully transparent, 1.0 is fully opaque.
	// Default is 0.5 (50% opacity).
	Opacity float64

	// TextColor is the color of the watermark text.
	// Default is white (255, 255, 255).
	TextColor color.Color

	// Font is the font face to use for rendering the text.
	// If nil, basicfont.Face7x13 is used as default.
	Font font.Face

	// Padding is the number of pixels to offset from the edge based on Position.
	// Default is 10 pixels.
	Padding int
}

WatermarkOptions contains options for adding a text watermark to an image.

Directories

Path Synopsis
cmd
imgx command
examples
author command
detection command
generator command
metadata command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL