Working with images in PHP using GD. The Complete Guide to Uploading Images in PHP Php Image Library


Creation of an empty picture.

Syntax:

Int imageCreate (int x, int y)

Creates an empty picture of size x on the y points and returns its identifier. After the picture is created, all work with it is carried out precisely through this identifier, by analogy with how we work with a file through its descriptor.

Example:

Creating a new picture with GD and output it to the browser screen:

imageCreateFromPng

Create a picture from a PNG file.

Syntax:

Int imageCreateFromPng (string filename)

This function loads images from a PNG file into memory and returns its ID. As after the call imageCreate ()

Example:

An example of finding an error when opening a graphic file.

Function LoadPNG ($ imgname) ($ im = @imagecreatefrompng ($ imgname); / * Attempt to open * / if (! $ Im) (/ * See if it failed * / $ im = imagecreate (150, 30); / * Create a blank image * / $ bgc = imagecolorallocate ($ im, 255, 255, 255); $ tc = imagecolorallocate ($ im, 0, 0, 0); imagefilledrectangle ($ im, 0, 0, 150, 30, $ bgc); / * Output an errmsg * / imagestring ($ im, 1, 5, 5, "Error loading $ imgname", $ tc);) return $ im;)

imageCreateFromJpeg

Creates a picture from a JPEG file.

Syntax:

Int imageCreateFromJpeg (string filename)

imageCreate (), further work with the picture is possible only through this identifier. When loaded from disk, the image is unpacked and stored in memory in an unpacked format, so that you can perform various operations with it as quickly as possible, such as scaling, drawing lines, etc.

imageCreateFromGif

Create a picture from a GIF file.

Syntax:

Int imageCreateFromGif (string filename)

This function loads images from a file into memory and returns its ID. As after the call imageCreate (), further work with the picture is possible only through this identifier. When loaded from disk, the image is unpacked and stored in memory in an unpacked format, so that you can perform various operations with it as quickly as possible, such as scaling, drawing lines, etc.

It is worth mentioning that GD since version 1.6 does not support GIF format. Therefore, this function is practically not used.

imagePng

The function outputs the image in PNG format to any browser or file.

Syntax:

Int imagePng (int im [, string filename])

This function saves the image specified by its identifier and located in memory to disk, or outputs it to the browser.

imageCreate () im.

If the argument filename Content-type Header ().

Header ("Content-type: image / png") for PNG.

Example: An example of using the function imagepng ():

To save the alpha-channel of the original image, use the function imagesavealpha ():

imageJpeg

Send the JPEG image to the browser or save it to a file.

Syntax:

Int imageJPEG (int im [, string filename [, int quality]])

This function saves the image specified by its identifier and resides in memory to disk, or outputs it to the browser.

Of course, first the image must be loaded or created using the function imageCreate (), i.e. we need to know its identifier im.

If the argument filename omitted, then the compressed data in the appropriate format is output directly to the standard output stream, i.e. into the browser. Desired title Content-type at the same time it is not displayed, so you need to display it manually using Header ().

In fact, you must invoke one of three commands, depending on the type of image:

Header ("Content-type: image / jpeg") for Jpeg

Third optional parameter quality sets the image quality (from 0 to 100).

image2WBMP

Output image to browser or file.

Syntax:

Int image2WBMP (resource image [, string filename [, int threshold]])

The function displays the image specified by the handle image, to the browser, or to a file whose name is specified by an optional parameter filename.

If the image is displayed in the browser, you need to set its WBMP type as image / vnd.wap.wbmp using the function Header ():

Function image2WBMP () available PHP only if the library version GD 1.8 or lower.

imageGif

Send the GIF image to the browser or save it to a file.

Syntax:

Int imageGIF (int im [, string filename])

The functions save the image specified by its identifier and located in memory to disk, or output it to the browser.

Of course, first the image must be loaded or created using the function imageCreate (), i.e. we need to know its identifier im.

If the argument filename omitted, then the compressed data in the appropriate format is output directly to the standard output stream, i.e. into the browser. Desired title Content-type at the same time it is not displayed, so you need to display it manually using Header ().

In fact, you must invoke one of three commands, depending on the type of image:

Header ("Content-type: image / gif")

Because library GD since version 1.6 does not support GIF format, this function is rarely used.

imageCopy

Copying part of a drawing.

Syntax:

Int imageCopy (int dst_im, int src_im, int dst_x, int dst_y, int src_x, int src_y, int src_w, int src_h)

The function copies a rectangular area starting at position ( src_x, src_y) width src_w and height src_h from picture src_im in drawing dst_im by giving the copied area an offset ( dst_x, dst_y).

The following example will be a picture file1.png copied entirely in file2.png

imageCopyResized

Copying part of a drawing with scaling.

Syntax:

Int imageCopyResized (int dst_im, int src_im, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH)

This feature is one of the most powerful and versatile. With it, you can copy images (or portions of them), move or scale them.

dst_im sets the identifier of the image into which the result of the function will be placed. This image must have already been created or uploaded and sized properly.

src_im- the identifier of the image on which the work is being carried out. However, src_im and dst_im can be the same.

Parameters srcX, srcY, srcW, srcH set the area inside the original image, over which the operation will be performed - respectively, the coordinates of its upper left corner, width and height.

Finally, the four dstX, dstY, dstW, dstH specifies the location in the image dst_im, into which the rectangle specified in the previous four will be "squeezed". Note that if the width or height of the two rectangles do not match, then the picture will automatically be stretched or shrunk as needed.

