Images
Jalno provides the packages\base\Image class to developers for managing images. Some of this class's methods are defined as abstract, so the programmer cannot call them directly from this class. Currently, the packages\base\Image\GD class is derived from the Image class.
In the framework, a separate class has been created for the JPEG, GIF, PNG, and WEBP image formats, and all of the classes listed below inherit from the GD class.
| Class | Image Format |
|---|---|
packages\base\Image\GIF | GIF |
packages\base\Image\JPEG | JPEG |
packages\base\Image\PNG | PNG |
packages\base\Image\WEBP | WEBP |
Creating an Object
An object of the Image class can be used either to create a new image or to modify an existing image. For each of these cases, the constructor's arguments are assigned differently.
Creating a New Image
When you intend to create a new image, you create an object from the format class you want to use for the image. The constructor takes three input arguments. The first argument is the image width, the second argument is the height, and the third argument is the image's background color, where the third argument must be of the Color class. Image dimensions are in px.
Programmers should note that the created image is not saved (no file is created for it) until the saveToFile() method is called, and it is only available to the programmer.
In the examples below, an image with a width of 200px, a height of 150px, and a black background is created in the specified format.
use packages\base\Image;
// Create an image in JPEG format
$image = new Image\JPEG(200, 150, Image\Color::fromRGB(0, 0, 0));
// Create an image in PNG format
$image = new Image\PNG(200, 150, Image\Color::fromRGB(0, 0, 0));
// Create an image in GIF format
$image = new Image\GIF(200, 150, Image\Color::fromRGB(0, 0, 0));
// Create an image in WEBP format
$image = new Image\WEBP(200, 150, Image\Color::fromRGB(0, 0, 0));
An Existing File or Image
When you intend to work on an existing image, you create an object from the image format class. The constructor takes one input argument, which is an object of the file class or of the Image class.
The specified file must exist; if the file does not exist, a NotFoundException is thrown.
If the object created from the file class refers to an image in jpeg format but an object is created from the Image\PNG class, you will receive a warning.
Example of incorrect code:
use packages\base\Image;
$file = new File\Local("packages/packagename/storage/images/image.jpg");
$image = new Image\PNG($file);
Output
Warning: imagecreatefrompng(): 'packages/packagename/storage/images/image.jpg' is not a valid PNG file
Example of correct code:
use packages\base\Image;
$image = new Image\JPEG(new File\Local("packages/packagename/storage/images/image.jpeg"));
$image = new Image\PNG(new File\Local("packages/packagename/storage/images/image.png"));
$image = new Image\GIF(new File\Local("packages/packagename/storage/images/image.gif"));
$image = new Image\WEBP(new File\Local("packages/packagename/storage/images/image.webp"));
Methods
The following methods have been created for working with images, and you can call them on all of the classes above.
| Method | Purpose |
|---|---|
saveToFile(File $file, int $quality) | Save the image to a specified location |
save(int $quality) | Save the image |
getFile() | For images that have been saved or created from a file, returns an object of the File class |
getWidth() | Read the image width |
getHeight() | Read the image height |
getExtension() | Read the image format |
resize(int $width, int $height) | Change the image dimensions |
resizeToHeight(int $height) | Change the image height |
resizeToWidth(int $width) | Change the image width |
scale(int $scale) | Zoom the image |
colorAt(int $x, int $y) | Read the color of a specific pixel of the image |
setColorAt(int $x, int $y, Image\Color $color) | Color a specific pixel |
paste(Image $image, int $x, int $y) | Paste content into a part of the image |
copy(int $x, int $y, int $width, $height) | Copy a part of the image |
rotate(float $angle, Image\Color $bg) | Rotate the image |
fromFormat(File $file) | Convert a file object to an image class object based on format |
fromContent(File $file) | Convert a file object to an image class object based on content |
Saving an Image
The data sent from the user's side may be an image; to save the received image, you must also use the methods of the image class.
The saveToFile and save methods are used to save images.
The save method is used to save an existing image and stores the changes in that same previous image. The save method takes no input arguments.
The saveToFile method saves the image to a new location. Its input argument is an object of the File class.
If the file object points to a file that already exists, the new file replaces the previous file.
Example
namespace packages\packagename\controllers;
use theme\theme_name\views;
use packages\packagename\User;
use packages\base\{Image, IO\File, Packages, View, Http};
class profile extends controller {
public function update($data) {
$user = User::byId($data['id']);
if (!$user) {
throw new NotFound;
}
$view = View::byName(views\profile\Update::class);
$this->response->setView($view);
if (Http::is_post()) {
$inputs = array(
'name' => array(
'type' => 'string'
),
'lastname' => array(
'type' => 'string'
),
'avatar' => array(
'optional' => true,
'empty' => true,
'type' => 'image'
)
);
$formdata = $this->checkinputs($inputs);
if (isset($formdata['avatar'])) {
$formdata['avatar'] = $formdata['avatar']->resize(200, 200);
$path = 'storage/public_avatar/' . $formdata['avatar']->getFile()->md5() . '.' . $formdata['avatar']->getExtension();
$avatar = Packages::package('packagename')->getFile($path);
$directory = $avatar->getDirectory();
if (!$directory->exists()) {
$directory->make(true);
}
$formdata['avatar']->saveToFile($avatar);
$formdata['avatar'] = $path;
}
$user->avatar = $formdata['avatar'];
$user->name = $formdata['name'];
$user->lastname = $formdata['lastname'];
$user->save();
}
return $this->response;
}
}
Drawing an Image
Using the setColorAt method, you can draw an image. The method works by taking a pixel's coordinates and coloring that pixel according to the specified color. In fact, to draw an image you need to proceed pixel by pixel.
The setColorAt method takes three input arguments: the first argument is the pixel's position on the x-axis and the second argument is the pixel's position on the y-axis; the third argument is the desired color of the Color class.
In the example below, we intend to draw a cross on the image.
Example 1
namespace packages\packagename\controllers;
use packages\base\{Image, IO\File, Packages};
class Drawing extends controller {
public function closeSign() {
$image = new Image\PNG(100, 100, Image\Color::fromRGB(255, 255, 255));
$yellow = Image\Color::fromRGB(248, 195, 13);
for ($i = 1; $i < 100; $i++) {
$image->setColorAt($i, $i, $yellow);
$image->setColorAt($i, 100 - $i, $yellow);
}
$file = Packages::package("packagename")->getFile("images/closeSign.png");
$image->saveToFile($file);
$this->response->setStatus(true);
return $this->response;
}
}
In the example above, we first create an image in png format with dimensions 100px * 100px. Then, in the for loop, we specify the coordinates of the pixels. For example, when $i = 4:
$image->setColorAt(4, 96, $yellow): the pixel whose x is 4 and y is 96 turns yellow.
The image created by the code above is as follows:
Reading a Pixel's Color
The colorAt method also returns the color of the specified pixel. The output of this method is of the Color class.
The colorAt method takes two input arguments: the first argument is the pixel's position on the x-axis and the second argument is the pixel's position on the y-axis.
Example 2
$image = new Image\PNG(new File\Local("packages/packagename/images/closeSign.png"));
$color = $image->colorAt(4, 96);
/**
* $color :
* packages\base\Image\Color Object
* (
* [r:packages\base\Image\Color:private] => 248
* [g:packages\base\Image\Color:private] => 195
* [b:packages\base\Image\Color:private] => 13
* [a:packages\base\Image\Color:private] => 1
* )
*/
If we consider $image to be the image created in Example 1, then the $color variable stores an object of the Color class that represents the yellow color code.
Copying a Part of an Image
Using the copy method, you can copy a part of an image. To specify the part you want to copy, you must specify the coordinates of a pixel and the width and height of that part. The copy method takes four input arguments: the first argument is the pixel's position on the x-axis, the second argument is the pixel's position on the y-axis, the third argument is the width, and the fourth argument is the height of that part.
The specified part, in fact, starting from the pixel whose coordinates are specified, includes the number of pixels of the width to the right and the number of pixels of the height downward.
By calling the paste method, you can place an image within your image. The paste method takes four input arguments: the first argument is the image you want to place, the second argument is the pixel's position on the x-axis, and the third argument is the pixel's position on the y-axis. The fourth argument specifies the image's transparency percentage, which is a number between 0 and 1.
The position of the placed image is set, starting from the specified pixel, by the amount of its width to the right and the amount of its height downward, within the image.
The image transparency percentage is only taken into account for images in png format; for other formats it is always considered to be 1.
Example
namespace packages\packagename\controllers;
use packages\base\{Image, IO\File, Packages};
class Drawing extends controller {
public function square() {
$image = new Image\JPEG(200, 200, Image\Color::fromRGB(255, 255, 255));
$red = Image\Color::fromRGB(255, 0, 0);
for ($i = 51; $i < 151; $i++) {
for ($j = 51; $j < 151; $j++) {
$image->setColorAt($i, $j, $red);
}
}
$image->saveToFile(new File\Local("packages/packagename/images/square.png"));
$partOfImage = $image->copy(51, 51, 100, 50);
$new = new Image\PNG(200, 200, Image\Color::fromRGB(0, 0, 0));
$new->paste($partOfImage, 50, 50, 0.5);
$new->saveToFile(new File\Local("packages/packagename/images/new_square.png"));
}
}
In the example above, a red square with dimensions 100px * 100px is created in the center of the image. Then, by calling the copy method, the upper part of the square is copied as a rectangle with dimensions 100px * 50px. A new image with a black background is created, and the copied rectangle is placed starting from the pixel with coordinates (50,50) with a transparency of 0.5.
The created images are as follows:
Resizing
The resize method has been created to change the size of an image. It takes two input arguments: the first argument is the width and the second argument is the height. In addition, the resizeToHeight and resizeToWidth methods have been created for changing the dimensions individually.
The output of the resize, resizeToHeight, and resizeToWidth methods is a new object of the Image class; therefore, to save it you must use the saveToFile method.
Example
namespace packages\packagename\controllers;
use packages\base\{Image, IO\File, Packages};
class Picture extends controller {
public function resizePic() {
$image = new Image\JPEG(new File\Local("packages/packagename/img.jpeg"));
$image->resize(150, 150)->saveToFile(new File\Local("packages/packagename/newImg.jpeg"));
$this->response->setStatus(true);
return $this->response;
}
public function resizeHeight() {
$image = new Image\JPEG(new File\Local("packages/packagename/img.jpeg"));
$image->resizeToHeight(200)->saveToFile(new File\Local("packages/packagename/newImg.jpeg"));
$this->response->setStatus(true);
return $this->response;
}
public function resizeWidth() {
$image = new Image\JPEG(new File\Local("packages/packagename/img.jpeg"));
$image->resizeToWidth(250)->saveToFile(new File\Local("packages/packagename/newImg.jpeg"));
$this->response->setStatus(true);
return $this->response;
}
}
Zooming an Image
Sometimes it is necessary to zoom an image and save it; for this purpose, the scale method has been created. The input of the scale method is an integer representing the zoom percentage of the image.
The output of the scale method is a new object of the Image class; therefore, to save it you must use the saveToFile method.
Example
namespace packages\packagename\controllers;
use packages\base\{Image, IO\File, Packages};
class Picture extends controller {
public function scale() {
$image = new Image\JPEG(new File\Local("packages/packagename/images/image.jpeg"));
$image->scale(5)->saveToFile(new File\Local("packages/packagename/images/newImage.jpeg"));
}
}
In the example above, the image is changed to 5% of its original size.
If you want the image size to be doubled, you must pass the number 200 to the scale method.
Rotating an Image
In the Image class, the rotate method has been created for rotating an image. This method takes two input arguments: the first argument is the rotation angle and the second argument is the background color for the new image.
The output of the rotate method is a new object of the Image class; therefore, to save it you must use the saveToFile method.
Example
namespace packages\packagename\controllers;
use packages\base\{Image, IO\File, Packages};
class Picture extends controller {
public function rotate() {
$image = new Image\PNG(new File\Local("packages/packagename/images/phpLogo.png"));
$image->rotate(180, Image\Color::fromRGB(0, 0, 0))->saveToFile(new File\Local("packages/packagename/images/newPhpLogo.png"));
$this->response->setStatus(true);
return $this->response;
}
}
The image created by the code above is as follows:

