Output an Image in PHP
![]()
If you have the liberty to configure your webserver yourself, tools like mod_xsendfile (for Apache) are considerably better than reading and printing the file in PHP. Your PHP code would look like this:
mod_xsendfile picks up the X-Sendfile header and sends the file to the browser itself. This can make a real difference in performance, especially for big files. Most of the proposed solutions read the whole file into memory and then print it out. That’s OK for a 20kbyte image file, but if you have a 200 MByte TIFF file, you’re bound to get problems.
For the next guy or gal hitting this problem, here’s what worked for me:
You need all of that, and only that. If your mimetype varies, have a look at PHP’s mime_content_type($filepath)
- log views of a jpg image and an animated gif , and,
- ensure that the images are never cached (so every view is logged), and,
- also retain the original file extensions.
I accomplished this by creating a «secondary» .htaccess file in the sub-folder where the images are located.
The file contains only one line:
In the same folder, I placed the two ‘original’ image files (we’ll call them orig.jpg and orig.gif ), as well as two variations of the [simplified] script below (saved as myimage.jpg and myimage.gif ).
The images render (or animate) normally and can be called in any of the normal ways for images (like an <img> tag), and will save a record of the visiting IP, while invisible to the user.
imagejpeg
Функция imagejpeg() создаёт файл JPEG из изображения image .
Список параметров
Объект GdImage , возвращаемый одной из функций создания изображений, например, такой как imagecreatetruecolor() .
Путь, или открытый потоковый ресурс (который автоматически закрывается после завершения функции), для сохранения файла. Если не установлен или равен null , изображение будет выведено в поток вывода в бинарном виде.
Необязательный параметр, и может принимать значения в диапазоне от 0 (низкое качество, маленький размер файла) до 100 (высокое качество, большой размер файла). По умолчанию ( -1 ) используется качество IJG (около 75).
Возвращаемые значения
Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.
Однако, если libgd не может вывести изображения, эта функция вернёт true .
Список изменений
| Версия | Описание |
|---|---|
| 8.0.0 | image теперь ожидает экземпляр GdImage ; ранее ожидался корректный gd ресурс ( resource ). |
Примеры
Пример #1 Вывод JPEG-изображения в браузер
<?php
// Создаём пустое изображение и добавляем текст
$im = imagecreatetruecolor ( 120 , 20 );
$text_color = imagecolorallocate ( $im , 233 , 14 , 91 );
imagestring ( $im , 1 , 5 , 5 , ‘A Simple Text String’ , $text_color );
// Устанавливаем тип содержимого в заголовок, в данном случае image/jpeg
header ( ‘Content-Type: image/jpeg’ );
// Выводим изображение
imagejpeg ( $im );
// Освобождаем память
imagedestroy ( $im );
?>
Результатом выполнения данного примера будет что-то подобное:
Пример #2 Сохранение изображения JPEG в файл
<?php
// Создаём пустое изображение и добавляем текст
$im = imagecreatetruecolor ( 120 , 20 );
$text_color = imagecolorallocate ( $im , 233 , 14 , 91 );
imagestring ( $im , 1 , 5 , 5 , ‘A Simple Text String’ , $text_color );
// Сохраняем изображение в ‘simpletext.jpg’
imagejpeg ( $im , ‘simpletext.jpg’ );
// Освобождаем память
imagedestroy ( $im );
?>
Пример #3 Вывод JPEG-изображения с 75% качеством в браузер
<?php
// Создаём пустое изображение и добавляем текст
$im = imagecreatetruecolor ( 120 , 20 );
$text_color = imagecolorallocate ( $im , 233 , 14 , 91 );
imagestring ( $im , 1 , 5 , 5 , ‘A Simple Text String’ , $text_color );
// Устанавливаем тип содержимого в заголовок, в данном случае image/jpeg
header ( ‘Content-Type: image/jpeg’ );
// Пропускаем параметр file, используя NULL, а затем устанавливаем качество в 75%
imagejpeg ( $im , NULL , 75 );
// Освобождаем память
imagedestroy ( $im );
?>
Примечания
Замечание:
Если требуется вывести Progressive JPEG (прогрессивное представление данных), то необходимо использовать функцию imageinterlace() для активации соответствующего режима.
Смотрите также
- imagepng() — Вывод PNG изображения в браузер или файл
- imagegif() — Выводит изображение в браузер или пишет в файл
- imagewbmp() — Выводит изображение в браузер или пишет в файл
- imageinterlace() — Включение или выключение интерлейсинга
- imagetypes() — Возвращает список типов изображений, поддерживаемых PHP сборкой
User Contributed Notes 35 notes
I didn’t find any example like this on the Web, so I mixed pieces together.. hope this will save time to other people!
Here’s a complete solution to READ any image (gif jpg png) from the FILESYSTEM, SCALE it to a max width/height, SAVE the scaled image to a BLOB field keeping the original image type. Quite tricky..
function scaleImageFileToBlob ( $file ) <
$source_pic = $file ;
$max_width = 200 ;
$max_height = 200 ;
list( $width , $height , $image_type ) = getimagesize ( $file );
switch ( $image_type )
<
case 1 : $src = imagecreatefromgif ( $file ); break;
case 2 : $src = imagecreatefromjpeg ( $file ); break;
case 3 : $src = imagecreatefrompng ( $file ); break;
default: return » ; break;
>
$x_ratio = $max_width / $width ;
$y_ratio = $max_height / $height ;
if( ( $width <= $max_width ) && ( $height <= $max_height ) ) <
$tn_width = $width ;
$tn_height = $height ;
>elseif (( $x_ratio * $height ) < $max_height ) <
$tn_height = ceil ( $x_ratio * $height );
$tn_width = $max_width ;
>else <
$tn_width = ceil ( $y_ratio * $width );
$tn_height = $max_height ;
>
$tmp = imagecreatetruecolor ( $tn_width , $tn_height );
/* Check if this image is PNG or GIF, then set if Transparent*/
if(( $image_type == 1 ) OR ( $image_type == 3 ))
<
imagealphablending ( $tmp , false );
imagesavealpha ( $tmp , true );
$transparent = imagecolorallocatealpha ( $tmp , 255 , 255 , 255 , 127 );
imagefilledrectangle ( $tmp , 0 , 0 , $tn_width , $tn_height , $transparent );
>
imagecopyresampled ( $tmp , $src , 0 , 0 , 0 , 0 , $tn_width , $tn_height , $width , $height );
/*
* imageXXX() only has two options, save as a file, or send to the browser.
* It does not provide you the oppurtunity to manipulate the final GIF/JPG/PNG file stream
* So I start the output buffering, use imageXXX() to output the data stream to the browser,
* get the contents of the stream, and use clean to silently discard the buffered contents.
*/
ob_start ();
switch ( $image_type )
<
case 1 : imagegif ( $tmp ); break;
case 2 : imagejpeg ( $tmp , NULL , 100 ); break; // best quality
case 3 : imagepng ( $tmp , NULL , 0 ); break; // no compression
default: echo » ; break;
>
?>
So, let’s suppose you have a form where a user can upload an image, and you have to scale it and save it into your database.
[..] // the user has clicked the Submit button..
// Check if the user entered an image
if ( $_FILES [ ‘imagefile’ ][ ‘name’ ] != » ) <
$image = scaleImageFileToBlob ( $_FILES [ ‘imagefile’ ][ ‘tmp_name’ ]);
if ( $image == » ) <
echo ‘Image type not supported’ ;
> else <
$image_type = $_FILES [ ‘imagefile’ ][ ‘type’ ];
$image = addslashes ( $image );
$query = «UPDATE yourtable SET image_type=’ $image_type ‘, image=’ $image ‘ WHERE . » ;
$result = mysql_query ( $query );
if ( $result ) <
echo ‘Image scaled and uploaded’ ;
> else <
echo ‘Error running the query’ ;
>
>
>
[[Editor’s note: removed the header()-call since it is not required when outputting inline image-data]]
One single code line, solve-me after 3 hours of blind search!
. ob_start();
imagejpeg( $img, NULL, 100 );
imagedestroy( $img );
$i = ob_get_clean();
echo «<img jpeg;base64,» . base64_encode( $i ).»‘>»; //saviour line!
Regarding Carl Gieringer’s comment, it is possible to have PHP files in utf-8. Just make sure the editor does not output BOM, which is unnecessary in utf-8 anyway.
Except for any editors from Microsoft, most programmer’s editors that supports utf allows you to surpress BOM.
With regard to chris.calo’s code:
// The following block retrieves the source file. It assumes the filename extensions match the file’s format.
if ( strpos($source_file,».gif») ) < $img_source = imagecreatefromgif($source_file); >
if ( (strpos($source_file,».jpg»)) || (strpos($source_file,».jpeg»)) )
. etc.
It assumes more than that, namely that the filename does not contain the strings ‘.gif’, ‘.jpg’, ‘.jpeg’, ‘.bmp’, or ‘.png’ *anywhere* in the string. Some valid files with special filenames could break this; for example, a file named «used.to.be.a.png.file.gif» would cause this script to attempt to load the file as a PNG. Obviously this is a rare case, but the issue could be easily avoided by using «else ifs» (uses less CPU time) or checking that the extension abuts the end of the string or both.
That said, the whole business could be avoided if PHP didn’t clutter the namespace with different functions to do the same thing with different image formats. Ick.
note below is missing «()» from the ob_end_clean call:
ob_end_clean; // stop this output buffer
ob_end_clean(); // stop this output buffer
You can then use this for adding content-length headers (for example flash requires a content length in advance to create loaders)
ob_start(); // start a new output buffer
imagejpeg( $newimage, «», 90 );
$ImageData = ob_get_contents();
$ImageDataLength = ob_get_length();
ob_end_clean(); // stop this output buffer
header(«Content-type: image/jpeg») ;
header(«Content-Length: «.$ImageDataLength);
echo $ImageData;
I worked out a script that allows the transfer of alphanumeric data to be placed on an image. The HTML feature is img src and the php feature is imagettftext. This simple code will increment from 1 to 3 on images.
<?php
//ImageCall.php — This script will call a script to produce the image.
for( $next = 1 ; $next < 4 ; $next ++)<
print «Image $next :<br>» ;
print «<img src = ‘Image.php?\$text= $next ‘>» ;
print «<br><br>» ;
>
?>
<?php
//Image.php — This script creates a square image and places the text on it.
// image size and color
$im = ImageCreate ( 77 , 77 );
$color1 = ImageColorAllocate ( $im , 0x66 , 0xCC , 0x00 );
$color2 = ImageColorAllocate ( $im , 0x33 , 0x66 , 0x00 );
$color3 = ImageColorAllocate ( $im , 0x00 , 0x99 , 0x00 );
$color4 = ImageColorAllocate ( $im , 0x3D , 0x3D , 0x3D );
// image creation
ImageFilledRectangle ( $im , 1 , 1 , 76 , 76 , $color1 );
ImageFilledpolygon ( $im , array ( 76 , 1 , 1 , 76 , 76 , 76 ), 3 , $color2 );
ImageFilledRectangle ( $im , 5 , 5 , 72 , 72 , $color3 );
// determine numeric center of image
$size = ImageTTFBBox ( 45 , 0 , ‘impact’ , $_GET [ ‘$text’ ]);
$X = ( 77 — ( abs ( $size [ 2 ]- $size [ 0 ])))/ 2 ;
$Y = (( 77 — ( abs ( $size [ 5 ] — $size [ 3 ])))/ 2 + ( abs ( $size [ 5 ] — $size [ 3 ])));
//places numeric information on image
ImageTTFText ( $im , 45 , 0 ,( $X — 1 ), $Y , $color4 , ‘impact’ , $_GET [ ‘$text’ ]);
//returns completed image to calling script
Header ( ‘Content-Type: image/png’ );
Imagejpeg ( $im );
I had similar problem with safe mode. My solution is:
before imagejpeg(), touch() etc.
write:
ini_set(safe_mode,Off);
and after everything:
ini_set(safe_mode,On);
strange, but it works
Chears2All
If you wish to capture the jpg data into a variable, rather than outputting it or saving it into a file (perhaps so you can put it in a database), you might want to consider output buffering. Something along these lines should work:
<?php
ob_start (); // start a new output buffer
imagejpeg ( $newimage , NULL , 100 );
$ImageData = ob_get_contents ();
ob_end_clean ; // stop this output buffer
?>
Rather than using the temporary file, as described above, you can buffer the output stream. Someone else showed me this, and it seems to work very nicely.
//Start buffering the output stream
ob_start();
// output the image as a file to the output stream
Imagejpeg($im);
//Read the output buffer
$buffer = ob_get_contents();
//clear the buffer
ob_end_clean();
//use $buffer as you wish.
I came here looking for something similar to the getJPEGresolution function, but noticed the drawbacks that were pointed out in the last post. So, after drawing on some other code examples on the web, I put together the following function which should always properly return the correct values. (But remember that you still need to have the EXIF extension installed with your instance of PHP for this to work!)
function jpeg_dpi ( $filename )
<
if ( exif_imagetype ( $filename ) != IMAGETYPE_JPEG ) <
return false ;
> else <
$exif = exif_read_data ( $filename , ‘IFD0’ );
>
$x = $y = 0 ;
if ( isset( $exif [ ‘XResolution’ ]) && isset( $exif [ ‘YResolution’ ]) ) <
$x = intval ( preg_replace ( ‘@^(\\d+)/(\\d+)$@e’ , ‘$1/$2’ , $exif [ ‘XResolution’ ]));
$y = intval ( preg_replace ( ‘@^(\\d+)/(\\d+)$@e’ , ‘$1/$2’ , $exif [ ‘YResolution’ ]));
>
if ( ! $x && ! $y && $fp = fopen ( $filename , ‘r’ ) ) <
$string = fread ( $fp , 20 );
fclose ( $fp );
$data = bin2hex ( substr ( $string , 14 , 4 ));
$x = hexdec ( substr ( $data , 0 , 4 ));
$y = hexdec ( substr ( $data , 4 , 4 ));
>
if ( $x || $y ) <
return array( $x , $y );
>
?>
This function returns an array with the x-resolution, y-resolution when they can be determined, otherwise FALSE.
I had a problem with denied permissions when trying to upload AND resize an image having safe_mode on. This caused that I couldn’t create the new file in which I wanted to resampled the image with nor with imagejpeg() nor with touch() and imagejpeg() after it.
Here is my solution, I didn’t test, but it’s possible, it is biting some memory:
<?php
function resize ( $image , $target_file ) <
// $image is the uploaded image
list( $width , $height ) = getimagesize ( $image [ ‘tmp_name’ ]);
//setup the new size of the image
$ratio = $width / $height ;
$new_height = 500 ;
$new_width = $new_height * $ratio ;
//move the file in the new location
move_uploaded_file ( $image [ ‘tmp_name’ ], $target_file );
// resample the image
$new_image = imagecreatetruecolor ( $new_width , $new_height );
$old_image = imagecreatefromjpeg ( $target_file );
imagecopyresampled ( $new_image , $old_image , 0 , 0 , 0 , 0 , $new_width , $new_height , $width , $height );
//output
imagejpeg ( $new_image , $target_file , 100 );
>
?>
As you can see, the function moves the uploaded file where you want to save the resampled image (move_uploaded_file is not restricted by safe_mode) and then you can resample the image, because it was created by moving it already.
Note: the directory where you want to save the file must have permissions set to 0777.
I did an experiment with the image quality parameter of the imagejpeg() function when creating jpegs. I found the optimal image quality with file size is taken into account to be 80 — very close to the default value of 75.
Anything over 80 results in an unnecessary increase in file size without much increase in image quality.
If you use the official Docker images and enable gd with `docker-php-ext-install gd`, you don’t get JPEG support by default.
If that’s you, and you get «Call to undefined function imagejpeg()», the you need to do this before docker-php-ext-install:
docker-php-ext-configure gd —with-jpeg
You’ll also want to install libjpeg-dev for this to work.
ZERO BYTE FILE RESULT — HERE’S WHY!
Take to heart that CAUTION note on this function. If gdlib fails to output, it still returns true! I’d call that a bug personally.
GD will fail to output if you have an image exceeding its maximum undisclosed dimensions of 65500 pixels.
You’ll get a zero byte file instead
For those looking to grab the resolution of a JPEG image without using GD nor ImageMagic. I wrote this simple function.
Too bad GD doesn’t have this very simple function for us to use.
<?php
function getJPEGresolution ( $filename ) <
$outRez =array();
// Read the file
ob_start (); // start a new output buffer
$image = file_get_contents ( $filename );
// grab DPI information from the JPG header
$outRez [ «xDPI» ] = ord ( $image [ 15 ]);
$outRez [ «yDPI» ] = ord ( $image [ 17 ]);
ob_end_clean (); // stop this output buffer
//xDPI and yDPI should equal in value. but we output both anyway.
return( $outRez );
> //end function getJPEGresolution
?>
Here is a function to resize an image and maintain aspect ratio. It will resize jpeg, gif or png and could easily be modified to add bmp. The name field is the destination of the file minus the file extension:
<?php
//name= filename minus type
function createImage ( $uploadedfile , $newWidth , $name )
<
// Capture the original size of the uploaded image
if(! $info = getimagesize ( $uploadedfile ))
return false ;
switch ( $info [ ‘mime’ ])
<
case ‘image/jpeg’ :
$src = imagecreatefromjpeg ( $uploadedfile );
break;
case ‘image/gif’ :
$src = imagecreatefromgif ( $uploadedfile );
break;
case ‘image/png’ :
$src = imagecreatefrompng ( $uploadedfile );
break;
default:
return false ;
>
//Change the filename to add the filetype
$mime = split ( «image/» , $info [ ‘mime’ ]);
$filename = $name . «.» . $mime [ 1 ];
$size = getimagesize ( $uploadedfile );
$newHeight = aspect_ratio ( $size [ 0 ], $newWidth , $size [ 1 ]);
$tmp = imagecreatetruecolor ( $newWidth , $newHeight );
// this line actually does the image resizing, copying from the original
// image into the $tmp image
imagecopyresampled ( $tmp , $src , 0 , 0 , 0 , 0 , $newWidth , $newHeight , $info [ 0 ], $info [ 1 ]);
switch ( $info [ ‘mime’ ])
<
case ‘image/jpeg’ :
imagejpeg ( $tmp , $filename , 100 ); //100 is the quality settings, values range from 0-100.
break;
case ‘image/gif’ :
imagegif ( $tmp , $filename , 100 ); //100 is the quality settings, values range from 0-100.
break;
case ‘image/png’ :
imagepng ( $tmp , $filename ); //100 is the quality settings, values range from 0-100.
break;
>
imagedestroy ( $src );
imagedestroy ( $tmp ); // NOTE: PHP will clean up the temp file it created when the request
// has completed.
return true ;
>
if(! createImage ( $uploadedfile , 100 , «uploaded_images/imgname» ))
<
echo «error» ;
>
?>
Here’s another on-the-fly thumbnail creation script.
When I scripted the pictuerviewer on my page, I had all the pictures only in full size and qualit, because I wanted the posibility für visitors to download the pictures.
But as Imagesizes of more than 4 MP are to large for websites, I created thumbnails and the smaller pictures on the fly. But I found out, that the Script needed too much RAM, especially in the thumbnail overview, when I had more then 50 thumbnails to create on the fly at the same time.
So I modified my image creator and my viewer to let them store images, that are created. So only the first visitor has to wait (which is usually me for controlling the uploads und updates), all other visitors get the stored images, which is much faster.
Create different folders. I have a main folder called ‘imagesdb’ and the tree subfolders full (Full quality images), show (images for the picture viewer) and thumb (for thumbnails in overview).
Store the script for example as image.php and link it like that:
<?PHP
$image_name = «foo.jpg» ;
$style = «show» ;
// I’ve taken the foldernames. It’s easier. For the
//thumbnails replace «show» with «thumb».
$image_name = «imagesdb/ $style / $image_name » ;
if(! file_exists ( $image_name ))
$image_name = «image.php?image_name= $image_name &style= $style » ;
// only if file doesn’t exist call the on-the-fly creating file
?>
Now the main script, stored in the file image.php:
$image_name = $_GET [ ‘image_name’ ];
$style = $_GET [ ‘style’ ];
// Now set the maximum sizes to the different styles.
// You may set additional styles, but remember to
// create the according subfolders.
switch( $style ) <
case «show» :
$max_size = 800 ;
break;
case «thumb» :
$max_size = 125 ;
>
$dest_file = «imagesdb/ $style / $image_name » ;
// set output file
$image_file = «imagesdb/full/ $image_name » ;
// set source file
$size = getimagesize ( $image_file );
// get original size
if( $size [ 0 ] > $size [ 1 ]) <
$divisor = $size [ 0 ] / $max_size ;
>
else <
$divisor = $size [ 1 ] / $max_size ;
>
// to get allways pictures of the same size, which ist
// mostly wanted in imageviewers, look what ist larger:
// width or height
$new_width = $size [ 0 ] / $divisor ;
$new_height = $size [ 1 ] / $divisor ;
// set new sizes
settype ( $new_width , ‘integer’ );
settype ( $new_height , ‘integer’ );
// sizes should be integers
$image_big = imagecreatefromjpeg ( $image_file );
// load original image
$image_small = imagecreatetruecolor ( $new_width , $new_height );
// create new image
imagecopyresampled ( $image_small , $image_big , 0 , 0 , 0 , 0 , $new_width , $new_height , $size [ 0 ], $size [ 1 ]);
// imageresampled whill result in a much higher quality
// than imageresized
imagedestroy ( $image_big );
// the original data are no longer used
header ( «Content-type: image/jpeg» );
if( $style == «show» || $style == «thumb» ) <
if(! file_exists ( $dest_file ))
imagejpeg ( $image_small , $dest_file , 100 );
>
// if you have set additional sizese put them in the
// if-arguments, too.
// if someone calls the image.php directly in the
// browser with imagenames allready existing, they
// won’t be overwritten
imagejpeg ( $image_small , » , 100 );
imagedestroy ( $image_small );
// finally send image to browser and destroy no longer
// needed data.
?>
As this website helped me for several times in the past and for creating this script, I hope I can help others with this script saving the time for developing a much more performant solution than an allways-on-the-fly-creating script.
Thanks to Chris dot Calo for the thumbnail snippet. The file type issue is easily resolved by getting the type from the file with getimagesize, and you can handle unsupported types at that stage too. Thus:
list($img_width,$img_height, $type) = getimagesize($source_file); // Get the original dimentions
if ($type != 1 && $type != 2 && $type != 3 && $type != 15)
. and then later check the type again to open the image correctly:
Please note that there is a bug report open for the currently broken safe_mode behaviour on this function:
According to the PHP staffer who has responded the docs are wrong (I don’t agree but I’m also not their employee).
The work around is to use touch() (or any other file system function that can do this) to create the file first before using imagejpeg().
Here is the simple, but powerful script for creating thumbnails on the fly.
You can include the script
directly to www page — just put it in <img src= tag.
with width 150pix.
This resizer respects the ASPECT RATIO.
Here is the script:
<?php
// Use it this way: resize.php?pic=imageurl&width=width_in_pixels
// kokesh@kokeshnet.com 2004
header ( «Content-type: image/jpeg» );
$im = imagecreatefromjpeg ( $pic );
$orange = imagecolorallocate ( $im , 220 , 210 , 60 );
$px = ( imagesx ( $im ) — 7.5 * strlen ( $string )) / 2 ;
$old_x = imageSX ( $im );
$old_y = imageSY ( $im );
$new_w =(int)( $width );
if (( $new_w <= 0 ) or ( $new_w > $old_x )) <
$new_w = $old_x ;
>
$new_h =( $old_x *( $new_w / $old_x ));
if ( $old_x > $old_y ) <
$thumb_w = $new_w ;
$thumb_h = $old_y *( $new_h / $old_x );
>
if ( $old_x < $old_y ) <
$thumb_w = $old_x *( $new_w / $old_y );
$thumb_h = $new_h ;
>
if ( $old_x == $old_y ) <
$thumb_w = $new_w ;
$thumb_h = $new_h ;
>
$thumb = ImageCreateTrueColor ( $thumb_w , $thumb_h );
imagecopyresized ( $thumb , $im , 0 , 0 , 0 , 0 , $thumb_w , $thumb_h , $old_x , $old_y );
imagejpeg ( $thumb , «» , 90 );
imagedestroy ( $thumb );
?>
A word of warning when outputting images to the browser.
Make sure there is no extra spaces around the <?php ?> tags, in the file you are editing, and also any included files.
I began to think there was a bug in GD or something, and I checked the file I was working on, but forgot about the includes.
[Editor’s note: fixed according to the note of roberto at ilpiola.it]
I could not find any information on changing the DPI information on a JPG file using the GD lib. Since changing this does not resize or scale the actual image, it is only a header-setting.
The following snipplet will save your $image to $file and set the DPI to 150.
imagejpeg ( $image , $file , 75 );
// Change DPI
$dpi_x = 150 ;
$dpi_y = 150 ;
// Read the file
$size = filesize ( $file );
$image = file_get_contents ( $file );
// Update DPI information in the JPG header
$image [ 13 ] = chr ( 1 );
$image [ 14 ] = chr ( floor ( $dpi_x / 256 ));
$image [ 15 ] = chr ( $dpi_x % 256 );
$image [ 16 ] = chr ( floor ( $dpi_y / 256 ));
$image [ 17 ] = chr ( $dpi_y % 256 );
// Write the new JPG
$f = fopen ( $file , ‘w’ );
fwrite ( $f , $msg , $size );
fclose ( $f );
?>
P.s. not fully tested (yet) but it works for my images .
Don’t forget that JPEG compression has artifacts! And they’re not all really obvious. The PHP JPEG compression is pretty decent, but it seems to generally:
-Lighten the image overall, by a reasonable amount (never seen this before, but it will drive graphic designers crazy, you might want to darken the image before compressing it)
-Reduce saturation, especially with images with lots of points of different color within a few pixels of each other (this is a documented feature of JPEG)
-Seriously mess with blue colors, which is common to all JPEG but really annoying in some situations with blue and black or other detailed blue parts
You might want to consider using imagepng() and outputting a PNG image instead of a JPEG if any of the above affect you, or your image is not very photo-like. Sometimes I have an algorithm compare JPEG to PNG for an image and send the smaller version to the user.
Also, when using imagepng(), you should use imageinterlace() before it 95% of the time. Interlaced JPEGs load progressively, improving in quality as the image loads, so users on slower connections see the whole image at low quality. All this happens without affecting the file size (actually, sometimes the file size is smaller!) or final quality.
Hope this helps a few people out. It’s not all that obvious without lots of playing around.
Don’t be like me racking my brain for hours trying to figure out why my xxx.php file outputs http://localhost/xxx.php as a one line response.
Most likely, you have either:
1. whitespaces before or after the php tags
2. need to set header(‘Content-type: image/jpeg’);
3. if you have required files. be sure nothing is outputted. no test print statements because page expects image information
4. there is an error in your code
in my case, it was 4. there is a reason why the function call base64decode does not work.
it’s actually: base64_decode()
by the way, other ways to validate your image encoded in base64 is to use the following tag:
echo ‘<img jpeg;base64,’.$row[‘IMAGE’].'» alt=»photo»>’;
I was pulling a blob encoded base 64 data from mysql database and trying to render it on a page
hope this helps someone.
Here is sample function that creates thumbnail of source JPEG file. Thumbnail wil be in square form (with and height are the same), and original image cropped to fit in.
$p_thumb_file — name of the file (including path) where thumb should be saved to
$p_photo_file — nam of the source JPEG file (including path) thatthumbnail should be created of
$p_max_size — with and height (they will be the same) in pixels for thumbnail image
$p_quality — quality of jpeg thumbnail
function photoCreateCropThumb ( $p_thumb_file , $p_photo_file , $p_max_size , $p_quality = 75 ) <
$pic = @ imagecreatefromjpeg ( $p_photo_file );
if ( $pic ) <
$thumb = @ imagecreatetruecolor ( $p_max_size , $p_max_size ) or die ( «Can’t create Image!» );
$width = imagesx ( $pic );
$height = imagesy ( $pic );
if ( $width < $height ) <
$twidth = $p_max_size ;
$theight = $twidth * $height / $width ;
imagecopyresized ( $thumb , $pic , 0 , 0 , 0 , ( $height / 2 )-( $width / 2 ), $twidth , $theight , $width , $height );
> else <
$theight = $p_max_size ;
$twidth = $theight * $width / $height ;
imagecopyresized ( $thumb , $pic , 0 , 0 , ( $width / 2 )-( $height / 2 ), 0 , $twidth , $theight , $width , $height );
>
ImageJPEG ( $thumb , $p_thumb_file , $p_quality );
>
Rewrote the manual example into this function for creating a thumbnail image:
function thumbnail_jpeg ($original, $thumbnail, $width, $height, $quality) <
list($width_orig, $height_orig) = getimagesize($original);
if ($width && ($width_orig < $height_orig)) <
$width = ($height / $height_orig) * $width_orig;
>
else <
$height = ($width / $width_orig) * $height_orig;
>
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($originial);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);
imagejpeg($image_p, $thumbnail, $quality);
return;
>
function create_thumbnail( $source_file, $destination_file, $max_dimension)
<
list($img_width,$img_height) = getimagesize($source_file); // Get the original dimentions
$aspect_ratio = $img_width / $img_height;
if ( ($img_width > $max_dimension) || ($img_height > $max_dimension) ) // If either dimension is too big.
<
if ( $img_width > $img_height ) // For wide images.
<
$new_width = $max_dimension;
$new_height = $new_width / $aspect_ratio;
>
elseif ( $img_width < $img_height ) // For tall images.
<
$new_height = $max_dimension;
$new_width = $new_height * $aspect_ratio;
>
elseif ( $img_width == $img_height ) // For square images.
<
$new_width = $max_dimension;
$new_height = $max_dimension;
>
else < echo "Error reading image size."; return FALSE; >
>
else < $new_width = $img_width; $new_height = $img_height; >// If it’s already smaller, don’t change the size.
// Make sure these are integers.
$new_width = intval($new_width);
$new_height = intval($new_height);
$thumbnail = imagecreatetruecolor($new_width,$new_height); // Creates a new image in memory.
// The following block retrieves the source file. It assumes the filename extensions match the file’s format.
if ( strpos($source_file,».gif») ) < $img_source = imagecreatefromgif($source_file); >
if ( (strpos($source_file,».jpg»)) || (strpos($source_file,».jpeg»)) )
< $img_source = imagecreatefromjpeg($source_file); >
if ( strpos($source_file,».bmp») ) < $img_source = imagecreatefromwbmp($source_file); >
if ( strpos($source_file,».png») )
// Here we resample and create the new jpeg.
imagecopyresampled($thumbnail, $img_source, 0, 0, 0, 0, $new_width, $new_height, $img_width, $img_height);
imagejpeg( $thumbnail, $destination_file, 100 );
// Finally, we destroy the two images in memory.
imagedestroy($img_source);
imagedestroy($thumbnail);
>
Создание изображения
PHP позволяет динамически создавать изображения. Конечно, не имеет смысла рисовать на PHP какие-то сложные картинки. Для этого есть графические редакторы. Зато можно рисовать изображения, привязанные к контенту. Прежде всего, графики. Но можно создавать и другие изображения.
Функции для создания изображения
Функция imageCreateTrueColor() создаёт новое изображение и возвращает дескриптор для дальнейшей работы с ним. На этом этапе картинка не отображается, она есть только в программе.
ImageCreateTrueColor (ширина, высота)
При создании изображение представляет собой прямоугольник чёрного цвета.
В примере создано изображение размером 200 на 70 пикселей.
Напомню, что в PHP имена функций не чувствительны к регистру символов. И это можно использовать. В отличие от большинства функций PHP, в функциях рисования слова не разделены знаком нижнего подчёркивания. Чтобы визуально отделить слова друг от друга, можно начинать их с большой буквы. Так читать код программы будет гораздо проще.
Есть ещё функция imageCreate() . Она работает почти также, но создаёт не полноцветное, а палитровое изображение. В нём используются не все цвета, а только набор доступных цветов. Работать с ним неудобно.
Вывод картинки
Чтобы сервер правильно отправлял картинку, в скрипте должен быть заголовок ContentType с указанием MIME-типа контента. Напомню, что во всех примерах этого учебника во 2 строке предполагается установка типа text/html. Но для изображений он другой. В примерах этой главы ContentType будет указан.
Для вывода картинки в браузер или в файл используется несколько функций, каждая из которых создаёт изображение своего формата. Например imageJpeg() выводит картинку в формате jpeg.
imageJpeg (изображение, файл, качество)
изображение — дескриптор изображения
файл — путь к файлу. Если NULL или не указан, то изображение выводится в поток.
качество — от 0 до 100. Влияет на размер файла. По умолчанию 75
Вот пример скрипта, который создаёт картинку и выводит на экран:
2 — Устанавливаем MIME-тип контента: изображение в формате jpeg
3 — Создаём изображение
4, 5 — Рисуем синий прямоугольник. Изучим это позже
6 — Выводим на экран
Функция imagepng() выводит картинку в формате PNG.
imagepng (изображение, файл, сжатие, фильтры)
изображение — дескриптор изображения
файл — путь к файлу
сжатие — от 0 до 9. По умолчанию установлено 0
фильтры — указываются с помощью констант, в том числе PNG_NO_FILTER и PNG_ALL_FILTERS
Если картинка выводится в поток, то сжатие и фильтры указываются обязательно.
Функция imagegif() выводит картинку в формате GIF.
imagegif (изображение, файл)
Функция imagewbmp() выводит в формате WBMP.
imagewbmp (изображение, файл, верхний слой)
изображение — дескриптор изображения
файл — путь к файлу
верхний слой — позволяет указать цвет верхнего слоя. О создании цвета рассказывается в следующей теме
Все функции работают по одному принципу: если путь к файлу указан, то картинка сохраняется в файл. А если установлен NULL или не указан, то рисунок выводится в поток.
imagejpeg
Функция imagejpeg() создаёт файл JPEG из изображения image .
Список параметров
Ресурс изображения, полученный одной из функций создания изображений, например, такой как imagecreatetruecolor() .
Путь для сохранения файла. Если не установлен или равен NULL , изображение будет выведено в поток вывода в бинарном виде.
Если вы хотите пропустить этот параметр и использовать quality , то укажите NULL .
Необязательный параметр, и может принимать значения в диапазоне от 0 (низкое качество, маленький размер файла) до 100 (высокое качество, большой размер файла). По умолчанию используется качество IJG (около 75).
Возвращаемые значения
Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.
Примеры
Пример #1 Вывод JPEG-изображения
<?php
// Создаём пустое изображение и добавляем текст
$im = imagecreatetruecolor ( 120 , 20 );
$text_color = imagecolorallocate ( $im , 233 , 14 , 91 );
imagestring ( $im , 1 , 5 , 5 , ‘A Simple Text String’ , $text_color );
// Устанавливаем тип содержимого в заголовок, в данном случае image/jpeg
header ( ‘Content-Type: image/jpeg’ );
// Выводим изображение
imagejpeg ( $im );
// Освобождаем память
imagedestroy ( $im );
?>
Результатом выполнения данного примера будет что-то подобное:
Пример #2 Сохранение изображения JPEG
<?php
// Создаём пустое изображение и добавляем текст
$im = imagecreatetruecolor ( 120 , 20 );
$text_color = imagecolorallocate ( $im , 233 , 14 , 91 );
imagestring ( $im , 1 , 5 , 5 , ‘A Simple Text String’ , $text_color );
// Сохраняем изображение в ‘simpletext.jpg’
imagejpeg ( $im , ‘simpletext.jpg’ );
// Освобождаем память
imagedestroy ( $im );
?>
Пример #3 Вывод JPEG-изображения с 75% качеством
<?php
// Создаём пустое изображение и добавляем текст
$im = imagecreatetruecolor ( 120 , 20 );
$text_color = imagecolorallocate ( $im , 233 , 14 , 91 );
imagestring ( $im , 1 , 5 , 5 , ‘A Simple Text String’ , $text_color );
// Устанавливаем тип содержимого в заголовок, в данном случае image/jpeg
header ( ‘Content-Type: image/jpeg’ );
// Пропускаем параметр filename, используя NULL, а затем устанавливаем качество в 75%
imagejpeg ( $im , NULL , 75 );
// Освобождаем память
imagedestroy ( $im );
?>
Примечания
Замечание: Поддержка JPEG доступна только в случае, если PHP был скомпилирован с GD-1.8 или более поздней версии.
Замечание:
Если требуется вывести Progressive JPEG (прогрессивное представление данных), то необходимо использовать функцию imageinterlace() для активации соответствующего режима.