In the following example, the file file1.jpg halved and written to a file file2.jp g:

imageDestroy

Destruction of the drawing.

Syntax:

Int imageDestroy (int im)

The function destroys the handle im a previously created picture (like closing a file fclose () after opening fopen ()).

Dear participants of the DvizhKod project! Another interesting topic awaits you today. We are all used to, say, uploading new avatars on social networks. But how do they scale to the correct size? What's happening on the server? Answers to these and many other questions are waiting for you under the cut.

Yes, if someone is not in the know, then in Internet terminology "cut" (from the English cut - cut) is a place that divides news into a short (in the general list) and full presentation.

Many people know that I am developing my own site management system called Cogear (Cogear, http://cogear.ru). The story is complex and long, but I stubbornly go towards the goal.

Let's take a look at the basic aspects of working with images.

PHP has a built-in GD library. Here is its documentation:

http://php.net/manual/ru/book.image.php

On this page you will find a huge number of very different functions. But don't be alarmed. We are interested in very specific ones.

As you can see, work with images so far happens in the form of procedures (functions), so you have to write the object-oriented shell yourself.

The simplest example of working with an image:

Trying it on a local machine.

Create a file image.php(I have a local domain for experiments test.local).

Place the image 1.jpg in the root of the test.local site folder:

We call http: //test.local/image.php in the browser (in your case, another address).

Find image 2.jpg in the folder:

The proportions have not been preserved, as you can see. Because we haven't counted them.

Let's fix our script so that the recalculation takes place:

$ ratio_orig) ($ width = $ height * $ ratio_orig;) else ($ height = $ width / $ ratio_orig;) // move the image from the file to the canvas with rescaling imagecopyresampled ($ image_p, $ image, 0, 0, 0 , 0, $ width, $ height, $ width_orig, $ height_orig); // imagejpeg output ($ image_p, "2.jpg", 100);

Let's see the result:

Since we counted in height, part of the final image turned out to be black (the original color of the created canvas).

What else can you do with the image? Crop it, rotate it, layer one on top of the other, paint on it.

I'm sure you will be interested in my class for working with images. It does not work outside the system, as it is a driver for the gear (module) "Images".

But you will find a lot of interesting things in it:

