ADR-001: Image Scaling Behavior
- Status
-
Accepted
- Date
-
2025-10-27
- Authors
-
Development Team
- Context
-
RTE CKEditor Image Extension for TYPO3
Table of Contents
Context and Problem Statement
The RTE CKEditor Image extension needs to provide flexible image processing options that balance quality, performance, and file size. Users need clear control over when images should be processed versus when original files should be used directly.
The system must handle various scenarios:
- Different display quality requirements (web, retina displays, print)
- Performance optimization (avoid unnecessary processing)
- File size considerations (prevent serving oversized originals)
- SVG handling (vector graphics don't need raster processing)
Decision Drivers
- User Control: Clear options for when to process vs use originals
- Performance: Avoid unnecessary image processing operations
- Quality: Provide appropriate quality for different use cases
- File Size: Prevent serving excessively large files to browsers
- Browser Compatibility: Ensure proper rendering across devices
Considered Options
Option 1: Always Process Images
- Pros: Consistent behavior, predictable output
- Cons: Unnecessary processing, performance overhead, potential quality loss
Option 2: Never Process Images (Always Use Originals)
- Pros: Maximum quality, no processing overhead
- Cons: Large file sizes, no optimization for different displays
Option 3: Intelligent Conditional Processing (Selected)
- Pros: Balances quality, performance, and file size
- Cons: More complex logic, requires configuration
Decision Outcome
Chosen option: Option 3 - Intelligent Conditional Processing
The system implements a multi-tier approach with explicit user control and automatic optimization.
Image Processing Modes
1. No Scaling (Skip Processing Entirely)
Behavior: Use original file without any TYPO3 image processing
When to Use:
- Newsletters (external email clients)
- PDF generation
- When maximum quality is required
- When original file optimization is already optimal
Backend Attribute: data-noscale="1"
Example Scenario:
Original Image: 1920×1080 px (500 KB)
Display Size: 1920×1080 px
Processing: NONE - original file used directly
Output URL: /fileadmin/user_upload/image.jpg
Result: Exact original file served (500 KB)
Processing Info Message (Gray):
Processing Info: Image 1920×1080 px will be displayed at 1920×1080 px = ● Standard Quality (1.0x scaling)
2. Low Quality (0.9x Multiplier)
Behavior: Process with reduced quality for smaller file sizes
When to Use:
- Thumbnail images
- Background images where quality is less critical
- Bandwidth-constrained scenarios
Example Scenario:
Original Image: 1920×1080 px
Display Size: 800×450 px
Multiplier: 0.9x
Calculation: 800×450 × 0.9 = 720×405 px
Processing: YES - image scaled and compressed
Output URL: /typo3temp/assets/processed/image_[hash].jpg
Result: Processed file at 720×405 px
Processing Info Message (Red):
Processing Info: Image 1920×1080 px will be resized to 720×405 px and displayed at 800×450 px = ● Low Quality (0.9x scaling)
3. Standard Quality (1.0x Multiplier)
Behavior: Process with exact display dimensions
When to Use:
- General content images
- Standard web displays (non-retina)
- Balanced quality and file size
Example Scenario:
Original Image: 1920×1080 px
Display Size: 800×450 px
Multiplier: 1.0x
Calculation: 800×450 × 1.0 = 800×450 px
Processing: YES - image scaled to exact display size
Output URL: /typo3temp/assets/processed/image_[hash].jpg
Result: Processed file at 800×450 px
Processing Info Message (Orange):
Processing Info: Image 1920×1080 px will be resized to 800×450 px and displayed at 800×450 px = ● Standard Quality (1.0x scaling)
4. Retina Quality (2.0x Multiplier)
Behavior: Process with 2x display dimensions for high-DPI screens
When to Use:
- Retina/HiDPI displays (MacBook, iPhone, modern monitors)
- High-quality content imagery
- Professional photography portfolios
Example Scenario:
Original Image: 1920×1500 px
Display Size: 960×750 px
Multiplier: 2.0x
Calculation: 960×750 × 2.0 = 1920×1500 px
Processing: YES - image scaled for retina displays
Output URL: /typo3temp/assets/processed/image_[hash].jpg
Result: Processed file at 1920×1500 px
Processing Info Message (Green):
Processing Info: Image 1920×1500 px will be resized to 1920×1500 px and displayed at 960×750 px = ● Retina Quality (2.0x scaling)
5. Ultra Quality (3.0x Multiplier)
Behavior: Process with 3x display dimensions for ultra-high-DPI
When to Use:
- 4K/5K displays
- Professional design work
- Maximum quality requirements
Example Scenario:
Original Image: 5760×3240 px
Display Size: 640×360 px
Multiplier: 3.0x
Calculation: 640×360 × 3.0 = 1920×1080 px
Processing: YES - image scaled for ultra displays
Output URL: /typo3temp/assets/processed/image_[hash].jpg
Result: Processed file at 1920×1080 px
Processing Info Message (Cyan):
Processing Info: Image 5760×3240 px will be resized to 1920×1080 px and displayed at 640×360 px = ● Ultra Quality (3.0x scaling)
6. Print Quality (6.0x Multiplier)
Behavior: Process with 6x display dimensions for print output
When to Use:
- Print-ready materials
- High-resolution documents
- Maximum quality print output
Example Scenario:
Original Image: 5760×3240 px
Display Size: 320×180 px
Multiplier: 6.0x
Calculation: 320×180 × 6.0 = 1920×1080 px
Processing: YES - image scaled for print quality
Output URL: /typo3temp/assets/processed/image_[hash].jpg
Result: Processed file at 1920×1080 px
Processing Info Message (Blue):
Processing Info: Image 5760×3240 px will be resized to 1920×1080 px and displayed at 320×180 px = ● Print Quality (6.0x scaling)
Quality Calculation Logic
Achievable Quality
The system automatically determines what quality can actually be achieved based on the original image dimensions:
Quality Formula: actualQuality = min(imageWidth / displayWidth, imageHeight / displayHeight)
Examples:
- Image 1920×1500, Display 960×750 → Quality = min(1920/960, 1500/750) = min(2.0, 2.0) = 2.0x (Retina)
- Image 1920×1500, Display 192×150 → Quality = min(1920/192, 1500/150) = min(10.0, 10.0) = 10.0x (Print)
- Image 1920×1500, Display 1920×1500 → Quality = min(1920/1920, 1500/1500) = min(1.0, 1.0) = 1.0x (Standard)
- Image 1920×1500, Display 2840×3000 → Quality = min(1920/2840, 1500/3000) = min(0.68, 0.5) = 0.5x (Poor)
Processing Multipliers vs Achievable Quality
When a processing option (Standard, Retina, Ultra, Print) is selected:
- Requested Size = Display × Multiplier
- Processed Size = min(Requested Size, Original Size) — Never upscale!
- Actual Quality = Processed Size / Display Size
Example: Image 1920×1500, Display 1920×1500, Retina (2.0x)
- Requested: 1920×1500 × 2.0 = 3840×3000
- Processed: min(3840×3000, 1920×1500) = 1920×1500
- Actual Quality: 1920/1920 = 1.0x (Standard, not Retina!)
Automatic Optimization Rules
Rule 1: SVG Files (Always Skip Processing)
Behavior: SVG files are NEVER processed regardless of settings
Rationale:
- SVG is vector format that scales perfectly at any resolution
- ImageMagick would rasterize SVG, losing vector benefits
- Browser handles SVG scaling natively
Example:
File: logo.svg (vector)
Display Size: 400×300 px
Setting: ANY (ignored for SVG)
Processing: NONE - original SVG used
Result: Browser scales SVG natively
Processing Info Message (Gray):
Processing Info: Vector image will not be processed (scales perfectly at any resolution).
Rule 2: Dimensions Match Exactly (Skip Processing)
Behavior: When display dimensions exactly match original, skip processing
Rationale:
- No resize needed = no quality benefit from processing
- Avoid unnecessary processing overhead
- Preserve original file quality
Example:
Original Image: 1920×1080 px
Display Size: 1920×1080 px
Setting: Standard (1.0x)
Processing: NONE - dimensions match exactly
Result: Original file used
Processing Info Message (varies by scaling option):
No Scaling: Image 1920×1080 px will be displayed at 1920×1080 px = ● Standard Quality (1.0x scaling)
Standard (1.0x): Image 1920×1080 px will be displayed at 1920×1080 px = ● Standard Quality (1.0x scaling)
Retina (2.0x): Image 1920×1080 px will be displayed at 1920×1080 px = ● Standard Quality (1.0x scaling) [cannot achieve 2.0x]
Note: When requested quality cannot be achieved (original image too small), the message shows the actual achievable quality.
Note: This rule is overridden by file size threshold (see Rule 4).
Rule 3: Display Exceeds Image Size (Skip Processing + Warning)
Behavior: When display size is larger than original image, skip processing and warn
Rationale:
- Upscaling degrades quality
- Better to use original at natural size
- User should be aware of quality limitation
Example:
Original Image: 800×600 px (small original)
Display Size: 1920×1080 px (larger than original)
Setting: Retina (2.0x)
Processing: NONE - cannot upscale quality
Result: Original 800×600 px used, stretched by browser
Warning: Quality degradation expected
Processing Info Message (Red warning):
Processing Info: Image 800×600 px will be displayed at 1920×1080 px = ● Poor Quality (0.4x scaling)
Rule 4: File Size Threshold (Force Processing)
Behavior: Large files are processed even when dimensions match
Configuration:
lib.parseFunc_RTE.tags.img {
noScale = 1
noScale {
maxFileSizeForAuto = 2000000 # 2MB threshold
}
}
Rationale:
- Prevent serving multi-megabyte originals
- Optimize file size through compression
- Balance quality and bandwidth
Example:
Original Image: 1920×1080 px (5 MB uncompressed TIFF)
Display Size: 1920×1080 px (exact match)
File Size: 5,242,880 bytes (> 2MB threshold)
Processing: YES - exceeds size threshold
Result: Processed JPEG at 1920×1080 px (~500 KB)
Frontend Rendering (ImageRenderingController)
Processing Decision Logic
protected function shouldSkipProcessing(
File $originalFile,
array $imageConfiguration,
bool $noScale,
int $maxFileSizeForAuto = 0
): bool {
// RULE 1: SVG files - always skip
if (strtolower($originalFile->getExtension()) === 'svg') {
return true;
}
// RULE 2: Explicit noScale setting OR data-noscale attribute
if ($noScale) {
return true;
}
// Get dimensions
$originalWidth = (int) ($originalFile->getProperty('width') ?? 0);
$originalHeight = (int) ($originalFile->getProperty('height') ?? 0);
$requestedWidth = (int) ($imageConfiguration['width'] ?? 0);
$requestedHeight = (int) ($imageConfiguration['height'] ?? 0);
// RULE 3: No dimensions requested - use original
if ($requestedWidth === 0 && $requestedHeight === 0) {
return true;
}
// RULE 4: Dimensions match exactly
if ($requestedWidth === $originalWidth && $requestedHeight === $originalHeight) {
// Check file size threshold
if ($maxFileSizeForAuto > 0) {
$fileSize = $originalFile->getSize();
// Exceeds threshold - process to reduce size
if ($fileSize > $maxFileSizeForAuto) {
return false;
}
}
// Within threshold or no limit - skip processing
return true;
}
// Different dimensions - processing needed
return false;
}
Configuration Examples
Global No Processing (All RTE Images)
# TypoScript Setup
lib.parseFunc_RTE.tags.img.noScale = 1
Result: ALL images use originals, no processing
Selective No Processing (Per Image)
Users set "No Scaling" option in image dialog.
Result: Only images with data-noscale="1" skip processing
File Size Optimized
lib.parseFunc_RTE.tags.img {
noScale = 0 # Enable processing
noScale {
maxFileSizeForAuto = 2000000 # 2MB
}
}
Result: Images processed only when needed, automatic optimization for large files
User Interface Indicators
Color Coding
| Quality | Color | Hex | Usage |
|---|---|---|---|
| No Scaling | Gray | #6c757d | No processing |
| Low | Red | #dc3545 | Reduced quality |
| Standard | Orange | #ffc107 | Balanced |
| Retina | Green | #28a745 | High quality |
| Ultra | Cyan | #17a2b8 | Ultra quality |
| Blue | #007bff | Print quality |
Processing Info States
- No Processing (Gray) - Original file used
- Normal Processing (Blue) - Standard resize operation
- Exact Match (Green) - No processing needed, dimensions match
- Oversized Display (Red) - Warning about quality limitation
Technical Implications
Backend (SelectImageController)
- Validation: Enforce dimension limits (1-10000px) to prevent resource exhaustion
- Security: Verify file access permissions (IDOR protection)
- Performance: Use efficient file property access
Frontend (ImageRenderingController)
- Caching: Processed images cached in
typo3temp/assets/ - Security: Block non-public files from frontend rendering
- Performance: Skip processing when possible to reduce server load
JavaScript (typo3image.js)
- Real-time Calculation: Show expected output dimensions
- Visual Feedback: Color-coded quality indicators
- Validation: Prevent invalid dimension combinations
Consequences
Positive
- Flexibility: Users control when processing occurs
- Performance: Automatic optimization reduces unnecessary operations
- Quality: Appropriate processing for different use cases
- File Size: Prevents serving oversized originals
Negative
- Complexity: More logic to maintain and test
- Learning Curve: Users need to understand when to use each option
- Edge Cases: Requires careful handling of dimension mismatches
Compliance
- TYPO3 Standards: Follows FAL (File Abstraction Layer) patterns
- Security: Implements access control and resource limits
- Performance: Optimizes for typical web usage patterns
References
Revision History
| Date | Version | Changes |
|---|---|---|
| 2025-10-27 | 1.0 | Initial ADR documenting scaling behavior |