Converting a File Object to an Image Class Object
Sometimes it is necessary to convert an image that is an object of the File class into an object of the Image class; for this purpose, two methods, fromFormat and fromContent, have been created.
The input argument of both methods is an object of the File class. The difference between the methods lies in how the image format is detected.
The fromFormat method detects the image format according to the format of the specified file.
The fromContent method detects the image format according to the content of the specified file.
Example
use packages\base\Image;
$image = Image::fromContent(new File\Local("packages/packagename/images/img.png"));
// or
$image = Image::fromFormat(new File\Local("packages/packagename/images/img.png"));
/**
* packages\base\Image\PNG Object
* (
* [image:protected] => Resource id #1180
* [file:protected] => packages\base\IO\file\local Object
* (
* [directory] => packages/packagename/images
* [basename] => img.png
* )
*
* )
*/
Colors
When using the methods of the Image class to create a new image, draw an image, and so on, you need to specify the desired color to the method, where the methods' input is an object of the packages\base\Image\Color class.
Defining a Color
The fromRGB and fromRGBA methods are used to define a color. Colors are defined according to the R G B format. For ease of calling, the methods are defined as static.
In both the fromRGB and fromRGBA methods, the first argument is the red color code, the second argument is the green color code, and the third argument is the blue color code.
For the fromRGBA method, a fourth argument is defined, which is used to specify the color's opacity, a number between zero and one.
Each of the RGB color codes is a number between 0 and 255.
use packages\base\Image\Color;
$rgb = Color::fromRGB(17, 160, 234); // red:17 green:160 blue:234 => represents blue
$rgba = Color::fromRGBA(235, 185, 18, 0.2); // red:235 green:185 blue:18 alpha:0.2 => represents orange
Reading a Color
By calling the toRGB and toRGBA methods, you can obtain the defined color codes as an array. The array elements represent the red, green, and blue color codes, respectively.
The toRGBA method returns an array with four elements, where the fourth element specifies the color's opacity.
Color opacity only applies to images in PNG format.
The toRGB and toRGBA methods are not defined as static and must be called on an object of the Color class.
use packages\base\Image\Color;
$rgb = Color::fromRGB(17, 160, 234);
$rgb->toRGB();
/**
* Array
* (
* [0] => 17
* [1] => 160
* [2] => 234
* )
*/
$rgba = Color::fromRGBA(235, 185, 18, 0.2);
$rgba->toRGBA();
/**
* Array
* (
* [0] => 235
* [1] => 185
* [2] => 18
* [3] => 0.2
* )
*/