* @copyright Copyright (c) 2012, Dmitry Belyaev * @license http://cogear.ru/license.html * @link http://cogear.ru * / class Image_Driver_GD extends Image_Driver_Abstract (/ ** * Creates an image * / public function create () (switch ($ this-> info-> type) (case IMAGETYPE_JPEG: case IMAGETYPE_JPEG2000: $ this-> source = imagecreatefromjpeg ($ this-> info-> file); break; case IMAGETYPE_PNG: $ this- > source = imagecreatefrompng ($ this-> info-> file); imagecolortransparent ($ this-> source, imagecolorallocate ($ this-> source, 0, 0, 0)); imagealphablending ($ this-> source, FALSE); imagesavealpha ($ this-> source, TRUE); break; case IMAGETYPE_GIF: $ this-> source = imagecreatefromgif ($ this-> info-> file); imagecolortransparent ($ this-> source, imagecolorallocate ($ this-> source, 0, 0, 0)); imagealphablending ($ this-> source, FALSE); imagesavealpha ($ this-> source, TRUE); break; case IMAGETYPE_ICO: $ this-> source = imagecreatefromwbmp ($ this-> info-> file); break;)) / ** * Destroys the image * / public function destroy () (imagedestroy ($ this-> source); is_resource ($ this-> target) && imagedestroy ($ this-> target); ) / ** * Creates target image * * @param mixed $ width * @param mixed $ height * / public function createTarget ($ width, $ height) ($ this-> target = imagecreatetruecolor ($ width, $ height); if ($ this-> info-> type == IMAGETYPE_PNG OR IMAGETYPE_GIF == $ this-> info-> type) (imagecolortransparent ($ this-> target, imagecolorallocate ($ this-> target, 0, 0, 0)); imagealphablending ($ this-> target, FALSE); imagesavealpha ($ this-> target, TRUE);) return $ this-> target;) / ** * Scale the image * * @param int | string $ width Width * @ param int | string $ height Height * @param string $ fit Scaling type width, height, fit * @param int | string $ scale Which images to scale any, up, down * @return object Image * / public function resize ($ width, $ height, $ fit = "width", $ scale = "any") ($ source_width = $ this-> smartSize ($ width, "width"); $ source_height = $ this-> smartSize ($ height, "height" ); // Check the scaling type switch ($ fit) (// If the we thread in width, then we bring the height to the desired proportions case "width": $ width = $ source_width; $ height = round (($ source_width * $ this-> info-> height) / $ this-> info-> width); break; // If adjusting the height, then bring the width to the desired proportions case "height": $ width = round (($ this-> info-> width * $ source_height) / $ this-> info-> height); $ height = $ source_height; break; case "crop": if ($ this-> info-> width> $ this-> info-> height) ($ width = round (($ this-> info-> width * $ source_height) / $ this-> info -> height); $ height = $ source_height;) else ($ width = $ source_width; $ height = round (($ this-> info-> height * $ source_width) / $ this-> info-> width);) break; // By default, just stretch default: case "fit":) // Check if scaling will be performed switch ($ scale) (// If the image is larger than the specified dimensions, nothing happens to it case "up": if ($ width< $this->info-> width && $ height< $this-> info-> height) (return $ this;) break; // If the image is smaller than the specified dimensions, nothing happens to it case "down": if ($ width> $ this-> info-> width && $ height> $ this-> info-> height) (return $ this;) break; case "any": default: // Do nothing. Philonym) $ this-> target = $ this-> createTarget ($ width, $ height); if (imagecopyresampled ($ this-> target, $ this-> source, 0, 0, 0, 0, $ width, $ height, $ this-> info-> width, $ this-> info-> height)) ( $ this-> source = $ this-> target; $ this-> info-> width = $ width; $ this-> info-> height = $ height; if ("crop" == $ fit) (return $ this -> crop ("center", "center", $ source_width, $ source_height);)) return $ this; ) / ** * Crops the image * * @param mixed $ x Cropping coordinate x * @param mixed $ y Cropping coordinate y * @param mixed $ width Cropping width * @param mixed $ height Cropping height * @return object Image * / public function crop ($ x, $ y, $ width, $ height) ($ x = $ this-> smartSize ($ x, "width") - $ width / 2; $ y = $ this-> smartSize ($ y , "height") - $ height / 2; $ width = $ this-> smartSize ($ width, "width"); $ height = $ this-> smartSize ($ height, "height"); $ this-> target = $ this-> createTarget ($ width, $ height); if (imagecopyresampled ($ this-> target, $ this-> source, 0, 0, $ x, $ y, $ width, $ height, $ width, $ height)) ($ this-> source = $ this-> target; $ this-> info-> width = $ width; $ this-> info-> height = $ height;) return $ this;) / ** * Merges images * / public function merge (Image $ image, $ x, $ y, $ percent = 100) ($ x = $ this-> smartSize ($ x, "width"); $ y = $ this-> smartSize ($ y, "height"); if (imagecopymerge ($ this-> source, $ image-> getSource (), $ x, $ y, 0, 0 , $ image-> object () -> image-> width, $ image-> object () -> image-> height, $ percent)) () return $ this; ) / ** * Saves the image * / public function save ($ file = NULL, $ options = array ()) ($ this-> target OR $ this-> target = $ this-> source; if (strpos ($ file , ".") OR $ file = $ this-> info-> file) ($ ext = pathinfo ($ file, PATHINFO_EXTENSION); $ ext = strtolower ($ ext);) else ($ ext = strtolower ($ file) ; $ file = NULL;) switch ($ ext) (case "jpg": case "jpeg": $ options OR $ options = 90; imagejpeg ($ this-> target, $ file, $ options); break; case " gif ": imagecolortransparent ($ this-> target, imagecolorallocatealpha ($ this-> target, 0, 0, 0, 127)); imagealphablending ($ this-> target, FALSE); imagesavealpha ($ this-> target, TRUE) ; imagegif ($ this-> target, $ file); break; case "png": imagealphablending ($ this-> target, FALSE); imagesavealpha ($ this-> target, TRUE); if (is_numeric ($ options)) ($ quality = $ options; $ filters = PNG_NO_FILTER;) else ($ quality = isset ($ options ["quality"])? $ options ["quality"]: 9; $ filters = isset ($ options ["filters"])? $ options ["filters"]: PNG_NO_FILTER; ) imagepng ($ this-> target, $ file, $ quality, $ filters); break; ) $ this-> destroy (); ) / ** * Output image * / public function output ($ format, $ options) ($ this-> save ($ format, $ options);))

How does it work in the system? What is so much code for?

See:

