Merge pull request #4229 from jonom/max-image-methods
Max image methods & Force resampling changes
@ -512,7 +512,7 @@ The staff section templates aren't too difficult to create, thanks to the utilit
|
|||||||
<% loop $Children %>
|
<% loop $Children %>
|
||||||
<article>
|
<article>
|
||||||
<h2><a href="$Link" title="Read more on "{$Title}"">$Title</a></h2>
|
<h2><a href="$Link" title="Read more on "{$Title}"">$Title</a></h2>
|
||||||
$Photo.SetWidth(150)
|
$Photo.ScaleWidth(150)
|
||||||
<p>$Content.FirstParagraph</p>
|
<p>$Content.FirstParagraph</p>
|
||||||
<a href="$Link" title="Read more on "{$Title}"">Read more >></a>
|
<a href="$Link" title="Read more on "{$Title}"">Read more >></a>
|
||||||
</article>
|
</article>
|
||||||
@ -521,7 +521,7 @@ The staff section templates aren't too difficult to create, thanks to the utilit
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
This template is very similar to the *ArticleHolder* template. The *SetWidth* method of the `[api:Image]` class
|
This template is very similar to the *ArticleHolder* template. The *ScaleWidth* method of the `[api:Image]` class
|
||||||
will resize the image before sending it to the browser. The resized image is cached, so the server doesn't have to
|
will resize the image before sending it to the browser. The resized image is cached, so the server doesn't have to
|
||||||
resize the image every time the page is viewed.
|
resize the image every time the page is viewed.
|
||||||
|
|
||||||
@ -537,13 +537,13 @@ The *StaffPage* template is also very straight forward.
|
|||||||
<article>
|
<article>
|
||||||
<h1>$Title</h1>
|
<h1>$Title</h1>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
$Photo.SetWidth(433)
|
$Photo.ScaleWidth(433)
|
||||||
$Content</div>
|
$Content</div>
|
||||||
</article>
|
</article>
|
||||||
$Form
|
$Form
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Here we use the *SetWidth* method to get a different sized image from the same source image. You should now have
|
Here we use the *ScaleWidth* method to get a different sized image from the same source image. You should now have
|
||||||
a complete staff section.
|
a complete staff section.
|
||||||
|
|
||||||
![](../_images/tutorial2_einstein.jpg)
|
![](../_images/tutorial2_einstein.jpg)
|
||||||
|
40
docs/en/02_Developer_Guides/14_Files/01_File_Management.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
summary: Learn how to work with File and Image records
|
||||||
|
|
||||||
|
# File Management
|
||||||
|
|
||||||
|
## Files, Images and Folders as database records
|
||||||
|
|
||||||
|
All files, images and folders in the 'assets' directory are stored in the database. Each record has the following database fields:
|
||||||
|
|
||||||
|
| Field name | Description |
|
||||||
|
| ---------- | ----------- |
|
||||||
|
| `ClassName` | The class name of the file (e.g. File, Image or Folder). |
|
||||||
|
| `Name` | The 'basename' of the file, or the folder name. For example 'my-image.jpg', or 'images' for a folder. |
|
||||||
|
| `Title` | The optional, human-readable title of the file for display only (doesn't apply to folders). |
|
||||||
|
| `Filename` | The path to the file/folder, relative to the webroot. For example 'assets/images/my-image.jpg', or 'assets/images/' for a folder. |
|
||||||
|
| `Content` | Typically unused, but handy for a textual representation of files. For example for fulltext indexing of PDF documents. |
|
||||||
|
| `ShowInSearch` | Whether the file should be shown in search results, defaults to '1'. See ["Tutorial 4 - Site Search"](/tutorials/site_search) for enabling search. |
|
||||||
|
| `ParentID` | The ID of the parent Folder that this File/Folder is in. A ParentID of '0' indicates that the File/Folder is in the 'assets' directory. |
|
||||||
|
| `OwnerID` | The ID of the Member that 'owns' the File/Folder (not related to filesystem permissions). |
|
||||||
|
|
||||||
|
## Management through the "Files" section of the CMS
|
||||||
|
|
||||||
|
If you have the CMS module installed, you can manage files, folders and images in the "Files" section of the CMS. Inside this section, you will see a list of files and folders like below:
|
||||||
|
|
||||||
|
![](../../_images/assets.png)
|
||||||
|
|
||||||
|
You can click on any file to edit it, or click on any folder to open it. To delete a file or a folder, simply click the red 'X' symbol next to it. If you click to open a folder, you can go back up one level by clicking the 'up' arrow above the folder name (highlighted below):
|
||||||
|
|
||||||
|
![](../../_images/assets_up.png)
|
||||||
|
|
||||||
|
Once you click to edit a file, you will see a form similar to the one below, in which you can edit the file's title, filename, owner, or even change which folder the file is located in:
|
||||||
|
|
||||||
|
![](../../_images/assets_editform.png)
|
||||||
|
|
||||||
|
You may also notice the 'Sync files' button (highlighted below). This button allows CMS users to 'synchronise' the database (remember, all files/folders are stored as database records) with the filesystem. This is particularly useful if someone has uploaded or removed files/folders via FTP, for example.
|
||||||
|
|
||||||
|
![](../../_images/assets_sync.png)
|
||||||
|
|
||||||
|
## Upload
|
||||||
|
|
||||||
|
Files can be managed through a `FileField` or an `UploadField`. The `[api:FileField]` class provides a simple HTML input with a type of "file", whereas an `[api:UploadField]` provides a much more feature-rich field (including AJAX-based uploads, previews, relationship management and file data management). See [`Reference - UploadField`](/developer_guides/forms/field_types/uploadfield) for more information about how to use the `UploadField` class.
|
@ -1,135 +0,0 @@
|
|||||||
# Image
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
Represents an image object through the `[api:Image]` class, inheriting all base functionality from the `[api:File]` class with extra functionality including resizing.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Managing images through form fields
|
|
||||||
|
|
||||||
Images can be uploaded like any other file, through `[api:FileField]`.
|
|
||||||
More advanced usage is possible through `[api:UploadField]`,
|
|
||||||
which provides thumbnails, a detail view of the image properties,
|
|
||||||
and management of relationships to other DataObject instances.
|
|
||||||
Allows upload of images through limiting file extensions with `setAllowedExtensions()`.
|
|
||||||
|
|
||||||
### Inserting images into the WYSIWYG editor
|
|
||||||
|
|
||||||
See [Topics: Rich Text Editing](/topics/rich-text-editing).
|
|
||||||
|
|
||||||
### Resizing Images in PHP
|
|
||||||
|
|
||||||
The following are methods defined on the GD class which you can call on Image Objects. Note to get the following to work
|
|
||||||
you need to have GD2 support in your PHP installation and because these generate files you must have write access to
|
|
||||||
your tmp folder.
|
|
||||||
|
|
||||||
:::php
|
|
||||||
// manipulation functions
|
|
||||||
$image->resize(width,height); // Basic resize, just skews the image
|
|
||||||
$image->resizeRatio(width,height) // Resizes an image with max width and height
|
|
||||||
$image->paddedResize(width,height) // Adds padding after resizing to width or height.
|
|
||||||
$image->croppedImage(width,height) // Crops the image from the centre, to given values.
|
|
||||||
$image->resizeByHeight(height) // Maximum height the image resizes to, keeps proportion
|
|
||||||
$image->resizeByWidth(width) // Maximum width the image resizes to, keeps proportion
|
|
||||||
$image->greyscale(r,g,b) // alters image channels ===
|
|
||||||
|
|
||||||
// values
|
|
||||||
$image->getHeight() // Returns the height of the image.
|
|
||||||
$image->getWidth() // Returns the width of the image
|
|
||||||
$image->getOrienation() // Returns a class constant: ORIENTATION_SQUARE or ORIENTATION_PORTRAIT or ORIENTATION_LANDSCAPE
|
|
||||||
|
|
||||||
|
|
||||||
You can also create your own functions by extending the image class, for example
|
|
||||||
|
|
||||||
:::php
|
|
||||||
class MyImage extends Image {
|
|
||||||
public function generateRotateClockwise(GD $gd) {
|
|
||||||
return $gd->rotate(90);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generateRotateCounterClockwise(GD $gd) {
|
|
||||||
return $gd->rotate(270);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function clearResampledImages() {
|
|
||||||
$files = glob(Director::baseFolder().'/'.$this->Parent()->Filename."_resampled/*-$this->Name");
|
|
||||||
foreach($files as $file) {unlink($file);}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Landscape() {
|
|
||||||
return $this->getWidth() > $this->getHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Portrait() {
|
|
||||||
return $this->getWidth() < $this->getHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generatePaddedImageByWidth(GD $gd,$width=600,$color="fff"){
|
|
||||||
return $gd->paddedResize($width, round($gd->getHeight()/($gd->getWidth()/$width),0),$color);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Exif(){
|
|
||||||
//http://www.v-nessa.net/2010/08/02/using-php-to-extract-image-exif-data
|
|
||||||
$image = $this->AbsoluteURL;
|
|
||||||
$d=new ArrayList();
|
|
||||||
$exif = exif_read_data($image, 0, true);
|
|
||||||
foreach ($exif as $key => $section) {
|
|
||||||
$a=new ArrayList();
|
|
||||||
foreach ($section as $name => $val)
|
|
||||||
$a->push(new ArrayData(array("Title"=>$name,"Content"=>$val)));
|
|
||||||
$d->push(new ArrayData(array("Title"=>strtolower($key),"Content"=>$a)));
|
|
||||||
}
|
|
||||||
return $d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
### Resizing in Templates
|
|
||||||
|
|
||||||
You can call certain resize functions directly from the template, to use the inbuilt GD functions as the template parser
|
|
||||||
supports these, for example SetWidth() or SetHeight().
|
|
||||||
|
|
||||||
For output of an image tag with the image automatically resized to 80px width, you can use:
|
|
||||||
|
|
||||||
:::php
|
|
||||||
$Image.SetWidth(80) // returns a image 80px wide, ratio kept the same
|
|
||||||
$Image.SetHeight(80) // returns a image 80px tall, ratio kept the same
|
|
||||||
$Image.SetSize(80,80) // returns a 80x80px padded image
|
|
||||||
$Image.SetRatioSize(80,80) // Returns an image scaled proportional, with its greatest diameter scaled to 80px
|
|
||||||
$Image.CroppedImage(80,80) // Returns an 80x80 image cropped from the center.
|
|
||||||
$Image.PaddedImage(80, 80, FFFFFF) // Returns an 80x80 image. Unused space is padded white. No crop. No stretching
|
|
||||||
$Image.Width // returns width of image
|
|
||||||
$Image.Height // returns height of image
|
|
||||||
$Image.Orientation // returns Orientation
|
|
||||||
$Image.Filename // returns filename
|
|
||||||
$Image.URL // returns filename
|
|
||||||
|
|
||||||
|
|
||||||
### Form Upload
|
|
||||||
|
|
||||||
For usage on a website form, see `[api:FileField]`.
|
|
||||||
If you want to upload images within the CMS, see `[api:UploadField]`.
|
|
||||||
|
|
||||||
### Image Quality
|
|
||||||
|
|
||||||
To adjust the quality of the generated images when they are resized add the following to your mysite/config/config.yml file:
|
|
||||||
|
|
||||||
:::yml
|
|
||||||
GDBackend:
|
|
||||||
default_quality: 90
|
|
||||||
|
|
||||||
The default value is 75.
|
|
||||||
|
|
||||||
### Clearing Thumbnail Cache
|
|
||||||
|
|
||||||
Images are (like all other Files) synchronized with the SilverStripe database.
|
|
||||||
This syncing happens whenever you load the "Files & Images" interface,
|
|
||||||
and whenever you upload or modify an Image through SilverStripe.
|
|
||||||
|
|
||||||
If you encounter problems with images not appearing, or have mysteriously disappeared, you can try manually flushing the
|
|
||||||
image cache.
|
|
||||||
|
|
||||||
http://localhost/dev/tasks/FlushGeneratedImagesTask
|
|
||||||
|
|
||||||
## API Documentation
|
|
||||||
`[api:Image]`
|
|
163
docs/en/02_Developer_Guides/14_Files/02_Images.md
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
summary: Learn how to crop and resize images in templates and PHP code
|
||||||
|
|
||||||
|
# Image
|
||||||
|
|
||||||
|
Represents an image object through the `[api:Image]` class, inheriting all base functionality from the `[api:File]` class with extra functionality including resizing.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Managing images through form fields
|
||||||
|
|
||||||
|
Images can be uploaded like any other file, through `[api:FileField]`.
|
||||||
|
More advanced usage is possible through `[api:UploadField]`,
|
||||||
|
which provides thumbnails, a detail view of the image properties,
|
||||||
|
and management of relationships to other DataObject instances.
|
||||||
|
Allows upload of images through limiting file extensions with `setAllowedExtensions()`.
|
||||||
|
|
||||||
|
### Inserting images into the WYSIWYG editor
|
||||||
|
|
||||||
|
See [Topics: Rich Text Editing](/topics/rich-text-editing).
|
||||||
|
|
||||||
|
### Manipulating images in Templates
|
||||||
|
|
||||||
|
You can manipulate images directly from templates to create images that are
|
||||||
|
resized and cropped to suit your needs. This doesn't affect the original
|
||||||
|
image or clutter the CMS with any additional files, and any images you create
|
||||||
|
in this way are cached for later use. In most cases the pixel aspect ratios of
|
||||||
|
images are preserved (meaning images are not stretched).
|
||||||
|
|
||||||
|
![](../../_images/image-methods.jpg)
|
||||||
|
|
||||||
|
Here are some examples, assuming the `$Image` object has dimensions of 200x100px:
|
||||||
|
|
||||||
|
:::ss
|
||||||
|
// Scaling functions
|
||||||
|
$Image.ScaleWidth(150) // Returns a 150x75px image
|
||||||
|
$Image.ScaleMaxWidth(100) // Returns a 100x50px image (like ScaleWidth but prevents up-sampling)
|
||||||
|
$Image.ScaleHeight(150) // Returns a 300x150px image (up-sampled. Try to avoid doing this)
|
||||||
|
$Image.ScaleMaxHeight(150) // Returns a 200x100px image (like ScaleHeight but prevents up-sampling)
|
||||||
|
$Image.Fit(300,300) // Returns an image that fits within a 300x300px boundary, resulting in a 300x150px image (up-sampled)
|
||||||
|
$Image.FitMax(300,300) // Returns a 200x100px image (like Fit but prevents up-sampling)
|
||||||
|
|
||||||
|
// Cropping functions
|
||||||
|
$Image.Fill(150,150) // Returns a 150x150px image resized and cropped to fill specified dimensions (up-sampled)
|
||||||
|
$Image.FillMax(150,150) // Returns a 100x100px image (like Fill but prevents up-sampling)
|
||||||
|
$Image.CropWidth(150) // Returns a 150x100px image (trims excess pixels off the x axis from the center)
|
||||||
|
$Image.CropHeight(50) // Returns a 200x50px image (trims excess pixels off the y axis from the center)
|
||||||
|
|
||||||
|
// Padding functions (add space around an image)
|
||||||
|
$Image.Pad(100,100) // Returns a 100x100px padded image, with white bars added at the top and bottom
|
||||||
|
$Image.Pad(100, 100, CCCCCC) // Same as above but with a grey background
|
||||||
|
|
||||||
|
// Metadata
|
||||||
|
$Image.Width // Returns width of image
|
||||||
|
$Image.Height // Returns height of image
|
||||||
|
$Image.Orientation // Returns Orientation
|
||||||
|
$Image.Title // Returns the friendly file name
|
||||||
|
$Image.Name // Returns the actual file name
|
||||||
|
$Image.FileName // Returns the actual file name including directory path from web root
|
||||||
|
$Image.Link // Returns relative URL path to image
|
||||||
|
$Image.AbsoluteLink // Returns absolute URL path to image
|
||||||
|
|
||||||
|
Image methods are chainable. Example:
|
||||||
|
|
||||||
|
:::ss
|
||||||
|
<body style="background-image:url($Image.ScaleWidth(800).CropHeight(800).Link)">
|
||||||
|
|
||||||
|
### Manipulating images in PHP
|
||||||
|
|
||||||
|
The image manipulation functions can be used in your code with the same names, example: `$image->Fill(150,150)`.
|
||||||
|
|
||||||
|
Some of the MetaData functions need to be prefixed with 'get', example `getHeight()`, `getOrientation()` etc.
|
||||||
|
|
||||||
|
Please refer to the `[api:Image]` API documentation for specific functions.
|
||||||
|
|
||||||
|
### Creating custom image functions
|
||||||
|
|
||||||
|
You can also create your own functions by extending the image class, for example
|
||||||
|
|
||||||
|
:::php
|
||||||
|
class MyImage extends DataExtension {
|
||||||
|
|
||||||
|
public function Landscape() {
|
||||||
|
return $this->owner->getWidth() > $this->owner->getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function Portrait() {
|
||||||
|
return $this->owner->getWidth() < $this->owner->getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function PerfectSquare() {
|
||||||
|
return $this->owner->getFormattedImage('PerfectSquare');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generatePerfectSquare(Image_Backend $backend) {
|
||||||
|
return $backend->croppedResize(100,100);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function Exif(){
|
||||||
|
//http://www.v-nessa.net/2010/08/02/using-php-to-extract-image-exif-data
|
||||||
|
$image = $this->owner->AbsoluteLink();
|
||||||
|
$d=new ArrayList();
|
||||||
|
$exif = exif_read_data($image, 0, true);
|
||||||
|
foreach ($exif as $key => $section) {
|
||||||
|
$a=new ArrayList();
|
||||||
|
foreach ($section as $name => $val)
|
||||||
|
$a->push(new ArrayData(array("Title"=>$name,"Content"=>$val)));
|
||||||
|
$d->push(new ArrayData(array("Title"=>strtolower($key),"Content"=>$a)));
|
||||||
|
}
|
||||||
|
return $d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:::yml
|
||||||
|
Image:
|
||||||
|
extensions:
|
||||||
|
- MyImage
|
||||||
|
|
||||||
|
### Form Upload
|
||||||
|
|
||||||
|
For usage on a website form, see `[api:FileField]`.
|
||||||
|
If you want to upload images within the CMS, see `[api:UploadField]`.
|
||||||
|
|
||||||
|
### Image Quality
|
||||||
|
|
||||||
|
To adjust the quality of the generated images when they are resized add the
|
||||||
|
following to your mysite/config/config.yml file:
|
||||||
|
|
||||||
|
:::yml
|
||||||
|
GDBackend:
|
||||||
|
default_quality: 90
|
||||||
|
# or
|
||||||
|
ImagickBackend:
|
||||||
|
default_quality: 90
|
||||||
|
|
||||||
|
The default value is 75.
|
||||||
|
|
||||||
|
By default SilverStripe image functions will not resample an image if no
|
||||||
|
cropping or resizing is taking place. You can tell SilverStripe to always to
|
||||||
|
always produce resampled output by adding this to your
|
||||||
|
mysite/config/config.yml file:
|
||||||
|
|
||||||
|
:::yml
|
||||||
|
Image:
|
||||||
|
force_resample: true
|
||||||
|
|
||||||
|
If you are intending to resample images with SilverStripe it is good practice
|
||||||
|
to upload high quality (minimal compression) images as these will produce
|
||||||
|
better results when resampled. Very high resolution images may cause GD to
|
||||||
|
crash so a good size for website images is around 2000px on the longest edge.
|
||||||
|
|
||||||
|
### Clearing Thumbnail Cache
|
||||||
|
|
||||||
|
Images are (like all other Files) synchronized with the SilverStripe database.
|
||||||
|
This syncing happens whenever you load the "Files & Images" interface,
|
||||||
|
and whenever you upload or modify an Image through SilverStripe.
|
||||||
|
|
||||||
|
If you encounter problems with images not appearing, or have mysteriously
|
||||||
|
disappeared, you can try manually flushing the image cache.
|
||||||
|
|
||||||
|
http://localhost/dev/tasks/FlushGeneratedImagesTask
|
||||||
|
|
||||||
|
## API Documentation
|
||||||
|
`[api:Image]`
|
@ -1,40 +1,11 @@
|
|||||||
summary: Learn how to deal with File and Image records
|
title: Files
|
||||||
|
summary: Upload, manage and manipulate files and images.
|
||||||
|
introduction: Upload, manage and manipulate files and images.
|
||||||
|
|
||||||
# Files, Images and Folders
|
[CHILDREN]
|
||||||
|
|
||||||
## Files, Images and Folders as database records
|
## API Documentation
|
||||||
|
|
||||||
All files, images and folders in the 'assets' directory are stored in the database. Each record has the following database fields:
|
* [api:File]
|
||||||
|
* [api:Image]
|
||||||
| Field name | Description |
|
* [api:Folder]
|
||||||
| ---------- | ----------- |
|
|
||||||
| `ClassName` | The class name of the file (e.g. File, Image or Folder). |
|
|
||||||
| `Name` | The 'basename' of the file, or the folder name. For example 'my-image.jpg', or 'images' for a folder. |
|
|
||||||
| `Title` | The optional, human-readable title of the file for display only (doesn't apply to folders). |
|
|
||||||
| `Filename` | The path to the file/folder, relative to the webroot. For example 'assets/images/my-image.jpg', or 'assets/images/' for a folder. |
|
|
||||||
| `Content` | Typically unused, but handy for a textual representation of files. For example for fulltext indexing of PDF documents. |
|
|
||||||
| `ShowInSearch` | Whether the file should be shown in search results, defaults to '1'. See ["Tutorial 4 - Site Search"](/tutorials/site_search) for enabling search. |
|
|
||||||
| `ParentID` | The ID of the parent Folder that this File/Folder is in. A ParentID of '0' indicates that the File/Folder is in the 'assets' directory. |
|
|
||||||
| `OwnerID` | The ID of the Member that 'owns' the File/Folder (not related to filesystem permissions). |
|
|
||||||
|
|
||||||
## Management through the "Files" section of the CMS
|
|
||||||
|
|
||||||
If you have the CMS module installed, you can manage files, folders and images in the "Files" section of the CMS. Inside this section, you will see a list of files and folders like below:
|
|
||||||
|
|
||||||
![](../../_images/assets.png)
|
|
||||||
|
|
||||||
You can click on any file to edit it, or click on any folder to open it. To delete a file or a folder, simply click the red 'X' symbol next to it. If you click to open a folder, you can go back up one level by clicking the 'up' arrow above the folder name (highlighted below):
|
|
||||||
|
|
||||||
![](../../_images/assets_up.png)
|
|
||||||
|
|
||||||
Once you click to edit a file, you will see a form similar to the one below, in which you can edit the file's title, filename, owner, or even change which folder the file is located in:
|
|
||||||
|
|
||||||
![](../../_images/assets_editform.png)
|
|
||||||
|
|
||||||
You may also notice the 'Sync files' button (highlighted below). This button allows CMS users to 'synchronise' the database (remember, all files/folders are stored as database records) with the filesystem. This is particularly useful if someone has uploaded or removed files/folders via FTP, for example.
|
|
||||||
|
|
||||||
![](../../_images/assets_sync.png)
|
|
||||||
|
|
||||||
## Upload
|
|
||||||
|
|
||||||
Files can be managed through a `FileField` or an `UploadField`. The `[api:FileField]` class provides a simple HTML input with a type of "file", whereas an `[api:UploadField]` provides a much more feature-rich field (including AJAX-based uploads, previews, relationship management and file data management). See [`Reference - UploadField`](/developer_guides/forms/field_types/uploadfield) for more information about how to use the `UploadField` class.
|
|
@ -20,6 +20,9 @@
|
|||||||
* Implementation of new "Archive" concept for page removal, which supercedes "delete". Where deletion removed
|
* Implementation of new "Archive" concept for page removal, which supercedes "delete". Where deletion removed
|
||||||
pages only from draft, archiving removes from both draft and live simultaneously.
|
pages only from draft, archiving removes from both draft and live simultaneously.
|
||||||
* Support for multiple HtmlEditorConfigs on the same page.
|
* Support for multiple HtmlEditorConfigs on the same page.
|
||||||
|
* Most of the `Image` manipulation methods have been renamed
|
||||||
|
* New `Image` methods `CropWidth` and `CropHeight` added
|
||||||
|
* 'Max' versions of `Image` methods introduced to prevent up-sampling
|
||||||
|
|
||||||
#### Deprecated classes/methods removed
|
#### Deprecated classes/methods removed
|
||||||
|
|
||||||
@ -393,6 +396,15 @@ In order to remove the new "archive" action and restore the old "delete" action
|
|||||||
- CMSBatchAction_Delete
|
- CMSBatchAction_Delete
|
||||||
|
|
||||||
|
|
||||||
|
### Update Image method names in PHP code and templates
|
||||||
|
|
||||||
|
* `SetRatioSize` -> `Fit`
|
||||||
|
* `CroppedImage` -> `Fill`
|
||||||
|
* `PaddedImage` -> `Pad`
|
||||||
|
* `SetSize` -> `Pad`
|
||||||
|
* `SetWidth` -> `ScaleWidth`
|
||||||
|
* `SetHeight` -> `ScaleHeight`
|
||||||
|
|
||||||
### Other
|
### Other
|
||||||
|
|
||||||
* Helper function `DB::placeholders` can be used to generate a comma separated list of placeholders
|
* Helper function `DB::placeholders` can be used to generate a comma separated list of placeholders
|
||||||
|
BIN
docs/en/_images/image-methods.jpg
Normal file
After Width: | Height: | Size: 33 KiB |
@ -364,7 +364,7 @@ class File extends DataObject {
|
|||||||
// Preview
|
// Preview
|
||||||
if($this instanceof Image) {
|
if($this instanceof Image) {
|
||||||
$formattedImage = $this->getFormattedImage(
|
$formattedImage = $this->getFormattedImage(
|
||||||
'SetWidth',
|
'ScaleWidth',
|
||||||
Config::inst()->get('Image', 'asset_preview_width')
|
Config::inst()->get('Image', 'asset_preview_width')
|
||||||
);
|
);
|
||||||
$thumbnail = $formattedImage ? $formattedImage->URL : '';
|
$thumbnail = $formattedImage ? $formattedImage->URL : '';
|
||||||
|
@ -673,7 +673,7 @@ class HtmlEditorField_Toolbar extends RequestHandler {
|
|||||||
*/
|
*/
|
||||||
protected function getFieldsForImage($url, $file) {
|
protected function getFieldsForImage($url, $file) {
|
||||||
if($file->File instanceof Image) {
|
if($file->File instanceof Image) {
|
||||||
$formattedImage = $file->File->generateFormattedImage('SetWidth',
|
$formattedImage = $file->File->generateFormattedImage('ScaleWidth',
|
||||||
Config::inst()->get('Image', 'asset_preview_width'));
|
Config::inst()->get('Image', 'asset_preview_width'));
|
||||||
$thumbnailURL = Convert::raw2att($formattedImage ? $formattedImage->URL : $url);
|
$thumbnailURL = Convert::raw2att($formattedImage ? $formattedImage->URL : $url);
|
||||||
} else {
|
} else {
|
||||||
|
@ -873,8 +873,8 @@ class UploadField extends FileField {
|
|||||||
return $file->getThumbnail($width, $height)->getURL();
|
return $file->getThumbnail($width, $height)->getURL();
|
||||||
} elseif ($file->hasMethod('getThumbnailURL')) {
|
} elseif ($file->hasMethod('getThumbnailURL')) {
|
||||||
return $file->getThumbnailURL($width, $height);
|
return $file->getThumbnailURL($width, $height);
|
||||||
} elseif ($file->hasMethod('SetRatioSize')) {
|
} elseif ($file->hasMethod('Fit')) {
|
||||||
return $file->SetRatioSize($width, $height)->getURL();
|
return $file->Fit($width, $height)->getURL();
|
||||||
} else {
|
} else {
|
||||||
return $file->Icon();
|
return $file->Icon();
|
||||||
}
|
}
|
||||||
|
321
model/Image.php
@ -215,6 +215,260 @@ class Image extends File implements Flushable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scale image proportionally to fit within the specified bounds
|
||||||
|
*
|
||||||
|
* @param integer $width The width to size within
|
||||||
|
* @param integer $height The height to size within
|
||||||
|
* @return Image
|
||||||
|
*/
|
||||||
|
public function Fit($width, $height) {
|
||||||
|
// Prevent divide by zero on missing/blank file
|
||||||
|
if(!$this->getWidth() || !$this->getHeight()) return null;
|
||||||
|
|
||||||
|
// Check if image is already sized to the correct dimension
|
||||||
|
$widthRatio = $width / $this->getWidth();
|
||||||
|
$heightRatio = $height / $this->getHeight();
|
||||||
|
|
||||||
|
if( $widthRatio < $heightRatio ) {
|
||||||
|
// Target is higher aspect ratio than image, so check width
|
||||||
|
if($this->isWidth($width) && !Config::inst()->get('Image', 'force_resample')) return $this;
|
||||||
|
} else {
|
||||||
|
// Target is wider or same aspect ratio as image, so check height
|
||||||
|
if($this->isHeight($height) && !Config::inst()->get('Image', 'force_resample')) return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Item must be regenerated
|
||||||
|
return $this->getFormattedImage('Fit', $width, $height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scale image proportionally to fit within the specified bounds
|
||||||
|
*
|
||||||
|
* @param Image_Backend $backend
|
||||||
|
* @param integer $width The width to size within
|
||||||
|
* @param integer $height The height to size within
|
||||||
|
* @return Image_Backend
|
||||||
|
*/
|
||||||
|
public function generateFit(Image_Backend $backend, $width, $height) {
|
||||||
|
return $backend->resizeRatio($width, $height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proportionally scale down this image if it is wider or taller than the specified dimensions.
|
||||||
|
* Similar to Fit but without up-sampling. Use in templates with $FitMax.
|
||||||
|
*
|
||||||
|
* @uses Image::Fit()
|
||||||
|
* @param integer $width The maximum width of the output image
|
||||||
|
* @param integer $height The maximum height of the output image
|
||||||
|
* @return Image
|
||||||
|
*/
|
||||||
|
public function FitMax($width, $height) {
|
||||||
|
// Temporary $force_resample support for 3.x, to be removed in 4.0
|
||||||
|
if (Config::inst()->get('Image', 'force_resample') && $this->getWidth() <= $width && $this->getHeight() <= $height) return $this->Fit($this->getWidth(),$this->getHeight());
|
||||||
|
|
||||||
|
return $this->getWidth() > $width || $this->getHeight() > $height
|
||||||
|
? $this->Fit($width,$height)
|
||||||
|
: $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize and crop image to fill specified dimensions.
|
||||||
|
* Use in templates with $Fill
|
||||||
|
*
|
||||||
|
* @param integer $width Width to crop to
|
||||||
|
* @param integer $height Height to crop to
|
||||||
|
* @return Image
|
||||||
|
*/
|
||||||
|
public function Fill($width, $height) {
|
||||||
|
return $this->isSize($width, $height) && !Config::inst()->get('Image', 'force_resample')
|
||||||
|
? $this
|
||||||
|
: $this->getFormattedImage('Fill', $width, $height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize and crop image to fill specified dimensions.
|
||||||
|
* Use in templates with $Fill
|
||||||
|
*
|
||||||
|
* @param Image_Backend $backend
|
||||||
|
* @param integer $width Width to crop to
|
||||||
|
* @param integer $height Height to crop to
|
||||||
|
* @return Image_Backend
|
||||||
|
*/
|
||||||
|
public function generateFill(Image_Backend $backend, $width, $height) {
|
||||||
|
return $backend->croppedResize($width, $height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crop this image to the aspect ratio defined by the specified width and height,
|
||||||
|
* then scale down the image to those dimensions if it exceeds them.
|
||||||
|
* Similar to Fill but without up-sampling. Use in templates with $FillMax.
|
||||||
|
*
|
||||||
|
* @uses Image::Fill()
|
||||||
|
* @param integer $width The relative (used to determine aspect ratio) and maximum width of the output image
|
||||||
|
* @param integer $height The relative (used to determine aspect ratio) and maximum height of the output image
|
||||||
|
* @return Image
|
||||||
|
*/
|
||||||
|
public function FillMax($width, $height) {
|
||||||
|
// Prevent divide by zero on missing/blank file
|
||||||
|
if(!$this->getWidth() || !$this->getHeight()) return null;
|
||||||
|
|
||||||
|
// Temporary $force_resample support for 3.x, to be removed in 4.0
|
||||||
|
if (Config::inst()->get('Image', 'force_resample') && $this->isSize($width, $height)) return $this->Fill($width, $height);
|
||||||
|
|
||||||
|
// Is the image already the correct size?
|
||||||
|
if ($this->isSize($width, $height)) return $this;
|
||||||
|
|
||||||
|
// If not, make sure the image isn't upsampled
|
||||||
|
$imageRatio = $this->getWidth() / $this->getHeight();
|
||||||
|
$cropRatio = $width / $height;
|
||||||
|
// If cropping on the x axis compare heights
|
||||||
|
if ($cropRatio < $imageRatio && $this->getHeight() < $height) return $this->Fill($this->getHeight()*$cropRatio, $this->getHeight());
|
||||||
|
// Otherwise we're cropping on the y axis (or not cropping at all) so compare widths
|
||||||
|
if ($this->getWidth() < $width) return $this->Fill($this->getWidth(), $this->getWidth()/$cropRatio);
|
||||||
|
|
||||||
|
return $this->Fill($width, $height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fit image to specified dimensions and fill leftover space with a solid colour (default white). Use in templates with $Pad.
|
||||||
|
*
|
||||||
|
* @param integer $width The width to size to
|
||||||
|
* @param integer $height The height to size to
|
||||||
|
* @return Image
|
||||||
|
*/
|
||||||
|
public function Pad($width, $height, $backgroundColor='FFFFFF') {
|
||||||
|
return $this->isSize($width, $height) && !Config::inst()->get('Image', 'force_resample')
|
||||||
|
? $this
|
||||||
|
: $this->getFormattedImage('Pad', $width, $height, $backgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fit image to specified dimensions and fill leftover space with a solid colour (default white). Use in templates with $Pad.
|
||||||
|
*
|
||||||
|
* @param Image_Backend $backend
|
||||||
|
* @param integer $width The width to size to
|
||||||
|
* @param integer $height The height to size to
|
||||||
|
* @return Image_Backend
|
||||||
|
*/
|
||||||
|
public function generatePad(Image_Backend $backend, $width, $height, $backgroundColor='FFFFFF') {
|
||||||
|
return $backend->paddedResize($width, $height, $backgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scale image proportionally by width. Use in templates with $ScaleWidth.
|
||||||
|
*
|
||||||
|
* @param integer $width The width to set
|
||||||
|
* @return Image
|
||||||
|
*/
|
||||||
|
public function ScaleWidth($width) {
|
||||||
|
return $this->isWidth($width) && !Config::inst()->get('Image', 'force_resample')
|
||||||
|
? $this
|
||||||
|
: $this->getFormattedImage('ScaleWidth', $width);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scale image proportionally by width. Use in templates with $ScaleWidth.
|
||||||
|
*
|
||||||
|
* @param Image_Backend $backend
|
||||||
|
* @param int $width The width to set
|
||||||
|
* @return Image_Backend
|
||||||
|
*/
|
||||||
|
public function generateScaleWidth(Image_Backend $backend, $width) {
|
||||||
|
return $backend->resizeByWidth($width);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proportionally scale down this image if it is wider than the specified width.
|
||||||
|
* Similar to ScaleWidth but without up-sampling. Use in templates with $ScaleMaxWidth.
|
||||||
|
*
|
||||||
|
* @uses Image::ScaleWidth()
|
||||||
|
* @param integer $width The maximum width of the output image
|
||||||
|
* @return Image
|
||||||
|
*/
|
||||||
|
public function ScaleMaxWidth($width) {
|
||||||
|
// Temporary $force_resample support for 3.x, to be removed in 4.0
|
||||||
|
if (Config::inst()->get('Image', 'force_resample') && $this->getWidth() <= $width) return $this->ScaleWidth($this->getWidth());
|
||||||
|
|
||||||
|
return $this->getWidth() > $width
|
||||||
|
? $this->ScaleWidth($width)
|
||||||
|
: $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scale image proportionally by height. Use in templates with $ScaleHeight.
|
||||||
|
*
|
||||||
|
* @param integer $height The height to set
|
||||||
|
* @return Image
|
||||||
|
*/
|
||||||
|
public function ScaleHeight($height) {
|
||||||
|
return $this->isHeight($height) && !Config::inst()->get('Image', 'force_resample')
|
||||||
|
? $this
|
||||||
|
: $this->getFormattedImage('ScaleHeight', $height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scale image proportionally by height. Use in templates with $ScaleHeight.
|
||||||
|
*
|
||||||
|
* @param Image_Backend $backend
|
||||||
|
* @param integer $height The height to set
|
||||||
|
* @return Image_Backend
|
||||||
|
*/
|
||||||
|
public function generateScaleHeight(Image_Backend $backend, $height){
|
||||||
|
return $backend->resizeByHeight($height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proportionally scale down this image if it is taller than the specified height.
|
||||||
|
* Similar to ScaleHeight but without up-sampling. Use in templates with $ScaleMaxHeight.
|
||||||
|
*
|
||||||
|
* @uses Image::ScaleHeight()
|
||||||
|
* @param integer $height The maximum height of the output image
|
||||||
|
* @return Image
|
||||||
|
*/
|
||||||
|
public function ScaleMaxHeight($height) {
|
||||||
|
// Temporary $force_resample support for 3.x, to be removed in 4.0
|
||||||
|
if (Config::inst()->get('Image', 'force_resample') && $this->getHeight() <= $height) return $this->ScaleHeight($this->getHeight());
|
||||||
|
|
||||||
|
return $this->getHeight() > $height
|
||||||
|
? $this->ScaleHeight($height)
|
||||||
|
: $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crop image on X axis if it exceeds specified width. Retain height.
|
||||||
|
* Use in templates with $CropWidth. Example: $Image.ScaleHeight(100).$CropWidth(100)
|
||||||
|
*
|
||||||
|
* @uses Image::Fill()
|
||||||
|
* @param integer $width The maximum width of the output image
|
||||||
|
* @return Image
|
||||||
|
*/
|
||||||
|
public function CropWidth($width) {
|
||||||
|
// Temporary $force_resample support for 3.x, to be removed in 4.0
|
||||||
|
if (Config::inst()->get('Image', 'force_resample') && $this->getWidth() <= $width) return $this->Fill($this->getWidth(), $this->getHeight());
|
||||||
|
|
||||||
|
return $this->getWidth() > $width
|
||||||
|
? $this->Fill($width, $this->getHeight())
|
||||||
|
: $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crop image on Y axis if it exceeds specified height. Retain width.
|
||||||
|
* Use in templates with $CropHeight. Example: $Image.ScaleWidth(100).CropHeight(100)
|
||||||
|
*
|
||||||
|
* @uses Image::Fill()
|
||||||
|
* @param integer $height The maximum height of the output image
|
||||||
|
* @return Image
|
||||||
|
*/
|
||||||
|
public function CropHeight($height) {
|
||||||
|
// Temporary $force_resample support for 3.x, to be removed in 4.0
|
||||||
|
if (Config::inst()->get('Image', 'force_resample') && $this->getHeight() <= $height) return $this->Fill($this->getWidth(), $this->getHeight());
|
||||||
|
|
||||||
|
return $this->getHeight() > $height
|
||||||
|
? $this->Fill($this->getWidth(), $height)
|
||||||
|
: $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resize the image by preserving aspect ratio, keeping the image inside the
|
* Resize the image by preserving aspect ratio, keeping the image inside the
|
||||||
* $width and $height
|
* $width and $height
|
||||||
@ -222,25 +476,11 @@ class Image extends File implements Flushable {
|
|||||||
* @param integer $width The width to size within
|
* @param integer $width The width to size within
|
||||||
* @param integer $height The height to size within
|
* @param integer $height The height to size within
|
||||||
* @return Image
|
* @return Image
|
||||||
|
* @deprecated 4.0 Use Fit instead
|
||||||
*/
|
*/
|
||||||
public function SetRatioSize($width, $height) {
|
public function SetRatioSize($width, $height) {
|
||||||
|
Deprecation::notice('4.0', 'Use Fit instead');
|
||||||
// Prevent divide by zero on missing/blank file
|
return $this->Fit($width, $height);
|
||||||
if(empty($this->width) || empty($this->height)) return null;
|
|
||||||
|
|
||||||
// Check if image is already sized to the correct dimension
|
|
||||||
$widthRatio = $width / $this->width;
|
|
||||||
$heightRatio = $height / $this->height;
|
|
||||||
if( $widthRatio < $heightRatio ) {
|
|
||||||
// Target is higher aspect ratio than image, so check width
|
|
||||||
if($this->isWidth($width) && !Config::inst()->get('Image', 'force_resample')) return $this;
|
|
||||||
} else {
|
|
||||||
// Target is wider aspect ratio than image, so check height
|
|
||||||
if($this->isHeight($height) && !Config::inst()->get('Image', 'force_resample')) return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Item must be regenerated
|
|
||||||
return $this->getFormattedImage('SetRatioSize', $width, $height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -251,8 +491,10 @@ class Image extends File implements Flushable {
|
|||||||
* @param integer $width The width to size within
|
* @param integer $width The width to size within
|
||||||
* @param integer $height The height to size within
|
* @param integer $height The height to size within
|
||||||
* @return Image_Backend
|
* @return Image_Backend
|
||||||
|
* @deprecated 4.0 Use generateFit instead
|
||||||
*/
|
*/
|
||||||
public function generateSetRatioSize(Image_Backend $backend, $width, $height) {
|
public function generateSetRatioSize(Image_Backend $backend, $width, $height) {
|
||||||
|
Deprecation::notice('4.0', 'Use generateFit instead');
|
||||||
return $backend->resizeRatio($width, $height);
|
return $backend->resizeRatio($width, $height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,11 +503,11 @@ class Image extends File implements Flushable {
|
|||||||
*
|
*
|
||||||
* @param integer $width The width to set
|
* @param integer $width The width to set
|
||||||
* @return Image
|
* @return Image
|
||||||
|
* @deprecated 4.0 Use ScaleWidth instead
|
||||||
*/
|
*/
|
||||||
public function SetWidth($width) {
|
public function SetWidth($width) {
|
||||||
return $this->isWidth($width) && !Config::inst()->get('Image', 'force_resample')
|
Deprecation::notice('4.0', 'Use ScaleWidth instead');
|
||||||
? $this
|
return $this->ScaleWidth($width);
|
||||||
: $this->getFormattedImage('SetWidth', $width);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -274,8 +516,10 @@ class Image extends File implements Flushable {
|
|||||||
* @param Image_Backend $backend
|
* @param Image_Backend $backend
|
||||||
* @param int $width The width to set
|
* @param int $width The width to set
|
||||||
* @return Image_Backend
|
* @return Image_Backend
|
||||||
|
* @deprecated 4.0 Use generateScaleWidth instead
|
||||||
*/
|
*/
|
||||||
public function generateSetWidth(Image_Backend $backend, $width) {
|
public function generateSetWidth(Image_Backend $backend, $width) {
|
||||||
|
Deprecation::notice('4.0', 'Use generateScaleWidth instead');
|
||||||
return $backend->resizeByWidth($width);
|
return $backend->resizeByWidth($width);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,11 +528,11 @@ class Image extends File implements Flushable {
|
|||||||
*
|
*
|
||||||
* @param integer $height The height to set
|
* @param integer $height The height to set
|
||||||
* @return Image
|
* @return Image
|
||||||
|
* @deprecated 4.0 Use ScaleHeight instead
|
||||||
*/
|
*/
|
||||||
public function SetHeight($height) {
|
public function SetHeight($height) {
|
||||||
return $this->isHeight($height) && !Config::inst()->get('Image', 'force_resample')
|
Deprecation::notice('4.0', 'Use ScaleHeight instead');
|
||||||
? $this
|
return $this->ScaleHeight($height);
|
||||||
: $this->getFormattedImage('SetHeight', $height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -297,8 +541,10 @@ class Image extends File implements Flushable {
|
|||||||
* @param Image_Backend $backend
|
* @param Image_Backend $backend
|
||||||
* @param integer $height The height to set
|
* @param integer $height The height to set
|
||||||
* @return Image_Backend
|
* @return Image_Backend
|
||||||
|
* @deprecated 4.0 Use generateScaleHeight instead
|
||||||
*/
|
*/
|
||||||
public function generateSetHeight(Image_Backend $backend, $height){
|
public function generateSetHeight(Image_Backend $backend, $height){
|
||||||
|
Deprecation::notice('4.0', 'Use generateScaleHeight instead');
|
||||||
return $backend->resizeByHeight($height);
|
return $backend->resizeByHeight($height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,11 +555,11 @@ class Image extends File implements Flushable {
|
|||||||
* @param integer $width The width to size to
|
* @param integer $width The width to size to
|
||||||
* @param integer $height The height to size to
|
* @param integer $height The height to size to
|
||||||
* @return Image
|
* @return Image
|
||||||
|
* @deprecated 4.0 Use Pad instead
|
||||||
*/
|
*/
|
||||||
public function SetSize($width, $height) {
|
public function SetSize($width, $height) {
|
||||||
return $this->isSize($width, $height) && !Config::inst()->get('Image', 'force_resample')
|
Deprecation::notice('4.0', 'Use Pad instead');
|
||||||
? $this
|
return $this->Pad($width, $height);
|
||||||
: $this->getFormattedImage('SetSize', $width, $height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -323,8 +569,10 @@ class Image extends File implements Flushable {
|
|||||||
* @param integer $width The width to size to
|
* @param integer $width The width to size to
|
||||||
* @param integer $height The height to size to
|
* @param integer $height The height to size to
|
||||||
* @return Image_Backend
|
* @return Image_Backend
|
||||||
|
* @deprecated 4.0 Use generatePad instead
|
||||||
*/
|
*/
|
||||||
public function generateSetSize(Image_Backend $backend, $width, $height) {
|
public function generateSetSize(Image_Backend $backend, $width, $height) {
|
||||||
|
Deprecation::notice('4.0', 'Use generatePad instead');
|
||||||
return $backend->paddedResize($width, $height);
|
return $backend->paddedResize($width, $height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,11 +619,11 @@ class Image extends File implements Flushable {
|
|||||||
* @param integer $width The width to size to
|
* @param integer $width The width to size to
|
||||||
* @param integer $height The height to size to
|
* @param integer $height The height to size to
|
||||||
* @return Image
|
* @return Image
|
||||||
|
* @deprecated 4.0 Use Pad instead
|
||||||
*/
|
*/
|
||||||
public function PaddedImage($width, $height, $backgroundColor='FFFFFF') {
|
public function PaddedImage($width, $height, $backgroundColor='FFFFFF') {
|
||||||
return $this->isSize($width, $height) && !Config::inst()->get('Image', 'force_resample')
|
Deprecation::notice('4.0', 'Use Pad instead');
|
||||||
? $this
|
return $this->Pad($width, $height, $backgroundColor);
|
||||||
: $this->getFormattedImage('PaddedImage', $width, $height, $backgroundColor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -385,8 +633,10 @@ class Image extends File implements Flushable {
|
|||||||
* @param integer $width The width to size to
|
* @param integer $width The width to size to
|
||||||
* @param integer $height The height to size to
|
* @param integer $height The height to size to
|
||||||
* @return Image_Backend
|
* @return Image_Backend
|
||||||
|
* @deprecated 4.0 Use generatePad instead
|
||||||
*/
|
*/
|
||||||
public function generatePaddedImage(Image_Backend $backend, $width, $height, $backgroundColor='FFFFFF') {
|
public function generatePaddedImage(Image_Backend $backend, $width, $height, $backgroundColor='FFFFFF') {
|
||||||
|
Deprecation::notice('4.0', 'Use generatePad instead');
|
||||||
return $backend->paddedResize($width, $height, $backgroundColor);
|
return $backend->paddedResize($width, $height, $backgroundColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,7 +760,8 @@ class Image extends File implements Flushable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a resized copy of this image with the given width & height.
|
* Generate a resized copy of this image with the given width & height.
|
||||||
* Use in templates with $ResizedImage.
|
* This can be used in templates with $ResizedImage but should be avoided,
|
||||||
|
* as it's the only image manipulation function which can skew an image.
|
||||||
*
|
*
|
||||||
* @param integer $width Width to resize to
|
* @param integer $width Width to resize to
|
||||||
* @param integer $height Height to resize to
|
* @param integer $height Height to resize to
|
||||||
@ -547,11 +798,11 @@ class Image extends File implements Flushable {
|
|||||||
* @param integer $width Width to crop to
|
* @param integer $width Width to crop to
|
||||||
* @param integer $height Height to crop to
|
* @param integer $height Height to crop to
|
||||||
* @return Image
|
* @return Image
|
||||||
|
* @deprecated 4.0 Use Fill instead
|
||||||
*/
|
*/
|
||||||
public function CroppedImage($width, $height) {
|
public function CroppedImage($width, $height) {
|
||||||
return $this->isSize($width, $height) && !Config::inst()->get('Image', 'force_resample')
|
Deprecation::notice('4.0', 'Use Fill instead');
|
||||||
? $this
|
return $this->Fill($width, $height);
|
||||||
: $this->getFormattedImage('CroppedImage', $width, $height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -562,8 +813,10 @@ class Image extends File implements Flushable {
|
|||||||
* @param integer $width Width to crop to
|
* @param integer $width Width to crop to
|
||||||
* @param integer $height Height to crop to
|
* @param integer $height Height to crop to
|
||||||
* @return Image_Backend
|
* @return Image_Backend
|
||||||
|
* @deprecated 4.0 Use generateFill instead
|
||||||
*/
|
*/
|
||||||
public function generateCroppedImage(Image_Backend $backend, $width, $height) {
|
public function generateCroppedImage(Image_Backend $backend, $width, $height) {
|
||||||
|
Deprecation::notice('4.0', 'Use generateFill instead');
|
||||||
return $backend->croppedResize($width, $height);
|
return $backend->croppedResize($width, $height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,7 +903,7 @@ class Image extends File implements Flushable {
|
|||||||
|
|
||||||
// Without this, not a single file would be written
|
// Without this, not a single file would be written
|
||||||
// caused by a check in getFormattedImage()
|
// caused by a check in getFormattedImage()
|
||||||
$_GET['flush'] = 1;
|
$this->flush();
|
||||||
|
|
||||||
$numGenerated = 0;
|
$numGenerated = 0;
|
||||||
$generatedImages = $this->getGeneratedImages();
|
$generatedImages = $this->getGeneratedImages();
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<div class="ss-uploadfield-item-preview">
|
<div class="ss-uploadfield-item-preview">
|
||||||
<% if $Width %>
|
<% if $Width %>
|
||||||
<span>$Preview.SetRatioSize(30, 40)</span>
|
<span>$Preview.Fit(30, 40)</span>
|
||||||
<% else %>
|
<% else %>
|
||||||
<span class="no-preview"></span>
|
<span class="no-preview"></span>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
|
@ -161,7 +161,7 @@ class GDTest extends SapphireTest {
|
|||||||
$fullPath = realpath(dirname(__FILE__) . '/gdtest/test_jpg.jpg');
|
$fullPath = realpath(dirname(__FILE__) . '/gdtest/test_jpg.jpg');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$gdFailure = new GDBackend_Failure($fullPath, array('SetWidth', 123));
|
$gdFailure = new GDBackend_Failure($fullPath, array('ScaleWidth', 123));
|
||||||
$this->fail('GDBackend_Failure should throw an exception when setting image resource');
|
$this->fail('GDBackend_Failure should throw an exception when setting image resource');
|
||||||
} catch (GDBackend_Failure_Exception $e) {
|
} catch (GDBackend_Failure_Exception $e) {
|
||||||
$cache = SS_Cache::factory('GDBackend_Manipulations');
|
$cache = SS_Cache::factory('GDBackend_Manipulations');
|
||||||
@ -169,8 +169,8 @@ class GDTest extends SapphireTest {
|
|||||||
|
|
||||||
$data = unserialize($cache->load($key));
|
$data = unserialize($cache->load($key));
|
||||||
|
|
||||||
$this->assertArrayHasKey('SetWidth|123', $data);
|
$this->assertArrayHasKey('ScaleWidth|123', $data);
|
||||||
$this->assertTrue($data['SetWidth|123']);
|
$this->assertTrue($data['ScaleWidth|123']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,12 +183,12 @@ class GDTest extends SapphireTest {
|
|||||||
$fullPath = realpath(dirname(__FILE__) . '/gdtest/test_jpg.jpg');
|
$fullPath = realpath(dirname(__FILE__) . '/gdtest/test_jpg.jpg');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$gdFailure = new GDBackend_Failure($fullPath, array('SetWidth-failed', 123));
|
$gdFailure = new GDBackend_Failure($fullPath, array('ScaleWidth-failed', 123));
|
||||||
$this->fail('GDBackend_Failure should throw an exception when setting image resource');
|
$this->fail('GDBackend_Failure should throw an exception when setting image resource');
|
||||||
} catch (GDBackend_Failure_Exception $e) {
|
} catch (GDBackend_Failure_Exception $e) {
|
||||||
$gd = new GDBackend($fullPath, array('SetWidth', 123));
|
$gd = new GDBackend($fullPath, array('ScaleWidth', 123));
|
||||||
$this->assertTrue($gd->failedResample($fullPath, 'SetWidth-failed|123'));
|
$this->assertTrue($gd->failedResample($fullPath, 'ScaleWidth-failed|123'));
|
||||||
$this->assertFalse($gd->failedResample($fullPath, 'SetWidth-not-failed|123'));
|
$this->assertFalse($gd->failedResample($fullPath, 'ScaleWidth-not-failed|123'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,8 +55,8 @@ class DataDifferencerTest extends SapphireTest {
|
|||||||
$differ = new DataDifferencer($obj1v1, $obj1v2);
|
$differ = new DataDifferencer($obj1v1, $obj1v2);
|
||||||
$obj1Diff = $differ->diffedData();
|
$obj1Diff = $differ->diffedData();
|
||||||
|
|
||||||
$this->assertContains($image1->Filename, $obj1Diff->getField('Image'));
|
$this->assertContains($image1->Name, $obj1Diff->getField('Image'));
|
||||||
$this->assertContains($image2->Filename, $obj1Diff->getField('Image'));
|
$this->assertContains($image2->Name, $obj1Diff->getField('Image'));
|
||||||
$this->assertContains('<ins>obj2</ins><del>obj1</del>',
|
$this->assertContains('<ins>obj2</ins><del>obj1</del>',
|
||||||
str_replace(' ','',$obj1Diff->getField('HasOneRelationID')));
|
str_replace(' ','',$obj1Diff->getField('HasOneRelationID')));
|
||||||
}
|
}
|
||||||
|
@ -10,22 +10,9 @@ class GDImageTest extends ImageTest {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
Image::set_backend("GDBackend");
|
Image::set_backend("GDBackend");
|
||||||
|
|
||||||
// Create a test files for each of the fixture references
|
parent::setUp();
|
||||||
$fileIDs = $this->allFixtureIDs('Image');
|
|
||||||
foreach($fileIDs as $fileID) {
|
|
||||||
$file = DataObject::get_by_id('Image', $fileID);
|
|
||||||
|
|
||||||
$image = imagecreatetruecolor(300,300);
|
|
||||||
|
|
||||||
imagepng($image, BASE_PATH."/{$file->Filename}");
|
|
||||||
imagedestroy($image);
|
|
||||||
|
|
||||||
$file->write();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown() {
|
public function tearDown() {
|
||||||
@ -47,13 +34,13 @@ class GDImageTest extends ImageTest {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Simluate a failed manipulation
|
// Simluate a failed manipulation
|
||||||
$gdFailure = new GDBackend_Failure($fullPath, array('SetWidth', 123));
|
$gdFailure = new GDBackend_Failure($fullPath, array('ScaleWidth', 123));
|
||||||
$this->fail('GDBackend_Failure should throw an exception when setting image resource');
|
$this->fail('GDBackend_Failure should throw an exception when setting image resource');
|
||||||
} catch (GDBackend_Failure_Exception $e) {
|
} catch (GDBackend_Failure_Exception $e) {
|
||||||
// Check that the cache has stored the manipulation failure
|
// Check that the cache has stored the manipulation failure
|
||||||
$data = unserialize($cache->load($key));
|
$data = unserialize($cache->load($key));
|
||||||
$this->assertArrayHasKey('SetWidth|123', $data);
|
$this->assertArrayHasKey('ScaleWidth|123', $data);
|
||||||
$this->assertTrue($data['SetWidth|123']);
|
$this->assertTrue($data['ScaleWidth|123']);
|
||||||
|
|
||||||
// Delete the image object
|
// Delete the image object
|
||||||
$image->delete();
|
$image->delete();
|
||||||
|
@ -30,19 +30,30 @@ class ImageTest extends SapphireTest {
|
|||||||
|
|
||||||
if(!file_exists(BASE_PATH."/$folder->Filename")) mkdir(BASE_PATH."/$folder->Filename");
|
if(!file_exists(BASE_PATH."/$folder->Filename")) mkdir(BASE_PATH."/$folder->Filename");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy test images for each of the fixture references
|
||||||
|
$imageIDs = $this->allFixtureIDs('Image');
|
||||||
|
foreach($imageIDs as $imageID) {
|
||||||
|
$image = DataObject::get_by_id('Image', $imageID);
|
||||||
|
$filePath = BASE_PATH."/$image->Filename";
|
||||||
|
$sourcePath = str_replace('assets/ImageTest/', 'framework/tests/model/testimages/', $filePath);
|
||||||
|
if(!file_exists($filePath)) {
|
||||||
|
if (!copy($sourcePath, $filePath)) user_error('Failed to copy test images', E_USER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown() {
|
public function tearDown() {
|
||||||
if($this->origBackend) Image::set_backend($this->origBackend);
|
if($this->origBackend) Image::set_backend($this->origBackend);
|
||||||
|
|
||||||
/* Remove the test files that we've created */
|
// Remove the test files that we've created
|
||||||
$fileIDs = $this->allFixtureIDs('Image');
|
$fileIDs = $this->allFixtureIDs('Image');
|
||||||
foreach($fileIDs as $fileID) {
|
foreach($fileIDs as $fileID) {
|
||||||
$file = DataObject::get_by_id('Image', $fileID);
|
$file = DataObject::get_by_id('Image', $fileID);
|
||||||
if($file && file_exists(BASE_PATH."/$file->Filename")) unlink(BASE_PATH."/$file->Filename");
|
if($file && file_exists(BASE_PATH."/$file->Filename")) unlink(BASE_PATH."/$file->Filename");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove the test folders that we've crated */
|
// Remove the test folders that we've created
|
||||||
$folderIDs = $this->allFixtureIDs('Folder');
|
$folderIDs = $this->allFixtureIDs('Folder');
|
||||||
foreach($folderIDs as $folderID) {
|
foreach($folderIDs as $folderID) {
|
||||||
$folder = DataObject::get_by_id('Folder', $folderID);
|
$folder = DataObject::get_by_id('Folder', $folderID);
|
||||||
@ -89,7 +100,7 @@ class ImageTest extends SapphireTest {
|
|||||||
public function testMultipleGenerateManipulationCalls() {
|
public function testMultipleGenerateManipulationCalls() {
|
||||||
$image = $this->objFromFixture('Image', 'imageWithoutTitle');
|
$image = $this->objFromFixture('Image', 'imageWithoutTitle');
|
||||||
|
|
||||||
$imageFirst = $image->SetWidth(200);
|
$imageFirst = $image->ScaleWidth(200);
|
||||||
$this->assertNotNull($imageFirst);
|
$this->assertNotNull($imageFirst);
|
||||||
$expected = 200;
|
$expected = 200;
|
||||||
$actual = $imageFirst->getWidth();
|
$actual = $imageFirst->getWidth();
|
||||||
@ -113,27 +124,27 @@ class ImageTest extends SapphireTest {
|
|||||||
$this->assertTrue($image->isSize(300, 300));
|
$this->assertTrue($image->isSize(300, 300));
|
||||||
|
|
||||||
// Set width to 300 pixels
|
// Set width to 300 pixels
|
||||||
$imageSetWidth = $image->SetWidth(300);
|
$imageScaleWidth = $image->ScaleWidth(300);
|
||||||
$this->assertEquals($imageSetWidth->getWidth(), 300);
|
$this->assertEquals($imageScaleWidth->getWidth(), 300);
|
||||||
$this->assertEquals($image->Filename, $imageSetWidth->Filename);
|
$this->assertEquals($image->Filename, $imageScaleWidth->Filename);
|
||||||
|
|
||||||
// Set height to 300 pixels
|
// Set height to 300 pixels
|
||||||
$imageSetHeight = $image->SetHeight(300);
|
$imageScaleHeight = $image->ScaleHeight(300);
|
||||||
$this->assertEquals($imageSetHeight->getHeight(), 300);
|
$this->assertEquals($imageScaleHeight->getHeight(), 300);
|
||||||
$this->assertEquals($image->Filename, $imageSetHeight->Filename);
|
$this->assertEquals($image->Filename, $imageScaleHeight->Filename);
|
||||||
|
|
||||||
// Crop image to 300 x 300
|
// Crop image to 300 x 300
|
||||||
$imageCropped = $image->CroppedImage(300, 300);
|
$imageCropped = $image->Fill(300, 300);
|
||||||
$this->assertTrue($imageCropped->isSize(300, 300));
|
$this->assertTrue($imageCropped->isSize(300, 300));
|
||||||
$this->assertEquals($image->Filename, $imageCropped->Filename);
|
$this->assertEquals($image->Filename, $imageCropped->Filename);
|
||||||
|
|
||||||
// Resize (padded) to 300 x 300
|
// Resize (padded) to 300 x 300
|
||||||
$imageSized = $image->SetSize(300, 300);
|
$imageSized = $image->Pad(300, 300);
|
||||||
$this->assertTrue($imageSized->isSize(300, 300));
|
$this->assertTrue($imageSized->isSize(300, 300));
|
||||||
$this->assertEquals($image->Filename, $imageSized->Filename);
|
$this->assertEquals($image->Filename, $imageSized->Filename);
|
||||||
|
|
||||||
// Padded image 300 x 300 (same as above)
|
// Padded image 300 x 300 (same as above)
|
||||||
$imagePadded = $image->PaddedImage(300, 300);
|
$imagePadded = $image->Pad(300, 300);
|
||||||
$this->assertTrue($imagePadded->isSize(300, 300));
|
$this->assertTrue($imagePadded->isSize(300, 300));
|
||||||
$this->assertEquals($image->Filename, $imagePadded->Filename);
|
$this->assertEquals($image->Filename, $imagePadded->Filename);
|
||||||
|
|
||||||
@ -142,16 +153,16 @@ class ImageTest extends SapphireTest {
|
|||||||
$this->assertTrue($imageStretched->isSize(300, 300));
|
$this->assertTrue($imageStretched->isSize(300, 300));
|
||||||
$this->assertEquals($image->Filename, $imageStretched->Filename);
|
$this->assertEquals($image->Filename, $imageStretched->Filename);
|
||||||
|
|
||||||
// SetRatioSize (various options)
|
// Fit (various options)
|
||||||
$imageSetRatioSize = $image->SetRatioSize(300, 600);
|
$imageFit = $image->Fit(300, 600);
|
||||||
$this->assertTrue($imageSetRatioSize->isSize(300, 300));
|
$this->assertTrue($imageFit->isSize(300, 300));
|
||||||
$this->assertEquals($image->Filename, $imageSetRatioSize->Filename);
|
$this->assertEquals($image->Filename, $imageFit->Filename);
|
||||||
$imageSetRatioSize = $image->SetRatioSize(600, 300);
|
$imageFit = $image->Fit(600, 300);
|
||||||
$this->assertTrue($imageSetRatioSize->isSize(300, 300));
|
$this->assertTrue($imageFit->isSize(300, 300));
|
||||||
$this->assertEquals($image->Filename, $imageSetRatioSize->Filename);
|
$this->assertEquals($image->Filename, $imageFit->Filename);
|
||||||
$imageSetRatioSize = $image->SetRatioSize(300, 300);
|
$imageFit = $image->Fit(300, 300);
|
||||||
$this->assertTrue($imageSetRatioSize->isSize(300, 300));
|
$this->assertTrue($imageFit->isSize(300, 300));
|
||||||
$this->assertEquals($image->Filename, $imageSetRatioSize->Filename);
|
$this->assertEquals($image->Filename, $imageFit->Filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -167,27 +178,27 @@ class ImageTest extends SapphireTest {
|
|||||||
Config::inst()->update('Image', 'force_resample', true);
|
Config::inst()->update('Image', 'force_resample', true);
|
||||||
|
|
||||||
// Set width to 300 pixels
|
// Set width to 300 pixels
|
||||||
$imageSetWidth = $image->SetWidth(300);
|
$imageScaleWidth = $image->ScaleWidth(300);
|
||||||
$this->assertEquals($imageSetWidth->getWidth(), 300);
|
$this->assertEquals($imageScaleWidth->getWidth(), 300);
|
||||||
$this->assertNotEquals($image->Filename, $imageSetWidth->Filename);
|
$this->assertNotEquals($image->Filename, $imageScaleWidth->Filename);
|
||||||
|
|
||||||
// Set height to 300 pixels
|
// Set height to 300 pixels
|
||||||
$imageSetHeight = $image->SetHeight(300);
|
$imageScaleHeight = $image->ScaleHeight(300);
|
||||||
$this->assertEquals($imageSetHeight->getHeight(), 300);
|
$this->assertEquals($imageScaleHeight->getHeight(), 300);
|
||||||
$this->assertNotEquals($image->Filename, $imageSetHeight->Filename);
|
$this->assertNotEquals($image->Filename, $imageScaleHeight->Filename);
|
||||||
|
|
||||||
// Crop image to 300 x 300
|
// Crop image to 300 x 300
|
||||||
$imageCropped = $image->CroppedImage(300, 300);
|
$imageCropped = $image->Fill(300, 300);
|
||||||
$this->assertTrue($imageCropped->isSize(300, 300));
|
$this->assertTrue($imageCropped->isSize(300, 300));
|
||||||
$this->assertNotEquals($image->Filename, $imageCropped->Filename);
|
$this->assertNotEquals($image->Filename, $imageCropped->Filename);
|
||||||
|
|
||||||
// Resize (padded) to 300 x 300
|
// Resize (padded) to 300 x 300
|
||||||
$imageSized = $image->SetSize(300, 300);
|
$imageSized = $image->Pad(300, 300);
|
||||||
$this->assertTrue($imageSized->isSize(300, 300));
|
$this->assertTrue($imageSized->isSize(300, 300));
|
||||||
$this->assertNotEquals($image->Filename, $imageSized->Filename);
|
$this->assertNotEquals($image->Filename, $imageSized->Filename);
|
||||||
|
|
||||||
// Padded image 300 x 300 (same as above)
|
// Padded image 300 x 300 (same as above)
|
||||||
$imagePadded = $image->PaddedImage(300, 300);
|
$imagePadded = $image->Pad(300, 300);
|
||||||
$this->assertTrue($imagePadded->isSize(300, 300));
|
$this->assertTrue($imagePadded->isSize(300, 300));
|
||||||
$this->assertNotEquals($image->Filename, $imagePadded->Filename);
|
$this->assertNotEquals($image->Filename, $imagePadded->Filename);
|
||||||
|
|
||||||
@ -196,16 +207,16 @@ class ImageTest extends SapphireTest {
|
|||||||
$this->assertTrue($imageStretched->isSize(300, 300));
|
$this->assertTrue($imageStretched->isSize(300, 300));
|
||||||
$this->assertNotEquals($image->Filename, $imageStretched->Filename);
|
$this->assertNotEquals($image->Filename, $imageStretched->Filename);
|
||||||
|
|
||||||
// SetRatioSize (various options)
|
// Fit (various options)
|
||||||
$imageSetRatioSize = $image->SetRatioSize(300, 600);
|
$imageFit = $image->Fit(300, 600);
|
||||||
$this->assertTrue($imageSetRatioSize->isSize(300, 300));
|
$this->assertTrue($imageFit->isSize(300, 300));
|
||||||
$this->assertNotEquals($image->Filename, $imageSetRatioSize->Filename);
|
$this->assertNotEquals($image->Filename, $imageFit->Filename);
|
||||||
$imageSetRatioSize = $image->SetRatioSize(600, 300);
|
$imageFit = $image->Fit(600, 300);
|
||||||
$this->assertTrue($imageSetRatioSize->isSize(300, 300));
|
$this->assertTrue($imageFit->isSize(300, 300));
|
||||||
$this->assertNotEquals($image->Filename, $imageSetRatioSize->Filename);
|
$this->assertNotEquals($image->Filename, $imageFit->Filename);
|
||||||
$imageSetRatioSize = $image->SetRatioSize(300, 300);
|
$imageFit = $image->Fit(300, 300);
|
||||||
$this->assertTrue($imageSetRatioSize->isSize(300, 300));
|
$this->assertTrue($imageFit->isSize(300, 300));
|
||||||
$this->assertNotEquals($image->Filename, $imageSetRatioSize->Filename);
|
$this->assertNotEquals($image->Filename, $imageFit->Filename);
|
||||||
Config::inst()->update('Image', 'force_resample', $origForceResample);
|
Config::inst()->update('Image', 'force_resample', $origForceResample);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,20 +225,52 @@ class ImageTest extends SapphireTest {
|
|||||||
$this->assertTrue($image->isSize(300, 300));
|
$this->assertTrue($image->isSize(300, 300));
|
||||||
|
|
||||||
// Test normal resize
|
// Test normal resize
|
||||||
$resized = $image->SetSize(150, 100);
|
$resized = $image->Pad(150, 100);
|
||||||
$this->assertTrue($resized->isSize(150, 100));
|
$this->assertTrue($resized->isSize(150, 100));
|
||||||
|
|
||||||
// Test cropped resize
|
// Test cropped resize
|
||||||
$cropped = $image->CroppedImage(100, 200);
|
$cropped = $image->Fill(100, 200);
|
||||||
$this->assertTrue($cropped->isSize(100, 200));
|
$this->assertTrue($cropped->isSize(100, 200));
|
||||||
|
|
||||||
// Test padded resize
|
// Test padded resize
|
||||||
$padded = $image->PaddedImage(200, 100);
|
$padded = $image->Pad(200, 100);
|
||||||
$this->assertTrue($padded->isSize(200, 100));
|
$this->assertTrue($padded->isSize(200, 100));
|
||||||
|
|
||||||
// Test SetRatioSize
|
// Test Fit
|
||||||
$ratio = $image->SetRatioSize(80, 160);
|
$ratio = $image->Fit(80, 160);
|
||||||
$this->assertTrue($ratio->isSize(80, 80));
|
$this->assertTrue($ratio->isSize(80, 80));
|
||||||
|
|
||||||
|
// Test FitMax
|
||||||
|
$fitMaxDn = $image->FitMax(200, 100);
|
||||||
|
$this->assertTrue($fitMaxDn->isSize(100, 100));
|
||||||
|
$fitMaxUp = $image->FitMax(500, 400);
|
||||||
|
$this->assertTrue($fitMaxUp->isSize(300, 300));
|
||||||
|
|
||||||
|
//Test ScaleMax
|
||||||
|
$scaleMaxWDn = $image->ScaleMaxWidth(200);
|
||||||
|
$this->assertTrue($scaleMaxWDn->isSize(200, 200));
|
||||||
|
$scaleMaxWUp = $image->ScaleMaxWidth(400);
|
||||||
|
$this->assertTrue($scaleMaxWUp->isSize(300, 300));
|
||||||
|
$scaleMaxHDn = $image->ScaleMaxHeight(200);
|
||||||
|
$this->assertTrue($scaleMaxHDn->isSize(200, 200));
|
||||||
|
$scaleMaxHUp = $image->ScaleMaxHeight(400);
|
||||||
|
$this->assertTrue($scaleMaxHUp->isSize(300, 300));
|
||||||
|
|
||||||
|
// Test FillMax
|
||||||
|
$cropMaxDn = $image->FillMax(200, 100);
|
||||||
|
$this->assertTrue($cropMaxDn->isSize(200, 100));
|
||||||
|
$cropMaxUp = $image->FillMax(400, 200);
|
||||||
|
$this->assertTrue($cropMaxUp->isSize(300, 150));
|
||||||
|
|
||||||
|
// Test Clip
|
||||||
|
$clipWDn = $image->CropWidth(200);
|
||||||
|
$this->assertTrue($clipWDn->isSize(200, 300));
|
||||||
|
$clipWUp = $image->CropWidth(400);
|
||||||
|
$this->assertTrue($clipWUp->isSize(300, 300));
|
||||||
|
$clipHDn = $image->CropHeight(200);
|
||||||
|
$this->assertTrue($clipHDn->isSize(300, 200));
|
||||||
|
$clipHUp = $image->CropHeight(400);
|
||||||
|
$this->assertTrue($clipHUp->isSize(300, 300));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -236,15 +279,15 @@ class ImageTest extends SapphireTest {
|
|||||||
public function testGenerateImageWithInvalidParameters() {
|
public function testGenerateImageWithInvalidParameters() {
|
||||||
$image = $this->objFromFixture('Image', 'imageWithoutTitle');
|
$image = $this->objFromFixture('Image', 'imageWithoutTitle');
|
||||||
$image->setHeight('String');
|
$image->setHeight('String');
|
||||||
$image->PaddedImage(600,600,'XXXXXX');
|
$image->Pad(600,600,'XXXXXX');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCacheFilename() {
|
public function testCacheFilename() {
|
||||||
$image = $this->objFromFixture('Image', 'imageWithoutTitle');
|
$image = $this->objFromFixture('Image', 'imageWithoutTitle');
|
||||||
$imageFirst = $image->SetSize(200,200);
|
$imageFirst = $image->Pad(200,200,'CCCCCC');
|
||||||
$imageFilename = $imageFirst->getFullPath();
|
$imageFilename = $imageFirst->getFullPath();
|
||||||
// Encoding of the arguments is duplicated from cacheFilename
|
// Encoding of the arguments is duplicated from cacheFilename
|
||||||
$neededPart = 'SetSize' . base64_encode(json_encode(array(200,200)));
|
$neededPart = 'Pad' . base64_encode(json_encode(array(200,200,'CCCCCC')));
|
||||||
$this->assertContains($neededPart, $imageFilename, 'Filename for cached image is correctly generated');
|
$this->assertContains($neededPart, $imageFilename, 'Filename for cached image is correctly generated');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +295,7 @@ class ImageTest extends SapphireTest {
|
|||||||
$image = $this->objFromFixture('Image', 'imageWithoutTitle');
|
$image = $this->objFromFixture('Image', 'imageWithoutTitle');
|
||||||
$folder = new SS_FileFinder();
|
$folder = new SS_FileFinder();
|
||||||
|
|
||||||
$imageFirst = $image->SetSize(200,200);
|
$imageFirst = $image->Pad(200,200);
|
||||||
$this->assertNotNull($imageFirst);
|
$this->assertNotNull($imageFirst);
|
||||||
$expected = 200;
|
$expected = 200;
|
||||||
$actual = $imageFirst->getWidth();
|
$actual = $imageFirst->getWidth();
|
||||||
@ -265,7 +308,7 @@ class ImageTest extends SapphireTest {
|
|||||||
$actual = $imageSecond->getHeight();
|
$actual = $imageSecond->getHeight();
|
||||||
$this->assertEquals($expected, $actual);
|
$this->assertEquals($expected, $actual);
|
||||||
|
|
||||||
$imageThird = $imageSecond->PaddedImage(600,600,'0F0F0F');
|
$imageThird = $imageSecond->Pad(600,600,'0F0F0F');
|
||||||
// Encoding of the arguments is duplicated from cacheFilename
|
// Encoding of the arguments is duplicated from cacheFilename
|
||||||
$argumentString = base64_encode(json_encode(array(600,600,'0F0F0F')));
|
$argumentString = base64_encode(json_encode(array(600,600,'0F0F0F')));
|
||||||
$this->assertNotNull($imageThird);
|
$this->assertNotNull($imageThird);
|
||||||
@ -289,7 +332,7 @@ class ImageTest extends SapphireTest {
|
|||||||
|
|
||||||
public function testRegenerateImages() {
|
public function testRegenerateImages() {
|
||||||
$image = $this->objFromFixture('Image', 'imageWithMetacharacters');
|
$image = $this->objFromFixture('Image', 'imageWithMetacharacters');
|
||||||
$image_generated = $image->SetWidth(200);
|
$image_generated = $image->ScaleWidth(200);
|
||||||
$p = $image_generated->getFullPath();
|
$p = $image_generated->getFullPath();
|
||||||
$this->assertTrue(file_exists($p), 'Resized image exists after creation call');
|
$this->assertTrue(file_exists($p), 'Resized image exists after creation call');
|
||||||
$this->assertEquals(1, $image->regenerateFormattedImages(), 'Cached images were regenerated correct');
|
$this->assertEquals(1, $image->regenerateFormattedImages(), 'Cached images were regenerated correct');
|
||||||
@ -298,9 +341,13 @@ class ImageTest extends SapphireTest {
|
|||||||
$this->assertTrue(file_exists($p), 'Resized image exists after regeneration call');
|
$this->assertTrue(file_exists($p), 'Resized image exists after regeneration call');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that cached images are regenerated properly after a cached file is renamed with new arguments
|
||||||
|
* ToDo: This doesn't seem like something that is worth testing - what is the point of this?
|
||||||
|
*/
|
||||||
public function testRegenerateImagesWithRenaming() {
|
public function testRegenerateImagesWithRenaming() {
|
||||||
$image = $this->objFromFixture('Image', 'imageWithMetacharacters');
|
$image = $this->objFromFixture('Image', 'imageWithMetacharacters');
|
||||||
$image_generated = $image->SetWidth(200);
|
$image_generated = $image->ScaleWidth(200);
|
||||||
$p = $image_generated->getFullPath();
|
$p = $image_generated->getFullPath();
|
||||||
$this->assertTrue(file_exists($p), 'Resized image exists after creation call');
|
$this->assertTrue(file_exists($p), 'Resized image exists after creation call');
|
||||||
|
|
||||||
@ -311,8 +358,8 @@ class ImageTest extends SapphireTest {
|
|||||||
$newPath = str_replace($oldArgumentString, $newArgumentString, $p);
|
$newPath = str_replace($oldArgumentString, $newArgumentString, $p);
|
||||||
$newRelative = str_replace($oldArgumentString, $newArgumentString, $image_generated->getFileName());
|
$newRelative = str_replace($oldArgumentString, $newArgumentString, $image_generated->getFileName());
|
||||||
rename($p, $newPath);
|
rename($p, $newPath);
|
||||||
$this->assertFalse(file_exists($p), 'Resized image does not exist after movement call under old name');
|
$this->assertFalse(file_exists($p), 'Resized image does not exist at old path after renaming');
|
||||||
$this->assertTrue(file_exists($newPath), 'Resized image exists after movement call under new name');
|
$this->assertTrue(file_exists($newPath), 'Resized image exists at new path after renaming');
|
||||||
$this->assertEquals(1, $image->regenerateFormattedImages(),
|
$this->assertEquals(1, $image->regenerateFormattedImages(),
|
||||||
'Cached images were regenerated in the right number');
|
'Cached images were regenerated in the right number');
|
||||||
|
|
||||||
@ -322,7 +369,7 @@ class ImageTest extends SapphireTest {
|
|||||||
|
|
||||||
public function testGeneratedImageDeletion() {
|
public function testGeneratedImageDeletion() {
|
||||||
$image = $this->objFromFixture('Image', 'imageWithMetacharacters');
|
$image = $this->objFromFixture('Image', 'imageWithMetacharacters');
|
||||||
$image_generated = $image->SetWidth(200);
|
$image_generated = $image->ScaleWidth(200);
|
||||||
$p = $image_generated->getFullPath();
|
$p = $image_generated->getFullPath();
|
||||||
$this->assertTrue(file_exists($p), 'Resized image exists after creation call');
|
$this->assertTrue(file_exists($p), 'Resized image exists after creation call');
|
||||||
$numDeleted = $image->deleteFormattedImages();
|
$numDeleted = $image->deleteFormattedImages();
|
||||||
@ -336,11 +383,11 @@ class ImageTest extends SapphireTest {
|
|||||||
public function testMultipleGenerateManipulationCallsImageDeletion() {
|
public function testMultipleGenerateManipulationCallsImageDeletion() {
|
||||||
$image = $this->objFromFixture('Image', 'imageWithMetacharacters');
|
$image = $this->objFromFixture('Image', 'imageWithMetacharacters');
|
||||||
|
|
||||||
$firstImage = $image->SetWidth(200);
|
$firstImage = $image->ScaleWidth(200);
|
||||||
$firstImagePath = $firstImage->getFullPath();
|
$firstImagePath = $firstImage->getFullPath();
|
||||||
$this->assertTrue(file_exists($firstImagePath));
|
$this->assertTrue(file_exists($firstImagePath));
|
||||||
|
|
||||||
$secondImage = $firstImage->SetHeight(100);
|
$secondImage = $firstImage->ScaleHeight(100);
|
||||||
$secondImagePath = $secondImage->getFullPath();
|
$secondImagePath = $secondImage->getFullPath();
|
||||||
$this->assertTrue(file_exists($secondImagePath));
|
$this->assertTrue(file_exists($secondImagePath));
|
||||||
|
|
||||||
@ -354,11 +401,11 @@ class ImageTest extends SapphireTest {
|
|||||||
*/
|
*/
|
||||||
public function testPathPropertiesCachedImage() {
|
public function testPathPropertiesCachedImage() {
|
||||||
$image = $this->objFromFixture('Image', 'imageWithMetacharacters');
|
$image = $this->objFromFixture('Image', 'imageWithMetacharacters');
|
||||||
$firstImage = $image->SetWidth(200);
|
$firstImage = $image->ScaleWidth(200);
|
||||||
$firstImagePath = $firstImage->getRelativePath();
|
$firstImagePath = $firstImage->getRelativePath();
|
||||||
$this->assertEquals($firstImagePath, $firstImage->Filename);
|
$this->assertEquals($firstImagePath, $firstImage->Filename);
|
||||||
|
|
||||||
$secondImage = $firstImage->SetHeight(100);
|
$secondImage = $firstImage->ScaleHeight(100);
|
||||||
$secondImagePath = $secondImage->getRelativePath();
|
$secondImagePath = $secondImage->getRelativePath();
|
||||||
$this->assertEquals($secondImagePath, $secondImage->Filename);
|
$this->assertEquals($secondImagePath, $secondImage->Filename);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
Folder:
|
Folder:
|
||||||
folder1:
|
folder1:
|
||||||
Filename: assets/ImageTest
|
Filename: assets/ImageTest/
|
||||||
Image:
|
Image:
|
||||||
imageWithTitle:
|
imageWithTitle:
|
||||||
Title: This is a image Title
|
Title: This is a image Title
|
||||||
@ -16,3 +16,11 @@ Image:
|
|||||||
Title: This is a/an image Title
|
Title: This is a/an image Title
|
||||||
Filename: assets/ImageTest/test_image.png
|
Filename: assets/ImageTest/test_image.png
|
||||||
Parent: =>Folder.folder1
|
Parent: =>Folder.folder1
|
||||||
|
lowQualityJPEG:
|
||||||
|
Title: This is a low quality JPEG
|
||||||
|
Filename: assets/ImageTest/test_image_low-quality.jpg
|
||||||
|
Parent: =>Folder.folder1
|
||||||
|
highQualityJPEG:
|
||||||
|
Title: This is a high quality JPEG
|
||||||
|
Filename: assets/ImageTest/test_image_high-quality.jpg
|
||||||
|
Parent: =>Folder.folder1
|
@ -8,22 +8,8 @@ class ImagickImageTest extends ImageTest {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
Image::set_backend("ImagickBackend");
|
Image::set_backend("ImagickBackend");
|
||||||
|
|
||||||
// Create a test files for each of the fixture references
|
parent::setUp();
|
||||||
$fileIDs = $this->allFixtureIDs('Image');
|
|
||||||
foreach($fileIDs as $fileID) {
|
|
||||||
$file = DataObject::get_by_id('Image', $fileID);
|
|
||||||
|
|
||||||
$image = new Imagick();
|
|
||||||
|
|
||||||
$image->newImage(300,300, new ImagickPixel("white"));
|
|
||||||
$image->setImageFormat("png");
|
|
||||||
$image->writeImage(BASE_PATH."/{$file->Filename}");
|
|
||||||
|
|
||||||
$file->write();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 5.8 KiB |
BIN
tests/model/testimages/test_image_high-quality.jpg
Normal file
After Width: | Height: | Size: 148 KiB |
BIN
tests/model/testimages/test_image_low-quality.jpg
Normal file
After Width: | Height: | Size: 12 KiB |