SquareImages for ProcessWire
Version: 1.2
Author: Maxim Alex
Website: smnv.org
Email: maxim@smnv.org
Release Date: December 27, 2025
License: MIT
A ProcessWire module that creates perfect square images from any source format. Born from the real-world need to display vertical product images (like Coca-Cola bottles) uniformly in galleries and grids.
The Story: From Pain to Solution
The Problem
Imagine you're building an e-commerce site selling beverages. You have product photos:
Coca-Cola Bottle (JPG): 500 × 1500px (vertical)
Coca-Cola Bottle (PNG): 600 × 1800px (vertical)
Coca-Cola Bottle (GIF): 450 × 1350px (vertical)Your product grid needs uniform squares for a clean layout:
┌──────────┐ ┌──────────┐ ┌──────────┐
│ │ │ │ │ │
│ BOTTLE │ │ BOTTLE │ │ BOTTLE │
│ │ │ │ │ │
└──────────┘ └──────────┘ └──────────┘
300×300 300×300 300×300But if you just resize:
❌ Option 1: width(300)
┌───┐ ┌───┐ ┌───┐
│ | │ │ | │ │ | │ ← Too narrow!
│ | │ │ | │ │ | │
│ | │ │ | │ │ | │
│ | │ │ | │ │ | │
└───┘ └───┘ └───┘
100×300 100×300 100×300
❌ Option 2: height(300)
┌──────┐
│BOTTLE│ ← Too wide!
└──────┘
900×300
❌ Option 3: size(300, 300)
┌──────────┐
│ BOTTLE │ ← Distorted!
└──────────┘
300×300 (stretched)None of these work! You need smart cropping that:
- Finds the shorter dimension
- Centers the crop on the longer dimension
- Creates a perfect square
- Preserves aspect ratio
- Maintains quality
The Solution: SquareImages
// Simple, elegant, perfect
$square = $image->square(300);Result:
✅ Perfect squares, centered crop, no distortion
┌──────────┐ ┌──────────┐ ┌──────────┐
│ │ │ │ │ │
│ BOTTLE │ │ BOTTLE │ │ BOTTLE │
│ │ │ │ │ │
└──────────┘ └──────────┘ └──────────┘
300×300 300×300 300×300This module was born from this exact use case - transforming vertical Coca-Cola bottle photos into uniform squares for a product gallery. Now it's battle-tested and ready for your projects.
✨ Features
- Perfect Squares: Always creates exactly square images
- Smart Cropping: Automatically centers crop on longer dimension
- Format Preservation: Maintains original format (JPG→JPG, PNG→PNG, GIF→GIF)
- WebP Support: Chain with
->webp()for optimal compression - ⚡ Performance: Fast URL generation without filesystem lookups
- Quality: Uses ProcessWire's native image engine
- Caching: Automatic caching of generated images
- Multiple Methods:
square(),squareWidth(),squareHeight(),getSquareURL()
Installation
Method 1: ProcessWire Modules Directory
- Download the module
- Place in
/site/modules/SquareImages/ - Install via Modules → Refresh → Install
Method 2: Manual
- Download ZIP
- Extract to
/site/modules/SquareImages/ - Refresh modules in admin
- Install
Quick Start
Basic Usage
// Get any image
$image = $page->images->first();
// Create 500×500 square
$square = $image->square(500);
// Use it
echo "<img src='{$square->url}' alt='Product'>";Real-World Example: Product Gallery
<div><?php foreach ($page->products as $product): ?><?php $thumb = $product->photo->square(300); ?><div> <img src="<?= $thumb->url ?>" alt="<?= $product->title ?>"> <h3><?= $product->title ?></h3> <p>$<?= $product->price ?></p> </div><?php endforeach; ?></div>
CSS:
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
.product-card img {
width: 100%;
height: auto;
}Result: Perfect grid of uniform squares, regardless of original image dimensions!
API Documentation
Methods
square($size)
Creates a square image of specified size.
$square = $image->square(400);
// Returns: Pageimage object (400×400)squareWidth($width)
Creates a square based on width dimension.
$square = $image->squareWidth(500);
// Returns: Pageimage object (500×500)squareHeight($height)
Creates a square based on height dimension.
$square = $image->squareHeight(600);
// Returns: Pageimage object (600×600)getSquareURL($size)
Returns URL string directly (faster for rendering).
$url = $image->getSquareURL(300);
// Returns: String URL
echo "<img src='{$url}'>";WebP Conversion
Chain with ->webp() for modern format:
$webp = $image->square(500)->webp();
// Returns: 500×500 WebP image (25-65% smaller!)Use with <picture> for fallback:
<?php $square = $image->square(500); $webp = $square->webp(); ?><picture> <source srcset="<?= $webp->url ?>" type="image/webp"> <img src="<?= $square->url ?>" alt="Product"> </picture>
Use Cases
1. Product Galleries
Uniform product images from mixed aspect ratios:
foreach ($products as $product) {
$thumb = $product->image->square(250);
echo "<img src='{$thumb->url}'>";
}2. Team Photos
Perfect avatars from portrait photos:
$avatar = $page->photo->square(150);
echo "<img src='{$avatar->url}'>";3. Blog Post Thumbnails
Consistent thumbnails from various image sizes:
$thumb = $post->featured_image->square(400);4. Social Media Previews
Generate square OG images:
$og = $page->hero->square(1200);
echo "<meta property='og:image' content='{$og->url}'>";5. Responsive Galleries
Multiple sizes for responsive design:
$small = $image->square(300);
$medium = $image->square(600);
$large = $image->square(1200);<img srcset="<?= $small->url ?>300w,<?= $medium->url ?>600w,<?= $large->url ?>1200w " sizes="(max-width: 600px) 300px, (max-width: 1200px) 600px, 1200px" src="<?= $medium->url ?>" >
Advanced Examples
E-commerce Product Catalog
<div><?php foreach ($page->children('template=product') as $product): ?><?php $thumb = $product->images->first()->square(350); $webp = $thumb->webp(); ?><article> <picture> <source srcset="<?= $webp->url ?>" type="image/webp"> <img src="<?= $thumb->url ?>" alt="<?= $product->title ?>"> </picture> <h2><?= $product->title ?></h2> <p>$<?= $product->price ?></p> <a href="<?= $product->url ?>">View Details</a> </article><?php endforeach; ?></div>
Instagram-Style Grid
<div><?php foreach ($page->gallery as $photo): ?><div> <a href="<?= $photo->url ?>"> <img src="<?= $photo->square(300)->url ?>" loading="lazy"> </a> </div><?php endforeach; ?></div> <style> .instagram-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; } .grid-item { aspect-ratio: 1; overflow: hidden; } .grid-item img { width: 100%; height: 100%; object-fit: cover; } </style>
Multi-Size Thumbnails
<?php
$sizes = [
'thumbnail' => 150,
'small' => 300,
'medium' => 600,
'large' => 1200
];
$variants = [];
foreach ($sizes as $name => $size) {
$variants[$name] = $image->square($size);
}
?>
<!-- Use variants -->
<img src="<?= $variants['thumbnail']->url ?>">
<img src="<?= $variants['medium']->url ?>">⚡ Performance Tips
1. Use getSquareURL() for Simple Rendering
// Faster (returns string)
$url = $image->getSquareURL(300);
// Slower (returns object)
$square = $image->square(300);
$url = $square->url;2. Cache in Variables
// Good
$square = $image->square(500);
echo $square->url;
echo $square->width;
echo $square->height;
// Bad (creates square 3 times!)
echo $image->square(500)->url;
echo $image->square(500)->width;
echo $image->square(500)->height;3. Use WebP for Modern Browsers
// 25-65% smaller file sizes!
$webp = $image->square(500)->webp();4. Lazy Load Images
<img src="<?= $thumb->url ?>" loading="lazy">
Testing
The module includes comprehensive test files:
Test Suite: test-squareimages.php
- Tests all image formats (JPG, PNG, GIF)
- Verifies 6 different sizes (100-1000px)
- Tests all 4 methods
- WebP conversion testing
- Automated pass/fail validation
Place in your template:
<?php include('./test-squareimages.php'); ?>Troubleshooting
Images Not Square
Problem: Images are distorted or not square.
Solution: Check that source image exists and has valid dimensions.
WebP Not Working
Problem: ->webp() returns original format.
Solution: Ensure GD or ImageMagick supports WebP on your server.
Cache Issues
Problem: Changes not appearing.
Solution: Clear ProcessWire image cache or use different size.
Memory Errors
Problem: Out of memory errors.
Solution: Reduce image size or increase PHP memory_limit.
Version History
v1.2 (December 27, 2025)
- Added comprehensive test suite
- WebP conversion support
- Format badges in tests
- All-images processing in tests
- Performance optimizations
- Full documentation
v1.1 (2025)
- Added
getSquareURL()method - Performance improvements
- Bug fixes
v1.0 (2025)
- Initial release
- Basic square() functionality
Contributing
Contributions welcome! Please:
- Fork the repository
- Create feature branch
- Commit changes
- Push to branch
- Open Pull Request
License
MIT License
Copyright (c) 2025 Maxim Alex (smnv.org)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Support
- Email: maxim@smnv.org
- Website: smnv.org
Credits
Created to solve a real problem: displaying vertical Coca-Cola bottle photos uniformly in product grids.
Test images (Coca-Cola bottles) used for demonstration purposes only. Coca-Cola® is a registered trademark of The Coca-Cola Company. Not affiliated.
Made with ❤️ by Maxim Alex
Transform any image into a perfect square. Simple, elegant, powerful.
More modules by Maxim Semenov
LQRS URL Shortener Profile for ProcessWire 3x
This site profile for ProcessWire offers a free and easy-to-use URL shortener that transforms long links into concise, shareable URLs. It is built using standard ProcessWire modules and field types.3Added 12 months ago by Maxim SemenovMedia Platform Profile for ProcessWire
This site profile for ProcessWire offers a fully-featured media platform for hosting and managing video content with Backblaze B2 and Cloudflare integration.3Added 1 month ago by Maxim SemenovWireNPS - Net Promoter Score
Collect NPS ratings and feedback with a clean popup interface, comprehensive analytics, and easy integration1Added 1 month ago by Maxim Semenov- Added 1 week ago by Maxim Semenov
Install and use modules at your own risk. Always have a site and database backup before installing new modules.