$ image = new Image ("1.jpg"); $ image-> resize (200,200, "width") -> crop (200,200) -> save ("2, jpg);

Do you understand? Works with all required formats automatically. The functionality can be expanded if necessary.

Homework for you will be doing what is indicated above (up to my class) on the local machine. If desired and time to experiment with the parameters.

The internet will be pretty boring without images. However, maintaining and managing hundreds or thousands of images for your website can be a headache. As your site design changes, you may need to change all of your images - for example, convert all of your images to grayscale, or resize them to 50% of their original size. You can also compress or crop different images. Doing this manually is time consuming and error prone, but with a little programming knowledge it can be automated.

In this tutorial, we will learn about the GD (Graphic Draw) library in PHP. You will see how this library can be used to manipulate images by resizing, cropping, rotating or filtering.

What is GD?

PHP can do a lot more than just send HTML messages to your visitors. For example, it has the ability to manipulate images. Not only that, but you can also create your own images from scratch and then either save them or serve them to users.

PHP can meet almost all of your basic image manipulation needs using the GD library, short for Graphic Draw.

Installation

If you are on Windows, you can include the file php_gd2.dll as an extension to php.ini... If you are using something like XAMPP you will find the file php_gd2.dll in the catalog xampp \ php \ ext... You can also check if GD is installed on your system with the phpinfo () function; ... If you look at the result, you will find something similar to the following.

You can also visit the Requirements and Installations page to learn more about the installation.

Generating Images with PHP GD

The first step to manipulating images with PHP is loading them into memory as an image resource. This can be achieved using different functions for different formats. All of these functions have very similar names, so they are easy to remember.

Create a new image

The imagecreatetruecolor () function is useful if you don't have the original source of the image you want to modify. It takes two integer parameters: width and height. It will return the image resource if all goes according to plan. The returned image resource is basically a black image with the given width and height.

Uploading an image file

If you plan on working with images that are already stored somewhere, using functions like imagecreatefromjpeg (), imagecreatefrompng (), and imagecreatefromgif () will come in handy. They will create an image resource with all the data from the loaded image file. These functions take a single parameter that specifies the location of the image to load, such as a URL or file path.

Creating an image from a string

The GD library also allows you to create images from a string using the imagecreatefromstring () function in PHP. Remember that you will need to use base64_decode () for the given string before imagecreatefromstring (). The function can automatically detect if the image type is JPG, PNG, GIF or other supported format.

Rotating, scaling, cropping and flipping an image

Some common operations you can perform on an image asset are rotation, scaling, cropping, and flipping.

Rotation

You can rotate an image that you have already loaded into the script using the imagerotate () function. It will rotate the image at a given angle using the center of the image as the center of rotation. The angle is represented as a floating point value, and PHP considers it to be the rotation angle value. Sometimes the rotated image will have different dimensions compared to the original version. This means that after turning, you will get some open area. The third parameter of the imagerotate () function can be used to set the background color of the empty area after rotation.

Scaling

It is very easy to scale an image using the GD library. You just need to pass the image resource as well as the width and height to the imagescale () function. If you lower the height, GD will scale the image to the specified width while maintaining the aspect ratio. You can also specify the image scaling mode. It can be set to IMG_NEAREST_NEIGHBOUR, IMG_BILINEAR_FIXED, IMG_BICUBIC, etc. The important thing to remember is that this function returns a new source of the scaled image instead of changing the original one.

Pruning

You can crop any image resource with the imagecrop () function in GD. The first parameter is the original resource of the image, and the second parameter is an associative array with the keys x, y, width and height, which determines the size of the position of the cropping box.

The butterfly image above has been cropped using the following code:

$ im_php = imagecreatefromjpeg ("path / to / image"); $ size = min (imagesx ($ im_php), imagesy ($ im_php)); $ im_php = imagecrop ($ im_php, ["x" => $ size * 0.4, "y" => 0, "width" => $ size, "height" => $ size]); $ im_php = imagescale ($ im_php, 300);

Basically, we store the length of the smallest side in the $ size variable. This variable is then used to define the border of our clipping rectangle. Finally, the image is scaled down so that it is only 300 pixels wide and long. This gives us a square image.

Flip images

Images can be flipped horizontally, vertically, or in both directions using the imageflip () function. It takes the image asset you want to flip as the first parameter and the flip mode as the second parameter. The flip mode can be set to IMG_FLIP_HORIZONTAL, IMG_FLIP_VERTICAL, or IMG_FLIP_BOTH.

The top left image in the above illustration is the original. The top right image was created using IMG_FLIP_HORIZONTAL, the bottom left image was created using IMG_FLIP_VERTICAL, and the bottom right image was created using IMG_FLIP_BOTH. (Raven image from Pixabay.)

Applying filters to an image

GD also has a very useful imagefilter () function that can apply filters on different image resources loaded using functions from previous images. This function can take various parameters depending on the filter applied.

First, specify the image asset and the name of the filter you want to apply. You can set it to one of the 12 predefined filter types mentioned in the docs.

  • IMG_FILTER_NEGATE: inverts (changes as in negative) the colors in the image
  • IMG_FILTER_GRAYSCALE: removes color from image
  • IMG_FILTER_BRIGHTNESS: makes the image brighter or darker
  • IMG_FILTER_CONTRAST: Increases the contrast of the image
  • IMG_FILTER_COLORIZE: tints the image to the selected color
  • IMG_FILTER_EDGEDETECT: Highlights the edges of the image
  • IMG_FILTER_EMBOSS: Similar to edge detection, but gives each edge a raised look
  • IMG_FILTER_GAUSSIAN_BLUR: Blurs the image using Gaussian method
  • IMG_FILTER_SELECTIVE_BLUR: Blurs the image using a selective method
  • IMG_FILTER_MEAN_REMOVAL: Stylized Image Creation Effect
  • IMG_FILTER_SMOOTH: Smooths jagged edges of the image
  • IMG_FILTER_PIXELATE: makes the image pixelated

Some filters like NEGATE, GRAYSCALE, EDGE_DETECT, and EMBOSS do not need additional data. Other filters, such as BRIGHTNESS, CONTRAST, and SMOOTH, can take an additional parameter that determines the amount of brightness, contrast, or smoothness in the final image. The PIXELATE parameter allows you to specify two additional parameters: block size and pixelation mode. Finally, the COLORIZE filter takes four parameters that define values ​​for the red, green and blue components, as well as the alpha channel.

The image in the upper left corner is the original. The top right image was created using the COLORIZE filter, the bottom left image was created using the GRAYSCALE filter, and the bottom right image was created using the BRIGHTNESS filter. (This butterfly image was found on Pixabay.)

Other useful functions for working with images

You should also be aware of some other common GD functions that can be useful from time to time.

Retrieving image dimensions

You can determine the width and height of an image resource using the imagesx () and imagesy () functions.

Another function called getimagesize () can also be used to get the width and height of an image along with its type. This function returns an array with elements defining the width, height, and aspect ratio. The first two elements of the array describe the width and height, and the third element contains a constant defining the file format: one of IMAGETYPE_PNG, IMAGETYPE_GIF, etc.

Saving an image

After you make all the necessary changes to the image, you most likely want to either output it to the browser or save it as a file. You will have to use one of GD's output functions anyway, such as imagejepg (), imagepng (), or imagegif (). You will pass your image resource to one of these output functions, and if you want to save the image to a file, you will provide the filename as well. You can also control the quality of the output image with an optional third parameter, depending on the type of image.

Resize all images in a directory

Let's put what we've learned into practice to do something. In this section, we will resize all JPEG images in a specific directory to 640 pixels wide. The height will be calculated automatically based on the dimensions of the original image.

We will save the modified images in a new folder called Resized... All original images in this case have the same dimensions, but the code will work correctly with images that have different sizes and proportions.

$ directory = "Nature /"; $ images = glob ($ directory. "*. jpg"); foreach ($ images as $ image) ($ im_php = imagecreatefromjpeg ($ image); $ im_php = imagescale ($ im_php, 640); $ new_height = imagesy ($ im_php); $ new_name = str_replace ("- 1920x1080", "- 640x ". $ New_height, basename ($ image)); imagejpeg ($ im_php, $ directory." Resized /".$ new_name);)

In the above code, we'll start by using the glob () function to find all images with the extension .jpg in a directory called Nature... The image files are stored in an array and we iterate through them one by one.

Since all the images we want to modify are JPEGs, we use the imagecreatefromjpeg () function to load them into the script. The imagescale () function is then used to resize the image to a specific width - 640 pixels in our case. We did not specify a fixed height so that the height would be calculated automatically.

Each of the original image files has been appended with -1920x1080 to their filename to indicate its dimensions. We use str_replace () on the original filename and replace -1920X1080 to the new image size.

Finally, we save the modified images in a folder named Resize with new filenames. You can also pass a third parameter to the imagejpeg () function to set the quality of the saved image file. If the third parameter is omitted, images are saved with a default quality of 75.

Applying grayscale and contrast filters to each image in the catalog

This time we will apply two different filters to each image in our directory and save the final result in a different directory without making any changes to the filename. Let's dive into the code and I'll explain later what each function does.

$ directory = "Nature /"; $ images = glob ($ directory. "*. jpg"); foreach ($ images as $ image) ($ im_php = imagecreatefromjpeg ($ image); imagefilter ($ im_php, IMG_FILTER_GRAYSCALE); imagefilter ($ im_php, IMG_FILTER_CONTRAST, -25); $ new_name = basename ($ image $); imagejpg , $ directory. "Grayscale /".$ new_name);)

