Upgrade to KH 3.3.0
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
# Examples
|
||||
|
||||
The following are mini applications that uses the [Image] module. They are very straight forward and did not include additional code such as validations and the like. They are designed to be simple and should work out of the box.
|
||||
|
||||
* [Uploading image](examples/upload)
|
||||
* [Cropping profile images](examples/crop)
|
||||
* [Serving images with dynamic dimension](examples/dynamic)
|
141
includes/kohana/modules/image/guide/image/examples/crop.md
Normal file
141
includes/kohana/modules/image/guide/image/examples/crop.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# Crop Profile Image
|
||||
|
||||
This example is very similar to our previous example and even uses the same upload logics. The only difference is that the uploaded image is cropped to square from the center whose dimension is half the original height of the image.
|
||||
|
||||
## Controller
|
||||
|
||||
We name our new controller as `Controller_Crop` and accessible through `/crop` URL. Assuming that your project is located at [http://localhost/kohana](http://localhost/kohana), then our crop controller is at [http://localhost/kohana/crop](http://localhost/kohana/crop).
|
||||
|
||||
~~~
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Controller_Crop extends Controller {
|
||||
|
||||
public function action_index()
|
||||
{
|
||||
$view = View::factory('crop/index');
|
||||
$this->response->body($view);
|
||||
}
|
||||
|
||||
public function action_do()
|
||||
{
|
||||
$view = View::factory('crop/do');
|
||||
$error_message = NULL;
|
||||
$filename = NULL;
|
||||
|
||||
if ($this->request->method() == Request::POST)
|
||||
{
|
||||
if (isset($_FILES['avatar']))
|
||||
{
|
||||
$filename = $this->_save_image($_FILES['avatar']);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $filename)
|
||||
{
|
||||
$error_message = 'There was a problem while uploading the image.
|
||||
Make sure it is uploaded and must be JPG/PNG/GIF file.';
|
||||
}
|
||||
|
||||
$view->uploaded_file = $filename;
|
||||
$view->error_message = $error_message;
|
||||
$this->response->body($view);
|
||||
}
|
||||
|
||||
protected function _save_image($image)
|
||||
{
|
||||
if (
|
||||
! Upload::valid($image) OR
|
||||
! Upload::not_empty($image) OR
|
||||
! Upload::type($image, array('jpg', 'jpeg', 'png', 'gif')))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$directory = DOCROOT.'uploads/';
|
||||
|
||||
if ($file = Upload::save($image, NULL, $directory))
|
||||
{
|
||||
$filename = strtolower(Text::random('alnum', 20)).'.jpg';
|
||||
|
||||
$img = Image::factory($file);
|
||||
|
||||
// Crop the image square half the height and crop from center
|
||||
$new_height = (int) $img->height / 2;
|
||||
|
||||
$img->crop($new_height, $new_height)
|
||||
->save($directory.$filename);
|
||||
|
||||
// Delete the temporary file
|
||||
unlink($file);
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
~~~
|
||||
|
||||
The `index` action displays the upload form whereas the `do` action will process the uploaded image and provides feedback to the user.
|
||||
|
||||
In `do` action, it checks if the request method was `POST`, then delegates the process to `_save_image()` method which in turn performs various checks and finally crops and saves the image to the `uploads` directory.
|
||||
|
||||
## Views
|
||||
|
||||
For the upload form (the `index` action), the view is located at `views/crop/index.php`.
|
||||
|
||||
~~~
|
||||
<html>
|
||||
<head>
|
||||
<title>Upload Profile Image</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Upload your profile image</h1>
|
||||
<form id="upload-form" action="<?php echo URL::site('crop/do') ?>" method="post" enctype="multipart/form-data">
|
||||
<p>Choose file:</p>
|
||||
<p><input type="file" name="avatar" id="avatar" /></p>
|
||||
<p><input type="submit" name="submit" id="submit" value="Upload and crop" /></p>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
~~~
|
||||
|
||||
View for `crop/do` action goes to `views/crop/do.php`.
|
||||
|
||||
~~~
|
||||
<html>
|
||||
<head>
|
||||
<title>Upload Profile Image Result</title>
|
||||
</head>
|
||||
<body>
|
||||
<?php if ($uploaded_file): ?>
|
||||
<h1>Upload success</h1>
|
||||
<p>
|
||||
Here is your uploaded and cropped avatar:
|
||||
<img src="<?php echo URL::site("/uploads/$uploaded_file") ?>" alt="Uploaded avatar" />
|
||||
</p>
|
||||
<?php else: ?>
|
||||
<h1>Something went wrong with the upload</h1>
|
||||
<p><?php echo $error_message ?></p>
|
||||
<?php endif ?>
|
||||
</body>
|
||||
</html>
|
||||
~~~
|
||||
|
||||
## Screenshots
|
||||
|
||||
Below are screenshots for this example.
|
||||
|
||||

|
||||
|
||||
_Original image to upload_
|
||||
|
||||

|
||||
|
||||
_Upload image form_
|
||||
|
||||

|
||||
|
||||
_Upload result form_
|
108
includes/kohana/modules/image/guide/image/examples/dynamic.md
Normal file
108
includes/kohana/modules/image/guide/image/examples/dynamic.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# Dynamic Image Controller
|
||||
|
||||
In this example, we have images under `/uploads` under the webroot directory. We allow the user to render any image with dynamic dimension and is resized on the fly. It also caches the response for 1 hour to show basic caching mechanism.
|
||||
|
||||
## Route
|
||||
|
||||
First, we need a [Route]. This [Route] is based on this URL pattern:
|
||||
|
||||
`/imagefly/filename/width/height` - where filename is the name of the image without the extension. This assumes that all images are in `jpg` and all filenames uses numbers, letters, dash and underscores only.
|
||||
|
||||
This is our [Route] definition:
|
||||
|
||||
~~~
|
||||
/**
|
||||
* Set route for image fly
|
||||
*/
|
||||
Route::set('imagefly', 'imagefly/<image>/<width>/<height>', array('image' => '[-09a-zA-Z_]+', 'width' => '[0-9]+', 'height' => '[0-9]+'))
|
||||
->defaults(array(
|
||||
'controller' => 'imagefly',
|
||||
'action' => 'index'
|
||||
));
|
||||
~~~
|
||||
|
||||
We ensure that the filename is only composed of letters, numbers and underscores, width and height must be numeric.
|
||||
|
||||
## Controller
|
||||
|
||||
Our controller simply accepts the request and capture the following parameters as defined by the [Route]:
|
||||
|
||||
* `filename` - without the filename extension (and without dot)
|
||||
* `width`
|
||||
* `height`
|
||||
|
||||
Then it finds the image file and when found, render it on the browser. Additional features added are browser caching.
|
||||
|
||||
~~~
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Controller_Imagefly extends Controller {
|
||||
|
||||
public function action_index()
|
||||
{
|
||||
$file = $this->request->param('image');
|
||||
$width = (int) $this->request->param('width');
|
||||
$height = (int) $this->request->param('height');
|
||||
|
||||
$rendered = FALSE;
|
||||
if ($file AND $width AND $height)
|
||||
{
|
||||
$filename = DOCROOT.'uploads/'.$file.'.jpg';
|
||||
|
||||
if (is_file($filename))
|
||||
{
|
||||
$this->_render_image($filename, $width, $height);
|
||||
$rendered = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $rendered)
|
||||
{
|
||||
$this->response->status(404);
|
||||
}
|
||||
}
|
||||
|
||||
protected function _render_image($filename, $width, $height)
|
||||
{
|
||||
// Calculate ETag from original file padded with the dimension specs
|
||||
$etag_sum = md5(base64_encode(file_get_contents($filename)).$width.','.$height);
|
||||
|
||||
// Render as image and cache for 1 hour
|
||||
$this->response->headers('Content-Type', 'image/jpeg')
|
||||
->headers('Cache-Control', 'max-age='.Date::HOUR.', public, must-revalidate')
|
||||
->headers('Expires', gmdate('D, d M Y H:i:s', time() + Date::HOUR).' GMT')
|
||||
->headers('Last-Modified', date('r', filemtime($filename)))
|
||||
->headers('ETag', $etag_sum);
|
||||
|
||||
if (
|
||||
$this->request->headers('if-none-match') AND
|
||||
(string) $this->request->headers('if-none-match') === $etag_sum)
|
||||
{
|
||||
$this->response->status(304)
|
||||
->headers('Content-Length', '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = Image::factory($filename)
|
||||
->resize($width, $height)
|
||||
->render('jpg');
|
||||
|
||||
$this->response->body($result);
|
||||
}
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
When the parameters are invalid or the filename does not exists, it simply returns 404 not found error.
|
||||
|
||||
The rendering of image uses some caching mechanism. One by setting the max age and expire headers and second by using etags.
|
||||
|
||||
## Screenshots
|
||||
|
||||
Visiting [http://localhost/kohana/imagefly/kitteh/400/400](http://localhost/kohana/imagefly/kitteh/400/400) yields:
|
||||
|
||||

|
||||
|
||||
Visiting [http://localhost/kohana/imagefly/kitteh/600/500](http://localhost/kohana/imagefly/kitteh/600/500) yields:
|
||||
|
||||

|
139
includes/kohana/modules/image/guide/image/examples/upload.md
Normal file
139
includes/kohana/modules/image/guide/image/examples/upload.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# Upload Image
|
||||
|
||||
The following example shows how to handle uploading of an image, resize it and save it to a file. Be sure you have enabled the [Image] module as discussed in getting started guide.
|
||||
|
||||
Assuming you are creating a web application that allows your members to upload their profile picture (avatar), the steps below explains it how.
|
||||
|
||||
## Controller
|
||||
|
||||
First we need to create a controller that handles the requests for uploading an image. We will name it `Controller_Avatar` and accessible through `/avatar` URL. Assuming that your project is located at [http://localhost/kohana](http://localhost/kohana), then our avatar controller is at [http://localhost/kohana/avatar](http://localhost/kohana/avatar).
|
||||
|
||||
For simplicity, the upload form will be on `index` action and `upload` action will process the uploaded file. This is what our controller now looks like. Please note that we are not using [Controller_Template], just [Controller].
|
||||
|
||||
~~~
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Controller_Avatar extends Controller {
|
||||
|
||||
public function action_index()
|
||||
{
|
||||
$view = View::factory('avatar/index');
|
||||
$this->response->body($view);
|
||||
}
|
||||
|
||||
public function action_upload()
|
||||
{
|
||||
$view = View::factory('avatar/upload');
|
||||
$error_message = NULL;
|
||||
$filename = NULL;
|
||||
|
||||
if ($this->request->method() == Request::POST)
|
||||
{
|
||||
if (isset($_FILES['avatar']))
|
||||
{
|
||||
$filename = $this->_save_image($_FILES['avatar']);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $filename)
|
||||
{
|
||||
$error_message = 'There was a problem while uploading the image.
|
||||
Make sure it is uploaded and must be JPG/PNG/GIF file.';
|
||||
}
|
||||
|
||||
$view->uploaded_file = $filename;
|
||||
$view->error_message = $error_message;
|
||||
$this->response->body($view);
|
||||
}
|
||||
|
||||
protected function _save_image($image)
|
||||
{
|
||||
if (
|
||||
! Upload::valid($image) OR
|
||||
! Upload::not_empty($image) OR
|
||||
! Upload::type($image, array('jpg', 'jpeg', 'png', 'gif')))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$directory = DOCROOT.'uploads/';
|
||||
|
||||
if ($file = Upload::save($image, NULL, $directory))
|
||||
{
|
||||
$filename = strtolower(Text::random('alnum', 20)).'.jpg';
|
||||
|
||||
Image::factory($file)
|
||||
->resize(200, 200, Image::AUTO)
|
||||
->save($directory.$filename);
|
||||
|
||||
// Delete the temporary file
|
||||
unlink($file);
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
~~~
|
||||
|
||||
We have `index` and `upload` actions. `index` action will display the upload form and `upload` action will process the uploaded image and provides feedback to the user.
|
||||
|
||||
In `upload` action, it checks if the request method was `POST`, then delegates the process to `_save_image()` method which in turn performs various checks and finally resize and save the image to the `uploads` directory.
|
||||
|
||||
## Views
|
||||
|
||||
For the upload form (the `index` action), the view is located at `views/avatar/index.php`.
|
||||
|
||||
~~~
|
||||
<html>
|
||||
<head>
|
||||
<title>Upload Avatar</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Upload your avatar</h1>
|
||||
<form id="upload-form" action="<?php echo URL::site('avatar/upload') ?>" method="post" enctype="multipart/form-data">
|
||||
<p>Choose file:</p>
|
||||
<p><input type="file" name="avatar" id="avatar" /></p>
|
||||
<p><input type="submit" name="submit" id="submit" value="Upload" /></p>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
~~~
|
||||
|
||||
Take note of the action attribute. It points to our `avatar/upload` action whose view code goes to `views/avatar/upload.php`.
|
||||
|
||||
~~~
|
||||
<html>
|
||||
<head>
|
||||
<title>Upload Avatar Result</title>
|
||||
</head>
|
||||
<body>
|
||||
<?php if ($uploaded_file): ?>
|
||||
<h1>Upload success</h1>
|
||||
<p>
|
||||
Here is your uploaded avatar:
|
||||
<img src="<?php echo URL::site("/uploads/$uploaded_file") ?>" alt="Uploaded avatar" />
|
||||
</p>
|
||||
<?php else: ?>
|
||||
<h1>Something went wrong with the upload</h1>
|
||||
<p><?php echo $error_message ?></p>
|
||||
<?php endif ?>
|
||||
</body>
|
||||
</html>
|
||||
~~~
|
||||
|
||||
When the upload is successfull, a success message is displayed with the uploaded image displayed. Otherwise, when it fails, it displays an error message.
|
||||
|
||||
## Screenshots
|
||||
|
||||
Below are screenshots for this example.
|
||||
|
||||

|
||||
|
||||
_Upload image form_
|
||||
|
||||

|
||||
|
||||
_Upload result form_
|
@@ -0,0 +1,21 @@
|
||||
# Image
|
||||
|
||||
Kohana 3.x provides a simple yet powerful image manipulation module. The [Image] module provides features that allows your application to resize images, crop, rotate, flip and many more.
|
||||
|
||||
## Drivers
|
||||
|
||||
[Image] module ships with [Image_GD] driver which requires `GD` extension enabled in your PHP installation. This is the default driver. Additional drivers can be created by extending the [Image] class.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Before using the image module, we must enable it first on `APPPATH/bootstrap.php`:
|
||||
|
||||
~~~
|
||||
Kohana::modules(array(
|
||||
...
|
||||
'image' => MODPATH.'image', // Image manipulation
|
||||
...
|
||||
));
|
||||
~~~
|
||||
|
||||
Next: [Using the image module](using).
|
@@ -1,3 +1,6 @@
|
||||
## [Image]()
|
||||
- [Using](using)
|
||||
- [Examples](examples)
|
||||
- [Examples](examples)
|
||||
- [Upload Image](examples/upload)
|
||||
- [Crop Profile Image](examples/crop)
|
||||
- [Dynamic Image Controller](examples/dynamic)
|
@@ -0,0 +1,112 @@
|
||||
# Basic Usage
|
||||
|
||||
Shown here are the basic usage of this module. For full documentation about the image module usage, visit the [Image] api browser.
|
||||
|
||||
## Creating Instance
|
||||
|
||||
[Image::factory()] creates an instance of the image object and prepares it for manipulation. It accepts the `filename` as an arguement and an optional `driver` parameter. When `driver` is not specified, the default driver `GD` is used.
|
||||
|
||||
~~~
|
||||
// Uses the image from upload directory
|
||||
$img = Image::factory(DOCROOT.'uploads/sample-image.jpg');
|
||||
~~~
|
||||
|
||||
Once an instance is created, you can now manipulate the image by using the following instance methods.
|
||||
|
||||
## Resize
|
||||
|
||||
Resize the image to the given size. Either the width or the height can be omitted and the image will be resized proportionally.
|
||||
|
||||
Using the image object above, we can resize our image to say 150x150 pixels with automatic scaling using the code below:
|
||||
|
||||
~~~
|
||||
$img->resize(150, 150, Image::AUTO);
|
||||
~~~
|
||||
|
||||
The parameters are `width`, `height` and `master` dimension respectively. With `AUTO` master dimension, the image is resized by either width or height depending on which is closer to the specified dimension.
|
||||
|
||||
Other examples:
|
||||
|
||||
~~~
|
||||
// Resize to 200 pixels on the shortest side
|
||||
$img->resize(200, 200);
|
||||
|
||||
// Resize to 200x200 pixels, keeping aspect ratio
|
||||
$img->resize(200, 200, Image::INVERSE);
|
||||
|
||||
// Resize to 500 pixel width, keeping aspect ratio
|
||||
$img->resize(500, NULL);
|
||||
|
||||
// Resize to 500 pixel height, keeping aspect ratio
|
||||
$img->resize(NULL, 500);
|
||||
|
||||
// Resize to 200x500 pixels, ignoring aspect ratio
|
||||
$img->resize(200, 500, Image::NONE);
|
||||
~~~
|
||||
|
||||
## Render
|
||||
|
||||
You can render the image object directly to the browser using the [Image::render()] method.
|
||||
|
||||
~~~
|
||||
$img = Image::factory(DOCROOT.'uploads/colorado-farm-1920x1200.jpg');
|
||||
|
||||
header('Content-Type: image/jpeg');
|
||||
|
||||
echo $img->resize(300, 300)
|
||||
->render();
|
||||
~~~
|
||||
|
||||
What it did is resize a 1920x1200 wallpaper image into 300x300 proportionally and render it to the browser. If you are trying to render the image in a controller action, you can do instead:
|
||||
|
||||
~~~
|
||||
$img = Image::factory(DOCROOT.'uploads/colorado-farm-1920x1200.jpg');
|
||||
|
||||
$this->response->headers('Content-Type', 'image/jpg');
|
||||
|
||||
$this->response->body(
|
||||
$img->resize(300, 300)
|
||||
->render()
|
||||
);
|
||||
~~~
|
||||
|
||||
[Image::render()] method also allows you to specify the type and quality of the rendered image.
|
||||
|
||||
~~~
|
||||
// Render the image at 50% quality
|
||||
$img->render(NULL, 50);
|
||||
|
||||
// Render the image as a PNG
|
||||
$img->render('png');
|
||||
~~~
|
||||
|
||||
## Save To File
|
||||
|
||||
[Image::save()] let's you save the image object to a file. It has two parameters: `filename` and `quality`. If `filename` is omitted, the original file used will be overwritten instead. The `quality` parameter is an integer from 1-100 which indicates the quality of image to save which defaults to 100.
|
||||
|
||||
On our example above, instead of rendering the file to the browser, you may want to save it somewhere instead. To do so, you may:
|
||||
|
||||
~~~
|
||||
$img = Image::factory(DOCROOT.'uploads/colorado-farm-1920x1200.jpg');
|
||||
|
||||
$filename = DOCROOT.'uploads/img-'.uniqid().'.jpg';
|
||||
|
||||
$img->resize(300, 300)
|
||||
->save($filename, 80);
|
||||
~~~
|
||||
|
||||
What we do is resize the image and save it to file reducing quality to 80% and save it to the upload directory using a unique filename.
|
||||
|
||||
## Other Methods
|
||||
|
||||
There are more methods available for the [Image] module which provides powerfull features that are best describe in the API documentation. Here are some of them:
|
||||
|
||||
* [Image::background()] - Set the background color of an image.
|
||||
* [Image::crop()] - Crop an image to the given size.
|
||||
* [Image::flip()] - Flip the image along the horizontal or vertical axis.
|
||||
* [Image::reflection()] - Add a reflection to an image.
|
||||
* [Image::rotate()] - Rotate the image by a given amount.
|
||||
* [Image::sharpen()] - Sharpen the image by a given amount.
|
||||
* [Image::watermark()] - Add a watermark to an image with a specified opacity.
|
||||
|
||||
Next: [Examples](examples)
|
Reference in New Issue
Block a user