As you can see we are loading images from the directory Nature the same as in the previous example. However, this time we will use the imagefilter () function to apply filters on the loaded image resource.

Note that imagefilter () changes the original image and returns TRUE or FALSE depending on the success or failure of the operation. This differs from the imagescale () function we used in the previous section, which returned a scaled image resource.

Another important thing to keep in mind is that the contrast filter takes values ​​from -100 to 100. Negative values ​​mean more contrast, while positive values ​​mean less contrast. This is the opposite of what some people might expect! A value of 0 leaves the image unchanged.

On the other hand, the luminance filter has minimum and maximum limits of -255 and 255. A negative value in this case implies the minimum brightness, and a positive value means the maximum brightness.

We get the filename from the file path using the basename () function and then save the image using the imagejpeg () function.

Final thoughts

The purpose of this tutorial was to introduce you to the GD library in PHP and learn how to use all of its features to make your life easier. You can use the examples at the end of the tutorial as a guide to writing your own imaging scripts. For example, you can resize an image only if it is larger than a specified limit by determining its width using the imagesx () function.

All of these features open up many possibilities for making your work with images easier and will ultimately save you a lot of time. If you have any questions related to this tutorial please let me know in the comments.

In this article, we will analyze in detail the mechanism for uploading images to the server using PHP without resorting to third-party components and frameworks. We will learn how to safely download images not only from the user's local machine, but also remote files via a link. I will write all code examples in a procedural style so that you can read the code faster and not jump from one method to another. The manual is completely copyrighted and does not pretend to be academic in any way.

§one. General principles

The entire sequence of uploading an image to the server can be displayed as follows: php.ini settingget the filesecurity checkdata validationsave to disk... The process of downloading an image from a user's computer or from a URL is no different, with the exception of the method of obtaining an image and saving it. The general scheme for uploading an image to the server is as follows:

To validate the image by URL, we will use the getimagesizefromstring () function, since cURL will download it into a variable for further manipulations.

Since we are uploading images to the server, it would be nice to check their specific parameters: width, the height, a type images, the size file in bytes. It depends on the logic of your application, but for clarity, in this tutorial we will check all the parameters described above.

§2. Safety regulations

The safety of downloading images comes down to preventing foreign code from entering the server and executing it. In practice, loading images is the most vulnerable spot in PHP applications: shell scripts hit, writing malicious code to binary files, substitution of EXIF ​​data... In order to avoid most hacking methods, you need to adhere to the following rules:

a not trust data from $ _FILES;
b not check the MIME-type of the image from the getimagesize () function;
generate a new name and extension in the loaded file;
d prohibit the execution of PHP scripts in the folder with pictures;
d not insert custom data via require and include;
That is, for $ _FILES use is_uploaded_file () and move_uploaded_file ().

If you have something to supplement the "Safety Rules", then leave your comments or links to articles on safety in the comments to this manual, and I will publish them in this paragraph.

§3. Php.ini configuration

PHP allows you to add certain configuration values ​​to the upload process of any files. To do this, you need to find the blocks in the php.ini file “ Resource Limits», « Data handling" and " File Uploads", And then edit the following values ​​as necessary:

; Maximum script execution time in seconds max_execution_time = 60 ; Maximum memory consumption by one script memory_limit = 64M ; Maximum allowed size of data sent by POST method post_max_size = 5M ; File upload permission file_uploads = On ; Folder for storing files during upload upload_tmp_dir = home / user / temp ; Maximum upload file size upload_max_filesize = 5M ; Maximum allowed number of simultaneously uploaded files max_file_uploads = 10

Based on the specified values, the user will not be able to download more than ten files at a time, and each file should not exceed 5 MB. Parameters from the block " Resource Limits"Are more needed to load a remote file, because with the help of cURL we will download the content into a variable and check it according to the criteria we need, and this requires additional time and memory.

The php.ini configuration file must always be configured according to the business logic of the web application being developed. For example, we plan to upload no more than ten files up to 5 MB, which means we need ~ 50 MB of memory. In addition, we need to know the maximum download time for one file from the local machine and by reference in order to set a sufficient script execution time in max_execution_time and not frighten users with errors.

§4. Loading pictures from a form

Now we will not consider uploading several files to the server, but we will analyze only the very mechanics of uploading on the example of one file. So, to upload a picture from a user's computer, you need to send a file to a PHP script using the POST method using an HTML form and specify a method for encoding data enctype = "multipart / form-data"(in this case, the data is not encoded and this value is used only for sending binary files). We will work with the form below:

For the file selection box, we use the name name = "upload" in our HTML form, although it can be anything. After sending the file to the PHP script file-handler.php, it can be intercepted using the superglobal variable $ _FILES ["upload"] with the same name, which in the array contains information about the file:

Array ( => picture.jpg // original file name => image / jpeg // MIME file type => home \ user \ temp \ phpD07E.tmp // binary file => 0 // error code => 17170 // file size in bytes)

Not all data from $ _FILES You can trust: The MIME type and size of a file can be spoofed, because they are formed from the HTTP response, and the extension in the file name should not be trusted due to the fact that a completely different file can be hidden behind it. Nevertheless, next we need to check whether our file has loaded correctly and whether it has loaded at all. To do this, you need to check for errors in $ _FILES ["upload"] ["error"] and make sure the file is uploaded using the POST method using the function is_uploaded_file ()... If something does not go according to plan, then we display the error on the screen.

// Overwrite the variables for convenience$ filePath = $ _FILES ["upload"] ["tmp_name"]; $ errorCode = $ _FILES ["upload"] ["error"]; // Check for errors if ($ errorCode! == UPLOAD_ERR_OK ||! is_uploaded_file ($ filePath)) ( // Array with error names$ errorMessages = [UPLOAD_ERR_INI_SIZE => "File size exceeded upload_max_filesize in PHP configuration.", UPLOAD_ERR_FORM_SIZE => "The size of the uploaded file has exceeded the MAX_FILE_SIZE value in HTML form.", UPLOAD_ERR_PARTIAL => "The download file was only partially received.", UPLOAD_ERR_NO_FILE => "The file was not loaded.", UPLOAD_ERR_NO_TMP_DIR => "Temp folder is missing.", UPLOAD_ERR_CANT_WRITE => "Failed to write file to disk.", UPLOAD_ERR_EXTENSION => "PHP extension has stopped downloading file.", ]; // Set an unknown error$ unknownMessage = "An unknown error occurred while downloading the file."; // If there is no error code in the array, let's say that the error is unknown$ outputMessage = isset ($ errorMessages [$ errorCode])? $ errorMessages [$ errorCode]: $ unknownMessage; // Display the name of the error die ($ outputMessage); )

To prevent an attacker from downloading the malicious code embedded in the image, the function cannot be trusted getimagesize () which also returns the MIME type. The function expects the first argument to be a link to a valid image file... You can determine the real MIME-type of a picture through the FileInfo extension. The code below will check for the presence of the keyword image in the type of our uploaded file and if it does not appear, it will give an error:

// Create a FileInfo resource$ fi = finfo_open (FILEINFO_MIME_TYPE); // Get the MIME type $ mime = (string) finfo_file ($ fi, $ filePath); );

At this stage, we can already upload absolutely any images to our server that have passed the MIME type check, but to upload images according to certain characteristics, we need to validate them using the function getimagesize (), which we will feed the binary file itself $ _FILES ["upload"] ["tmp_name"]... As a result, we will get an array with a maximum of 7 elements:

Array (=> 1280 // width => 768 // height => 2 // type => width = "1280" height = "768" // attributes for HTML => 8 // color depth => 3 // color model => image / jpeg // MIME type)

To further validate the image and work on it, we only need to know 3 values: width, the height and the size file (to calculate the size, use the function filesize () for a binary file from a temporary folder).

// Write the result of the function into a variable$ image = getimagesize ($ filePath); $ limitBytes = 1024 * 1024 * 5; $ limitWidth = 1280; $ limitHeight = 768; // Check the required parameters if (filesize ($ filePath)> $ limitBytes) die ( "Image size must not exceed 5 MB."); if ($ image> $ limitHeight) die (); if ($ image> $ limitWidth) die ();

After all the checks, we can confidently move our downloadable file to some folder with pictures. It is better to do it through a function move_uploaded_file () that runs in safe mode. Before moving the file, you must not forget generate random name and extension from image type for our file. This is how it looks:

// Generate a new file name based on the MD5 hash$ name = md5_file ($ filePath); // Reduce .jpeg to .jpg// Move the picture with a new name and extension to the / pics folder if (! move_uploaded_file ($ filePath, __DIR__. "/ pics /". $ name. $ format)) (die ( "An error occurred while writing the image to disc."); }

This completes the image loading. For more convenient file uploading, you can use the UploadedFile class from the Symfony HttpFoundation package, which is a wrapper for $ _FILES and also saves the file via move_uploaded_file ().

§5. Uploading an image from a link

To load an image from a link, we need a cURL library that works with remote resources. With the help of it, we will download the content into a variable. On the one hand, it may seem that for these purposes is suitable file_get_contents (), but in fact, we will not be able to control the amount of downloaded data and normally handle all errors that occur. In order for cURL to download the data correctly, we need to: allow to follow redirects, enable check certificate, indicate maximum time cURL work (formed due to the amount of downloaded data and the average speed of work with the resource). How to correctly download a file into a variable is shown below with the necessary parameters:

// Get the link somehow$ url = "https://site.ru/picture.jpg"; // Check the HTTP in the link url if (! preg_match ("/ ^ https?: / i", $ url) && filter_var ($ url, FILTER_VALIDATE_URL)) (die ( "Specify a valid link to the remote file."); } // Run cURL with our link$ ch = curl_init ($ url); // Specify settings for cURL curl_setopt_array ($ ch, [ // Specify the maximum running time for cURL CURLOPT_TIMEOUT => 60, // Allow to follow redirects CURLOPT_FOLLOWLOCATION => 1, // Let's allow the result to be written to a variable CURLOPT_RETURNTRANSFER => 1, // Turn on the data loading indicator CURLOPT_NOPROGRESS => 0, // Set the buffer size to 1 KB CURLOPT_BUFFERSIZE => 1024, // Write a function to count the downloaded data // More details: http://stackoverflow.com/a/17642638 CURLOPT_PROGRESSFUNCTION => function ($ ch, $ dwnldSize, $ dwnld, $ upldSize, $ upld) ( // When more than 5 MB have been downloaded, cURL will abort if ($ dwnld> 1024 * 1024 * 5) (return - 1;)), // Turn on certificate verification (by default) CURLOPT_SSL_VERIFYPEER => 1, // Check the name of the certificate and its match with the specified host (by default) CURLOPT_SSL_VERIFYHOST => 2, // Specify the verification certificate // Download: https://curl.haxx.se/docs/caextract.html CURLOPT_CAINFO => __DIR__. "/cacert.pem",]); $ raw = curl_exec ($ ch); // Load data into a variable$ info = curl_getinfo ($ ch); // Get information about the operation$ error = curl_errno ($ ch); // Write the code of the last error // End the cURL session curl_close ($ ch);

If everything went well and cURL finished within 60 seconds, then the contents of the link will be downloaded into a variable $ raw... In addition, the function curl_getinfo () will return information about the request made, from where we can get additional information to analyze the work with remote resources:

Array ( => image / jpeg // MIME type from Content-Type => 200 // last HTTP code => 0 // number of redirects => 0.656 // total running time of cURL => 0.188 // time to connect to the host => 4504 // real size of the received data => 4504 // data size from Content-Length /* ... */ )

Next, we need to check if there are any errors in curl_errno () and make sure that the resource returns an HTTP code equal to 200, otherwise we will say that nothing was found at this URL. After all checks, the variable $ raw transfer to getimagesizefromstring () and we work according to the established scheme, as in the case of loading pictures from a form.

Please note that we are validating the file size at the time of receiving the data, since we cannot 100% trust curl_getinfo (), since the content_type, http_code, download_content_length values ​​are generated based on the received HTTP headers. Downloading the entire file and then checking the number of bytes will take a lot of time and memory. Therefore, we controlled the size of the received data using the CURLOPT_PROGRESSFUNCTION option: as soon as cURL receives more data than our limit, it will stop working and throw a CURLE_ABORTED_BY_CALLBACK error.

// Check for cURL errors and file availability if ($ error === CURLE_OPERATION_TIMEDOUT) die ( "Waiting limit exceeded."); if ($ error === CURLE_ABORTED_BY_CALLBACK) die ( "The size should not exceed 5 MB."); if ($ info ["http_code"]! == 200) die ( "File not available."); // Create a FileInfo resource$ fi = finfo_open (FILEINFO_MIME_TYPE); // Get the MIME type using the contents of $ raw$ mime = (string) finfo_buffer ($ fi, $ raw); // Close the FileInfo resource finfo_close ($ fi); // Check the keyword image (image / jpeg, image / png, etc.) if (strpos ($ mime, "image") === false) die ( "Only images can be uploaded."); // Take the image data from its content$ image = getimagesizefromstring ($ raw); // Set limits for images$ limitWidth = 1280; $ limitHeight = 768; // Check the required parameters if ($ image> $ limitHeight) die ( "Image height should not exceed 768 pixels."); if ($ image> $ limitWidth) die ( "Image width must not exceed 1280 dots."); // Generate a new name from the MD5 hash of the image$ name = md5 ($ raw); // Generate the file extension based on the image type$ extension = image_type_to_extension ($ image); // Reduce .jpeg to .jpg$ format = str_replace ("jpeg", "jpg", $ extension); // Save the picture with a new name and extension to the / pics folder if (! file_put_contents (__DIR__. "/ pics /". $ name. $ format, $ raw)) (die ( "An error occurred while saving the image to disk."); }

To save the image to disk, you can use file_put_contents () which will write the content to a file. We will create a new file name through the function md5 (), and we will make the extension from image_type_to_extension ()... Now we can download any images from the link.

§6. Configuring Multiple File Selection

In this section, we will analyze how to download several images at one time from the user's local machine and from remote links. To send links, we use $ _POST and pass all the data to it using the tag textarea... To load files from the form, we will continue to work with $ _FILES... Our new HTML form will be slightly different from the old one.

At the end of the file selection field name name = "upload" added curly braces and an attribute multiple which allows the browser to select multiple files. All files will be uploaded to the temporary folder again if there are no errors in php.ini. You can intercept them in $ _FILES, but this time the superglobal will have an awkward structure for handling data in an array. This problem is solved by small manipulations with the array:

// Change the structure of $ _FILES foreach ($ _FILES ["upload"] as $ key => $ value) (foreach ($ value as $ k => $ v) ($ _FILES ["upload"] [$ k] [$ key] = $ v; ) // Delete old keys unset ($ _FILES ["upload"] [$ key]); ) // Load all pictures in order foreach ($ _FILES ["upload"] as $ k => $ v) ( // Load one file at a time$ _FILES ["upload"] [$ k] ["tmp_name"]; $ _FILES ["upload"] [$ k] ["error"]; )

To download several images by URL, we will pass our links through textarea With name name = "upload", where you can specify them separated by a space or on a new line. Function preg_split will parse all data from $ _POST ["upload"] and will form an array that you need to loop through and send each valid URL to the handler.

$ data = preg_split ("/ \ s + /", $ _POST ["upload"], - 1, PREG_SPLIT_NO_EMPTY); foreach ($ data as $ url) ( // Validate and load the image by URL }

9 years ago

Hello there,
i made a function to create a gradient image.

description:
gradient (int image_width, int image_height,
int start_red, int start_green, int start_blue,
int end_red, int end_green, int end_blue,
bool vertical)

function:
function gradient ($ image_width, $ image_height, $ c1_r, $ c1_g, $ c1_b, $ c2_r, $ c2_g, $ c2_b, $ vertical = false)
{
// first: lets type cast;
$ image_width = (integer) $ image_width;
$ image_height = (integer) $ image_height;
$ c1_r = (integer) $ c1_r;
$ c1_g = (integer) $ c1_g;
$ c1_b = (integer) $ c1_b;
$ c2_r = (integer) $ c2_r;
$ c2_g = (integer) $ c2_g;
$ c2_b = (integer) $ c2_b;
$ vertical = (bool) $ vertical;

// create a image
$ image = imagecreatetruecolor ($ image_width, $ image_height);

// make the gradient
for ($ i = 0; $ i< $image_height ; $i ++)
{
$ color_r = floor ($ i * ($ c2_r - $ c1_r) / $ image_height) + $ c1_r;
$ color_g = floor ($ i * ($ c2_g - $ c1_g) / $ image_height) + $ c1_g;
$ color_b = floor ($ i * ($ c2_b - $ c1_b) / $ image_height) + $ c1_b;

$ color = ImageColorAllocate ($ image, $ color_r, $ color_g, $ color_b);
imageline ($ image, 0, $ i, $ image_width, $ i, $ color);
}

# Prints out all the figures and picture and frees memory
header ("Content-type: image / png");

if ($ vertical) ($ image = imagerotate ($ image, 90, 0);)
ImagePNG ($ image);
imagedestroy ($ image);
}
?>

7 years ago

In case your script is using output-buffering-functions somewhere, then you have to clear the buffer first (with ob_clear ()), before outputting an image with a function like imagepng ().

And you should make sure that no buffer will get send after outputing an image by using the ob_end_flush () - function.

Furthermore you should check if a buffer has already been flushed somewhere before. This can be done using the headers_sent () - function.

Here is the full solution:

if (headers_sent ()) (
die ( "Headers have been send somewhere within my script");
}

Ob_clean (); // Clears the buffer

Header ("Content-type: image / png");
imagepng ($ img, NULL, 0, NULL);

Ob_end_flush (); // Now we send the header and image plus we make sure that nothing will get send from now on (including possible shutdown-functions and __destruct () - methods) till the end of page-execution
?>

10 years ago

You know, maybe this goes without saying, but I thought I would drop a note in here. When developing code to resize images, it is best not to use GD. When using the current GD methodologies, you are reading content from an image and manipulating it. By then writing that content to a brand new file, you are losing the EXIF ​​data.

For purposes when you want to retain EXIF ​​data, it is recommended that you compile in and use the PECL Imagick extension. It has great resizing methods built right in and the EXIF ​​data is retained.

10 years ago

I have been looking to send the output from GD to a text string without proxying via a file or to a browser.

I have come up with a solution.

This code buffers the output between the ob_start () and ob_end () functions into ob_get_contents ()

See the example below

// Create a test source image for this example
$ im = imagecreatetruecolor (300, 50);
$ text_color = imagecolorallocate ($ im, 233, 14, 91);
imagestring ($ im, 1, 5, 5, "A Simple Text String", $ text_color);

// start buffering
ob_start ();
// output jpeg (or any other chosen) format & quality
imagejpeg ($ im, NULL, 85);
// capture output to string
$ contents = ob_get_contents ();
// end capture
ob_end_clean ();

// be tidy; free up memory
imagedestroy ($ im);

// lastly (for the example) we are writing the string to a file
$ fh = fopen ("./temp/img.jpg", "a +");
fwrite ($ fh, $ contents);
fclose ($ fh);
?>







2021 gtavrl.ru.