On upload of images, the code creates several different thumbnails. In some cases, the thumbnail may be larger than the original image, in which case a padding is applied. In the case of JPEGs, the padding is white, and all is well. In the case of GIFs and PNGs, the padding should be transparent. And it is. Or not. Which is weird.
If I was getting an entirely black or transparent padding, I'd have some idea where the problem is, but I'm getting paddings which are transparent in places and black in others, which makes no sense.
Sample PNG and GIF images at http://filedump.xn--es-zka.info/broken_thumbs/ (on a shocking pink background colour so you can see the difference between white and transparent).
Any bright ideas?
class Image {
public static function exec($path) {
// This function receives the path to an image.
// Logic here skipped: For each thumbnail, check whether Crop is set. If it is, call self::crop(). Otherwise, call self::resize().
return true;
}
public static function resize($file, $class, $width='-', $height='-', $fit=0) {
$a = getimagesize($file);
switch ($a[2]) {
case 1:
$tag = 'gif';
break;
case 2:
$tag = 'jpeg';
break;
case 3:
$tag = 'png';
break;
default:
return;
}
$w = $a[0];
$h = $a[1];
if ($width == 0) {
$fw = 0;
$fh = $h / $height;
} elseif ($height == 0) {
$fw = $w / $width;
$fh = 0;
} else {
$fw = $w / $width;
$fh = $h / $height;
}
if (($fw == 1) and ($fh == 1)) {
$file2 = dirname($file) . '/' . $class . basename($file);
copy($file, $file2);
return true;
} elseif (($fw >= 1) and ($fh >= 1)) {
if ($fw > $fh) {
$w = $width;
$h = floor($h / $fw);
} else {
$h = $height;
$w = floor($w / $fh);
}
} elseif ($fh == 0) {
if ($fw > 1) {
$fit = 0;
$w = $width;
$h = floor($h / $fw);
} else {
if ($fit) {
$height = $h;
}
}
} elseif ($fw == 0) {
if ($fh > 1) {
$fit = 0;
$w = floor($w / $fh);
$h = $height;
} else {
if ($fit) {
$width = $w;
}
}
} elseif (($fw < 1) and ($fh < 1)) {
//
} elseif ($fw > $fh) {
if ($fw >= 1) {
$w = $width;
$h = floor($h / $fw);
}
} elseif ($fh > $fw) {
if ($fh >= 1) {
$w = floor($w / $fh);
$h = $height;
}
}
if ($fit) {
$x = ($width - $w) / 2;
$y = ($height - $h) / 2;
$cw = $width;
$ch = $height;
} else {
$x = 0;
$y = 0;
$cw = $w;
$ch = $h;
}
$file2 = dirname($file) . '/' . $class . basename($file);
$f1 = 'imagecreatefrom' . $tag;
$src = $f1($file);
$new = imagecreatetruecolor($cw, $ch);
return self::create($new, $src, $file2, $x, $y, $w, $h, $a);
}
public static function crop($file, $class, $width='-', $height='-', $fit=0) {
if (!$class) return trigger_error('ExecImage: Original image can not be overwritten.');
$small = 0;
$a = getimagesize($file);
switch ($a[2]) {
case 1:
$tag = 'gif';
break;
case 2:
$tag = 'jpeg';
break;
case 3:
$tag = 'png';
break;
default:
return;
}
$w = $a[0];
$h = $a[1];
if ($height == 0) {
//resize by width -- height will follow
$fh = 0;
$fw = $w / $width;
} elseif ($width == 0) {
//resize by height -- width will follow
$fw = 0;
$fh = $h / $height;
} else {
$fw = $w / $width;
$fh = $h / $height;
}
if (($fw <= 1) and ($fh <= 1)) {
$small = 1;
//don't resize
} else {
$fit = 1;
//chop by the smallest
if ($fh < $fw) {
//Crop By Height
$h = $height;
$w = floor($w / $fh);
//$w = $width;
//$h = floor($h /$fw);
//$w = $width;
} else {
//Crop By Width
$w = $width;
$h = floor($h /$fw);
//$h = $height;
//$w = floor($w / $fh);
}
}
$file2 = dirname($file) . '/' . $class . basename($file);
$f1 = 'imagecreatefrom' . $tag;
$src = $f1($file);
if ($small) {
if ($fit) {
//image must be padded
$x = ($width - $w) / 2;
$y = ($height - $h) / 2;
} else {
//image goes as is -- shrinked
$x = 0;
$y = 0;
}
} else {
//image must be centered -- this should be a square from js
$x = ($width - $w) / 2;
$y = ($height - $h) / 2;
}
if ($small) {
if ($fit) {
//create with the full size
$new = imagecreatetruecolor($width, $height);
} else {
//nah, just with the original size
$new = imagecreatetruecolor($w, $h);
}
} else {
if ($fit) {
$new = imagecreatetruecolor($width, $height);
} else {
$new = imagecreatetruecolor($w, $h);
}
}
return self::create($new, $src, $file2, $x, $y, $w, $h, $a);
}
private static function create($new, $src, $file2, $x, $y, $w, $h, $a) {
switch ($a[2]) {
case 1: // GIF
case 3: // PNG
// http://www.akemapa.com/2008/07/10/php-gd-resize-transparent-image-png-gif/
// http://www.mummey.org/2008/11/transparent-gifs-with-php-and-gd/
imagealphablending($new, false);
imagesavealpha($new, true);
$back = imagecolorallocatealpha($new, 255, 255, 255, 127);
imagefilledrectangle($new, 0, 0, $w, $h, $back);
imagecolortransparent($new, $back);
break;
case 2: // JPEG
$back = imagecolorallocate($new, 255, 255, 255);
break;
}
imagefill($new, 0, 0, $back);
imagecopyresampled($new, $src, $x, $y, 0, 0, $w, $h, $a[0], $a[1]);
if (file_exists($file2)) unlink($file2);
switch ($a[2]) {
case 1:
imagegif($new, $file2);
break;
case 2:
imagejpeg($new, $file2, 100);
break;
case 3:
imagepng($new, $file2, 0);
break;
}
imagedestroy($src);
imagedestroy($new);
return true;
}
}
Revision/Edit to add:
Well, I've solved the main problem: padding added to PNG or GIF images is now transparent, instead of black. The smaller problem, that GIF transparency becomes black, is still with us, but I don't use GIF transparency much.
<?php
class Image {
public static function exec($path) {
$file = Nearest::file('.config.php', dirname($path) . '/', BD . '/images/');
if (!file_exists($file)) exit('The ".config.php" file doesnt exist');
require $file;
foreach ($config['operations'] as $k => $v) {
if (!isset($v['class'])) $v['class'] = '.' . $k . '.';
if (Core::val($v, 'crop')) {
self::crop($path, $v['class'], Core::val($v, 'width', '-'), Core::val($v, 'height', '-'), Core::val($v, 'fit', 0));
} else {
self::resize($path, $v['class'], Core::val($v, 'width', '-'), Core::val($v, 'height', '-'), Core::val($v, 'fit', 0));
}
}
return true;
}
public static function delete($path) {
$a = glob(dirname($path) . '/.*.' . basename($path));
foreach ($a as $v) unlink($v);
unlink($path);
}
public static function resize($file, $class, $width='-', $height='-', $fit=0) {
$a = getimagesize($file);
switch ($a[2]) {
case 1:
$tag = 'gif';
break;
case 2:
$tag = 'jpeg';
break;
case 3:
$tag = 'png';
break;
default:
return;
}
$w = $a[0];
$h = $a[1];
if ($width == 0) {
$fw = 0;
$fh = $h / $height;
} elseif ($height == 0) {
$fw = $w / $width;
$fh = 0;
} else {
$fw = $w / $width;
$fh = $h / $height;
}
if (($fw == 1) and ($fh == 1)) {
$file2 = dirname($file) . '/' . $class . basename($file);
copy($file, $file2);
return true;
} elseif (($fw >= 1) and ($fh >= 1)) {
if ($fw > $fh) {
$w = $width;
$h = floor($h / $fw);
} else {
$h = $height;
$w = floor($w / $fh);
}
} elseif ($fh == 0) {
if ($fw > 1) {
$fit = 0;
$w = $width;
$h = floor($h / $fw);
} else {
if ($fit) {
$height = $h;
}
}
} elseif ($fw == 0) {
if ($fh > 1) {
$fit = 0;
$w = floor($w / $fh);
$h = $height;
} else {
if ($fit) {
$width = $w;
}
}
} elseif (($fw < 1) and ($fh < 1)) {
//
} elseif ($fw > $fh) {
if ($fw >= 1) {
$w = $width;
$h = floor($h / $fw);
}
} elseif ($fh > $fw) {
if ($fh >= 1) {
$w = floor($w / $fh);
$h = $height;
}
}
if ($fit) {
$x = ($width - $w) / 2;
$y = ($height - $h) / 2;
$cw = $width;
$ch = $height;
} else {
$x = 0;
$y = 0;
$cw = $w;
$ch = $h;
}
$file2 = dirname($file) . '/' . $class . basename($file);
$f1 = 'imagecreatefrom' . $tag;
$src = $f1($file);
$new = imagecreatetruecolor($cw, $ch);
return self::create($new, $src, $file2, $x, $y, $w, $h, $cw, $ch, $a);
}
public static function crop($file, $class, $width='-', $height='-', $fit=0) {
if (!$class) exit('ExecImage: Original image can not be overwrite.');
$small = 0;
$a = getimagesize($file);
switch ($a[2]) {
case 1:
$tag = 'Gif';
break;
case 2:
$tag = 'Jpeg';
break;
case 3:
$tag = 'Png';
break;
default:
return;
}
$w = $a[0];
$h = $a[1];
if ($height == 0) {
//resize by width -- height will follow
$fh = 0;
$fw = $w / $width;
} elseif ($width == 0) {
//resize by height -- width will follow
$fw = 0;
$fh = $h / $height;
} else {
$fw = $w / $width;
$fh = $h / $height;
}
if (($fw <= 1) and ($fh <= 1)) {
$small = 1;
//dont resize
} else {
$fit = 1;
//chop by the smallest
if ($fh < $fw) {
//Crop By Height
$h = $height;
$w = floor($w / $fh);
//$w = $width;
//$h = floor($h /$fw);
//$w = $width;
} else {
//Crop By Width
$w = $width;
$h = floor($h /$fw);
//$h = $height;
//$w = floor($w / $fh);
}
}
$file2 = dirname($file) . '/' . $class . basename($file);
$f1 = 'ImageCreateFrom' . $tag;
$src = $f1($file);
if ($small) {
if ($fit) {
//image must be padded
$x = ($width - $w) / 2;
$y = ($height - $h) / 2;
} else {
//image goes as is -- shrinked
$x = 0;
$y = 0;
}
} else {
//image must be centered -- this should be a square from js
$x = ($width - $w) / 2;
$y = ($height - $h) / 2;
}
if ($small) {
if ($fit) {
//create with the full size
$new = imagecreatetruecolor($width, $height);
return self::create($new, $src, $file2, $x, $y, $w, $h, $width, $height, $a);
} else {
//nah, just with the original size
$new = imagecreatetruecolor($w, $h);
return self::create($new, $src, $file2, $x, $y, $w, $h, $w, $h, $a);
}
} else {
if ($fit) {
//create with the full size
$new = imagecreatetruecolor($width, $height);
return self::create($new, $src, $file2, $x, $y, $w, $h, $width, $height, $a);
} else {
//nah, just with the original size
$new = imagecreatetruecolor($w, $h);
return self::create($new, $src, $file2, $x, $y, $w, $h, $w, $h, $a);
}
}
}
private static function create($new, $src, $file2, $x, $y, $w, $h, $cw, $ch, $a) {
switch ($a[2]) {
case 1: // GIF
case 3: // PNG
// http://www.akemapa.com/2008/07/10/php-gd-resize-transparent-image-png-gif/
// http://www.mummey.org/2008/11/transparent-gifs-with-php-and-gd/
imagealphablending($new, false);
imagesavealpha($new, true);
$back = imagecolorallocatealpha($new, 255, 255, 255, 127);
imagefilledrectangle($new, 0, 0, $cw, $ch, $back);
imagecolortransparent($new, $back);
break;
case 2: // JPEG
$back = imagecolorallocate($new, 255, 255, 255);
break;
}
imagefill($new, 0, 0, $back);
imagecopyresampled($new, $src, $x, $y, 0, 0, $w, $h, $a[0], $a[1]);
if (file_exists($file2)) unlink($file2);
switch ($a[2]) {
case 1:
imagegif($new, $file2);
break;
case 2:
imagejpeg($new, $file2, 100);
break;
case 3:
imagepng($new, $file2, 0);
break;
}
imagedestroy($src);
imagedestroy($new);
return true;
}
}
So, any hints on how to preserve GIF transparency?
You put a link with your answer ;)
You're using imageCopyResampled which acts weird with alpha. Use imageCopyResized instead.
http://www.mummey.org/2008/11/transparent-gifs-with-php-and-gd/comment-page-1/#comment-94
Related
I use GD library to upload / process photos, but when uploading a photo via Android or some mobile phone, photos are not uploaded correctly as an orientation. I have a site where users can upload photos from mobile, but all the photos that are uploaded from mobiles, show 90 degrees to the left when upload.
I now the problem is the exeif but i tried using a plugin but is not working. Any help is recommended.
Share my script code is:
CImageHandler.php
/**
* Image handler
* #author Yaroslav Pelesh aka Tokolist http://tokolist.com
* #link https://github.com/tokolist/yii-components
* #version 1.2
* #license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
ini_set('memory_limit', '8192M');
class CImageHandler extends CApplicationComponent
{
private $originalImage = null;
private $image = null;
private $format = 0;
private $width = 0;
private $height = 0;
private $mimeType = '';
private $fileName = '';
public $transparencyColor = [0, 0, 0];
const IMG_GIF = 1;
const IMG_JPEG = 2;
const IMG_PNG = 3;
const CORNER_LEFT_TOP = 1;
const CORNER_RIGHT_TOP = 2;
const CORNER_LEFT_BOTTOM = 3;
const CORNER_RIGHT_BOTTOM = 4;
const CORNER_CENTER = 5;
const CORNER_CENTER_TOP = 6;
const CORNER_CENTER_BOTTOM = 7;
const CORNER_LEFT_CENTER = 8;
const CORNER_RIGHT_CENTER = 9;
const FLIP_HORIZONTAL = 1;
const FLIP_VERTICAL = 2;
const FLIP_BOTH = 3;
public function getImage()
{
return $this->image;
}
public function getFormat()
{
return $this->format;
}
public function getWidth()
{
return $this->width;
}
public function getHeight()
{
return $this->height;
}
public function getMimeType()
{
return $this->mimeType;
}
public function __destruct()
{
$this->freeImage();
}
private function freeImage()
{
if (is_resource($this->image)) {
imagedestroy($this->image);
}
if ($this->originalImage !== null) {
if (is_resource($this->originalImage['image'])) {
imagedestroy($this->originalImage['image']);
}
$this->originalImage = null;
}
}
private function checkLoaded()
{
if (!is_resource($this->image)) {
throw new Exception('Load image first');
}
}
private function loadImage($file)
{
$result = [];
if ($imageInfo = #getimagesize($file)) {
$result['width'] = $imageInfo[0];
$result['height'] = $imageInfo[1];
$result['mimeType'] = $imageInfo['mime'];
switch ($result['format'] = $imageInfo[2]) {
case self::IMG_GIF:
if(file_exists($file)) {
$gd = #imagecreatefromstring(file_get_contents($file));
if ($gd === false) {
throw new Exception ('Invalid image gif format');
} else {
if ($result['image'] = imagecreatefromgif($file)) {
return $result;
} else {
throw new Exception('Invalid image gif format');
}
}
} else {
throw new Exception('Invalid image gif format');
}
break;
case self::IMG_JPEG:
if(file_exists($file)) {
$gd = #imagecreatefromstring(file_get_contents($file));
if ($gd === false) {
throw new Exception ('Invalid image jpeg format');
} else {
/*
//Read the JPEG image Exif data to get the Orientation value
if (function_exists('exif_read_data')) {
$exif = exif_read_data($file);
$orientation = #$exif['IFD0']['Orientation'];
if (!$orientation) {
$orientation = #$exif['Orientation'];
}
if(!$orientation) return;
$source = #imagecreatefromjpeg($file);
if(!$source) return;
switch ($orientation) {
case 1: // nothing
break;
case 2: // horizontal flip
imageflip($source, IMG_FLIP_HORIZONTAL);
break;
case 3: // 180 rotate left
$modifiedImage = imagerotate($source, 180, 0);
imagejpeg($modifiedImage, $file, 90); //save output to file system at full quality
break;
case 4: // vertical flip
imageflip($source, IMG_FLIP_VERTICAL);
break;
case 5: // vertical flip + 90 rotate right
imageflip($source, IMG_FLIP_VERTICAL);
$modifiedImage = imagerotate($source, -90, 0);
imagejpeg($modifiedImage, $file, 90); //save output to file system at full quality
break;
case 6: // 90 rotate right
$modifiedImage = imagerotate($source, -90, 0);
imagejpeg($modifiedImage, $file, 90); //save output to file system at full quality
break;
case 7: // horizontal flip + 90 rotate right
imageflip($source, IMG_FLIP_HORIZONTAL);
$modifiedImage = imagerotate($source, -90, 0);
imagejpeg($modifiedImage, $file, 90); //save output to file system at full quality
break;
case 8: // 90 rotate left
$modifiedImage = imagerotate($source, 90, 0);
imagejpeg($modifiedImage, $file, 90); //save output to file system at full quality
break;
}
}
//Read the JPEG image Exif data to get the Orientation value
*/
if ($result['image'] = #imagecreatefromjpeg($file)) {
return $result;
} else {
throw new Exception('Invalid image jpeg format');
}
}
} else {
throw new Exception('Invalid image jpeg format');
}
break;
case self::IMG_PNG:
if(file_exists($file)) {
$gd = #imagecreatefromstring(file_get_contents($file));
if ($gd === false) {
throw new Exception ('Invalid image png format');
} else {
if ($result['image'] = imagecreatefrompng($file)) {
return $result;
} else {
throw new Exception('Invalid image png format');
}
}
} else {
throw new Exception('Invalid image png format');
}
break;
default:
throw new Exception('Not supported image format');
}
} else {
throw new Exception('Invalid image file');
}
}
protected function initImage($image = false)
{
if ($image === false) {
$image = $this->originalImage;
}
$this->width = $image['width'];
$this->height = $image['height'];
$this->mimeType = $image['mimeType'];
$this->format = $image['format'];
//Image
if (is_resource($this->image))
imagedestroy($this->image);
//10-08-2018
$this->image = imagecreatetruecolor($this->width, $this->height);
$this->preserveTransparency($this->image);
imagecopy($this->image, $image['image'], 0, 0, 0, 0, $this->width, $this->height);
}
/**
* #param $file
*
* #return CImageHandler
* #throws Exception
*/
public function load($file)
{
$this->freeImage();
if (($this->originalImage = $this->loadImage($file))) {
$this->initImage();
$this->fileName = $file;
return $this;
} else {
return false;
}
}
public function reload()
{
$this->checkLoaded();
$this->initImage();
return $this;
}
private function preserveTransparency($newImage)
{
switch ($this->format) {
case self::IMG_GIF:
$color = imagecolorallocate(
$newImage,
$this->transparencyColor[0],
$this->transparencyColor[1],
$this->transparencyColor[2]
);
imagecolortransparent($newImage, $color);
imagetruecolortopalette($newImage, false, 256);
break;
case self::IMG_PNG:
imagealphablending($newImage, false);
$color = imagecolorallocatealpha(
$newImage,
$this->transparencyColor[0],
$this->transparencyColor[1],
$this->transparencyColor[2],
0
);
imagefill($newImage, 0, 0, $color);
imagesavealpha($newImage, true);
break;
}
}
public function resize($toWidth, $toHeight, $proportional = true)
{
$this->checkLoaded();
$toWidth = $toWidth !== false ? $toWidth : $this->width;
$toHeight = $toHeight !== false ? $toHeight : $this->height;
if ($proportional) {
$newHeight = $toHeight;
$newWidth = round($newHeight / $this->height * $this->width);
if ($newWidth > $toWidth) {
$newWidth = $toWidth;
$newHeight = round($newWidth / $this->width * $this->height);
}
} else {
$newWidth = $toWidth;
$newHeight = $toHeight;
}
$newImage = imagecreatetruecolor($newWidth, $newHeight);
$this->preserveTransparency($newImage);
imagecopyresampled($newImage, $this->image, 0, 0, 0, 0, $newWidth, $newHeight, $this->width, $this->height);
imagedestroy($this->image);
$this->image = $newImage;
$this->width = $newWidth;
$this->height = $newHeight;
return $this;
}
public function thumb($toWidth, $toHeight, $proportional = true)
{
$this->checkLoaded();
if ($toWidth !== false)
$toWidth = min($toWidth, $this->width);
if ($toHeight !== false)
$toHeight = min($toHeight, $this->height);
$this->resize($toWidth, $toHeight, $proportional);
return $this;
}
public function watermark($watermarkFile, $offsetX, $offsetY, $corner = self::CORNER_RIGHT_BOTTOM, $zoom = false)
{
$this->checkLoaded();
if ($wImg = $this->loadImage($watermarkFile)) {
$posX = 0;
$posY = 0;
$watermarkWidth = $wImg['width'];
$watermarkHeight = $wImg['height'];
if ($zoom !== false) {
$dimension = round(max($this->width, $this->height) * $zoom);
$watermarkHeight = $dimension;
$watermarkWidth = round($watermarkHeight / $wImg['height'] * $wImg['width']);
if ($watermarkWidth > $dimension) {
$watermarkWidth = $dimension;
$watermarkHeight = round($watermarkWidth / $wImg['width'] * $wImg['height']);
}
}
switch ($corner) {
case self::CORNER_LEFT_TOP:
$posX = $offsetX;
$posY = $offsetY;
break;
case self::CORNER_RIGHT_TOP:
$posX = $this->width - $watermarkWidth - $offsetX;
$posY = $offsetY;
break;
case self::CORNER_LEFT_BOTTOM:
$posX = $offsetX;
$posY = $this->height - $watermarkHeight - $offsetY;
break;
case self::CORNER_RIGHT_BOTTOM:
$posX = $this->width - $watermarkWidth - $offsetX;
$posY = $this->height - $watermarkHeight - $offsetY;
break;
case self::CORNER_CENTER:
$posX = floor(($this->width - $watermarkWidth) / 2);
$posY = floor(($this->height - $watermarkHeight) / 2);
break;
case self::CORNER_CENTER_TOP:
$posX = floor(($this->width - $watermarkWidth) / 2);
$posY = $offsetY;
break;
case self::CORNER_CENTER_BOTTOM:
$posX = floor(($this->width - $watermarkWidth) / 2);
$posY = $this->height - $watermarkHeight - $offsetY;
break;
case self::CORNER_LEFT_CENTER:
$posX = $offsetX;
$posY = floor(($this->height - $watermarkHeight) / 2);
break;
case self::CORNER_RIGHT_CENTER:
$posX = $this->width - $watermarkWidth - $offsetX;
$posY = floor(($this->height - $watermarkHeight) / 2);
break;
default:
throw new Exception('Invalid $corner value');
}
imagecopyresampled(
$this->image,
$wImg['image'],
$posX,
$posY,
0,
0,
$watermarkWidth,
$watermarkHeight,
$wImg['width'],
$wImg['height']
);
imagedestroy($wImg['image']);
return $this;
} else {
return false;
}
}
public function flip($mode)
{
$this->checkLoaded();
$srcX = 0;
$srcY = 0;
$srcWidth = $this->width;
$srcHeight = $this->height;
switch ($mode) {
case self::FLIP_HORIZONTAL:
$srcX = $this->width - 1;
$srcWidth = -$this->width;
break;
case self::FLIP_VERTICAL:
$srcY = $this->height - 1;
$srcHeight = -$this->height;
break;
case self::FLIP_BOTH:
$srcX = $this->width - 1;
$srcY = $this->height - 1;
$srcWidth = -$this->width;
$srcHeight = -$this->height;
break;
default:
throw new Exception('Invalid $mode value');
}
$newImage = imagecreatetruecolor($this->width, $this->height);
$this->preserveTransparency($newImage);
imagecopyresampled($newImage, $this->image, 0, 0, $srcX, $srcY, $this->width, $this->height, $srcWidth, $srcHeight);
imagedestroy($this->image);
$this->image = $newImage;
//dimensions not changed
return $this;
}
public function rotate($degrees)
{
$this->checkLoaded();
$degrees = (int)$degrees;
$this->image = imagerotate($this->image, $degrees, 0);
$this->width = imagesx($this->image);
$this->height = imagesy($this->image);
return $this;
}
public function crop($width, $height, $startX = false, $startY = false)
{
$this->checkLoaded();
$width = (int)$width;
$height = (int)$height;
//Centered crop
$startX = $startX === false ? floor(($this->width - $width) / 2) : intval($startX);
$startY = $startY === false ? floor(($this->height - $height) / 2) : intval($startY);
//Check dimensions
$startX = max(0, min($this->width, $startX));
$startY = max(0, min($this->height, $startY));
$width = min($width, $this->width - $startX);
$height = min($height, $this->height - $startY);
$newImage = imagecreatetruecolor($width, $height);
$this->preserveTransparency($newImage);
imagecopyresampled($newImage, $this->image, 0, 0, $startX, $startY, $width, $height, $width, $height);
imagedestroy($this->image);
$this->image = $newImage;
$this->width = $width;
$this->height = $height;
return $this;
}
public function text($text, $fontFile, $size = 12, $color = [0, 0, 0],
$corner = self::CORNER_LEFT_TOP, $offsetX = 0, $offsetY = 0, $angle = 0, $alpha = 0)
{
$this->checkLoaded();
$bBox = imagettfbbox($size, $angle, $fontFile, $text);
$textHeight = $bBox[1] - $bBox[7];
$textWidth = $bBox[2] - $bBox[0];
switch ($corner) {
case self::CORNER_LEFT_TOP:
$posX = $offsetX;
$posY = $offsetY;
break;
case self::CORNER_RIGHT_TOP:
$posX = $this->width - $textWidth - $offsetX;
$posY = $offsetY;
break;
case self::CORNER_LEFT_BOTTOM:
$posX = $offsetX;
$posY = $this->height - $textHeight - $offsetY;
break;
case self::CORNER_RIGHT_BOTTOM:
$posX = $this->width - $textWidth - $offsetX;
$posY = $this->height - $textHeight - $offsetY;
break;
case self::CORNER_CENTER:
$posX = floor(($this->width - $textWidth) / 2);
$posY = floor(($this->height - $textHeight) / 2);
break;
case self::CORNER_CENTER_TOP:
$posX = floor(($this->width - $textWidth) / 2);
$posY = $offsetY;
break;
case self::CORNER_CENTER_BOTTOM:
$posX = floor(($this->width - $textWidth) / 2);
$posY = $this->height - $textHeight - $offsetY;
break;
case self::CORNER_LEFT_CENTER:
$posX = $offsetX;
$posY = floor(($this->height - $textHeight) / 2);
break;
case self::CORNER_RIGHT_CENTER:
$posX = $this->width - $textWidth - $offsetX;
$posY = floor(($this->height - $textHeight) / 2);
break;
default:
throw new Exception('Invalid $corner value');
}
if ($alpha > 0) {
$color = imagecolorallocatealpha($this->image, $color[0], $color[1], $color[2], $alpha);
} else {
$color = imagecolorallocate($this->image, $color[0], $color[1], $color[2]);
}
imagettftext($this->image, $size, $angle, $posX, $posY + $textHeight, $color, $fontFile, $text);
return $this;
}
public function adaptiveThumb($width, $height)
{
$this->checkLoaded();
$width = intval($width);
$height = intval($height);
$widthProportion = $width / $this->width;
$heightProportion = $height / $this->height;
if ($widthProportion > $heightProportion) {
$newWidth = $width;
$newHeight = round($newWidth / $this->width * $this->height);
} else {
$newHeight = $height;
$newWidth = round($newHeight / $this->height * $this->width);
}
$this->resize($newWidth, $newHeight);
$this->crop($width, $height);
return $this;
}
public function resizeCanvas($toWidth, $toHeight, $backgroundColor = [255, 255, 255])
{
$this->checkLoaded();
$newWidth = min($toWidth, $this->width);
$newHeight = min($toHeight, $this->height);
$widthProportion = $newWidth / $this->width;
$heightProportion = $newHeight / $this->height;
if ($widthProportion < $heightProportion) {
$newHeight = round($widthProportion * $this->height);
} else {
$newWidth = round($heightProportion * $this->width);
}
$posX = floor(($toWidth - $newWidth) / 2);
$posY = floor(($toHeight - $newHeight) / 2);
$newImage = imagecreatetruecolor($toWidth, $toHeight);
$backgroundColor = imagecolorallocate($newImage, $backgroundColor[0], $backgroundColor[1], $backgroundColor[2]);
imagefill($newImage, 0, 0, $backgroundColor);
imagecopyresampled($newImage, $this->image, $posX, $posY, 0, 0, $newWidth, $newHeight, $this->width, $this->height);
imagedestroy($this->image);
$this->image = $newImage;
$this->width = $toWidth;
$this->height = $toHeight;
return $this;
}
public function grayscale()
{
$newImage = imagecreatetruecolor($this->width, $this->height);
imagecopy($newImage, $this->image, 0, 0, 0, 0, $this->width, $this->height);
imagecopymergegray($newImage, $newImage, 0, 0, 0, 0, $this->width, $this->height, 0);
imagedestroy($this->image);
$this->image = $newImage;
return $this;
}
public function show($inFormat = false, $jpegQuality = 75)
{
$this->checkLoaded();
if (!$inFormat) {
$inFormat = $this->format;
}
switch ($inFormat) {
case self::IMG_GIF:
header('Content-type: image/gif');
imagegif($this->image);
break;
case self::IMG_JPEG:
header('Content-type: image/jpeg');
imagejpeg($this->image, null, $jpegQuality);
break;
case self::IMG_PNG:
header('Content-type: image/png');
imagepng($this->image);
break;
default:
throw new Exception('Invalid image format for putput');
}
return $this;
}
public function save($file = false, $toFormat = false, $jpegQuality = 75, $touch = false)
{
if (empty($file)) {
$file = $this->fileName;
}
$this->checkLoaded();
if (!$toFormat) {
$toFormat = $this->format;
}
switch ($toFormat) {
case self::IMG_GIF:
if (!imagegif($this->image, $file)) {
throw new Exception('Can\'t save gif file');
}
break;
case self::IMG_JPEG:
if (!imagejpeg($this->image, $file, $jpegQuality)) {
throw new Exception('Can\'t save jpeg file');
}
break;
case self::IMG_PNG:
if (!imagepng($this->image, $file)) {
throw new Exception('Can\'t save png file');
}
break;
default:
throw new Exception('Invalid image format for save');
}
if ($touch && $file != $this->fileName) {
touch($file, filemtime($this->fileName));
}
return $this;
}
}
Thank you #Yanik Lupien your simple code is very nice work :)
if (function_exists('exif_read_data')) {
$buffer = imagecreatefromjpeg($file);
$exif = #exif_read_data($file);
if ($exif && !empty($exif['Orientation']))
{
switch($exif['Orientation']) {
case 8:
$buffer = imagerotate($buffer, 90, 0);
break;
case 3:
$buffer = imagerotate($buffer, 180, 0);
break;
case 6:
$buffer = imagerotate($buffer, -90, 0);
break;
case 5: // vertical flip + 90 rotate right
$buffer = imagerotate($buffer, -90, 0);
break;
case 7: // horizontal flip + 90 rotate right
$buffer = imagerotate($buffer, -90, 0);
break;
}
}
imagejpeg($buffer, $file, 90);
}
Here is a small snippet to fix rotation.
$imagePathName = 'file.jpg';
$buffer = ImageCreateFromJPEG($imagePathName);
$exif = #exif_read_data($imagePathName);
if ($exif && !empty($exif['Orientation']))
{
switch($exif['Orientation']) {
case 8:
$buffer = imagerotate($buffer, 90, 0);
break;
case 3:
$buffer = imagerotate($buffer, 180, 0);
break;
case 6:
$buffer = imagerotate($buffer, -90, 0);
break;
}
}
imagejpeg($buffer, $imagePathName, 90);
I am trying to built an option unto my site where users can upload a profile picture, so far so good, but the data is saved again and again in my database(table) when I refresh the page
++ the image doesn't show, it just shows a black square.
Thanks for any help, as you can see, I'm still an absolute beginner learning eagerly and ferociously
$images = (isset ($_FILES['images']['name']));
$paths= [];
if ($images)
{
$saveto = "uploads/$user.jpg";
move_uploaded_file($_FILES['images']['tmp_name'], $saveto);
$typeok = TRUE;
$paths[] = $saveto;
$date1=date("Y-m-d h:m:s");
$link=mysqli_connect("localhost","root","","vlindr");
mysqli_select_db($link,"imageupload"); //database connectivity
mysqli_query($link,"insert into images
(images_id, images_path, submission_date)
VALUES (NULL,'$user','$date1')")
or die(mysqli_error($link));
switch($_FILES['images']['type'])
{
case "image/gif": $src = imagecreatefromgif($saveto); break;
case "image/jpeg": // Both regular and progressive jpegs
case "image/pjpeg": $src = imagecreatefromjpeg($saveto); break;
case "image/png": $src = imagecreatefrompng($saveto); break;
default: $typeok = FALSE; break;
}
if ($typeok)
{
list($w, $h) = getimagesize($saveto);
$max = 150;
$tw = $w;
$th = $h;
if ($w > $h && $max < $w) {
$th = $max ;
$tw = $max;
}
elseif ($h > $w && $max < $h) {
$tw = $max / $h * $w;
$th = $max;
}
elseif ($max < $w) {
$tw = $th = $max;
}
$tmp = imagecreatetruecolor($tw, $th);
imagecopyresampled($tmp, $src, 0, 0, 0, 0, $tw, $th, $w, $h);
imageconvolution($tmp, array(array(-1, -1, -1),
array(-1, 16, -1),
array(-1, -1, -1)),
8, 0);
imagejpeg($tmp, $saveto);
imagedestroy($tmp);
imagedestroy($src);
}
}
Please let me know if the code below works.
I also recommend prepared statements, although the code below is not the neatest it will get the job done!
$images = (isset ($_FILES['images']['name']));
$paths= [];
if ($images)
{
$saveto = "uploads/$user.jpg";
move_uploaded_file($_FILES['images']['tmp_name'], $saveto);
$typeok = TRUE;
$paths[] = $saveto;
$date1=date("Y-m-d h:m:s");
$link=mysqli_connect("localhost","root","","vlindr");
mysqli_select_db($link,"imageupload"); //database connectivity
//Checks if Image already exists in database
$stmt = $link->prepare("SELECT * FROM images WHERE images_path=(?)");
$stmt->bind_param("s",$saveto);
$stmt->execute();
$stmt->store_result();
//If the amount of rows returned is zero, the script will insert the image into the database
if($stmt->num_rows === 0) {
//Inserts the image into the database
$stmt2 = $link->prepare("INSERT INTO images (images_id,images_path,submission_date) VALUES (NULL,?,?)");
$stmt2->bind_param("ss",$saveto,$date1);
if($stmt2->execute()) {
echo "Image is unique and uploaded to database";
}
switch($_FILES['images']['type'])
{
case "image/gif": $src = imagecreatefromgif($saveto); break;
case "image/jpeg": // Both regular and progressive jpegs
case "image/pjpeg": $src = imagecreatefromjpeg($saveto); break;
case "image/png": $src = imagecreatefrompng($saveto); break;
default: $typeok = FALSE; break;
}
if ($typeok)
{
list($w, $h) = getimagesize($saveto);
$max = 150;
$tw = $w;
$th = $h;
if ($w > $h && $max < $w)
{
$th = $max ;
$tw = $max;
}
elseif ($h > $w && $max < $h)
{
$tw = $max / $h * $w;
$th = $max;
}
elseif ($max < $w)
{
$tw = $th = $max;
}
$tmp = imagecreatetruecolor($tw, $th);
imagecopyresampled($tmp, $src, 0, 0, 0, 0, $tw, $th, $w, $h);
imageconvolution($tmp, array(array(-1, -1, -1),
array(-1, 16, -1), array(-1, -1, -1)), 8, 0);
imagejpeg($tmp, $saveto);
imagedestroy($tmp);
imagedestroy($src);
}
}//end if
else {
echo "Image Already Exists";
}//end else
I want to add watermark on image when i upload in CakePHP. I found many components on Google but I don't know how to use them like ImageTool, Qimage etc. I don't know what value should pass to component function to add watermark. Could anybody help me.
Here is the ImageToolComponent::watermark() function:-
public static function watermark($options = array()) {
$options = array_merge(array(
'afterCallbacks' => null,
'scale' => false,
'strech' => false,
'repeat' => false,
'watermark' => null,
'output' => null,
'input' => null,
'position' => 'center',
'compression' => 9,
'quality' => 100,
'chmod' => null,
'opacity' => 100
), $options);
// if output path (directories) doesn’t exist, try to make whole path
if (!self::createPath($options['output'])) {
return false;
}
$img = self::openImage($options['input']);
unset($options['input']);
if (empty($img)) {
return false;
}
$src_wm = self::openImage($options['watermark']);
unset($options['watermark']);
if (empty($src_wm)) {
return false;
}
// image size
$img_im_w = imagesx($img);
$img_im_h = imagesy($img);
// watermark size
$img_wm_w = imagesx($src_wm);
$img_wm_h = imagesy($src_wm);
if ($options['scale']) {
if ($options['strech']) {
$r = imagecopyresampled($img, $src_wm, 0, 0, 0, 0, $img_im_w, $img_im_h, $img_wm_w, $img_wm_h);
} else {
$x = 0;
$y = 0;
$w = $img_im_w;
$h = $img_im_h;
if (($img_im_w / $img_im_h) > ($img_wm_w / $img_wm_h)) {
$ratio = $img_im_h / $img_wm_h;
$w = $ratio * $img_wm_w;
$x = round(($img_im_w - $w) / 2);
} else {
$ratio = $img_im_w / $img_wm_w;
$h = $ratio * $img_wm_h;
$y = round(($img_im_h - $h) / 2);
}
$r = imagecopyresampled($img, $src_wm, $x, $y, 0, 0, $w, $h, $img_wm_w, $img_wm_h);
}
} else if ($options['repeat']) {
if (is_array($options['position'])) {
$options['position'] = 5;
}
switch ($options['position']) {
case 'top-left':
for ($y = 0; $y < $img_im_h; $y+=$img_wm_h) {
for ($x = 0; $x < $img_im_w; $x+=$img_wm_w) {
$r = self::imagecopymerge_alpha($img, $src_wm, $x, $y, 0, 0, $img_wm_w, $img_wm_h, $options['opacity']);
}
}
break;
case 'top-right':
for ($y = 0; $y < $img_im_h; $y+=$img_wm_h) {
for ($x = $img_im_w; $x > -$img_wm_w; $x-=$img_wm_w) {
$r = self::imagecopymerge_alpha($img, $src_wm, $x, $y, 0, 0, $img_wm_w, $img_wm_h, $options['opacity']);
}
}
break;
case 'bottom-right':
for ($y = $img_im_h; $y > -$img_wm_h; $y-=$img_wm_h) {
for ($x = $img_im_w; $x > -$img_wm_w; $x-=$img_wm_w) {
$r = self::imagecopymerge_alpha($img, $src_wm, $x, $y, 0, 0, $img_wm_w, $img_wm_h, $options['opacity']);
}
}
break;
case 'bottom-left':
for ($y = $img_im_h; $y > -$img_wm_h; $y-=$img_wm_h) {
for ($x = 0; $x < $img_im_w; $x+=$img_wm_w) {
$r = self::imagecopymerge_alpha($img, $src_wm, $x, $y, 0, 0, $img_wm_w, $img_wm_h, $options['opacity']);
}
}
break;
case 'center':
default:
$pos_x = -(($img_im_w % $img_wm_w) / 2);
$pos_y = -(($img_im_h % $img_wm_h) / 2);
for ($y = $pos_y; $y < $img_im_h; $y+=$img_wm_h) {
for ($x = $pos_x; $x < $img_im_w; $x+=$img_wm_w) {
$r = self::imagecopymerge_alpha($img, $src_wm, $x, $y, 0, 0, $img_wm_w, $img_wm_h, $options['opacity']);
}
}
break;
}
} else {
// custom location
if (is_array($options['position'])) {
list($pos_x, $pos_y) = $options['position'];
} else {
// predefined location
switch ($options['position']) {
case 'top-left':
$pos_x = 0;
$pos_y = 0;
break;
case 'top-right':
$pos_x = $img_im_w - $img_wm_w;
$pos_y = 0;
break;
case 'bottom-right':
$pos_x = $img_im_w - $img_wm_w;
$pos_y = $img_im_h - $img_wm_h;
break;
case 'bottom-left':
$pos_x = 0;
$pos_y = $img_im_h - $img_wm_h;
break;
case 'center':
default:
$pos_x = round(($img_im_w - $img_wm_w) / 2);
$pos_y = round(($img_im_h - $img_wm_h) / 2);
break;
}
}
$r = self::imagecopymerge_alpha($img, $src_wm, $pos_x, $pos_y, 0, 0, $img_wm_w, $img_wm_h, $options['opacity']);
}
if (!$r) {
return false;
}
if (!self::afterCallbacks($img, $options['afterCallbacks'])) {
return false;
}
return self::saveImage($img, $options);
}
I don't know what parameter should i pass to watermark function.`
Say I've got some square images which I want to resize to rectangle images with the ratio 16:9. What is the best way to do it using PHP?
you could use imagecopyresampled ( resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h )
more at http://us2.php.net/imagecopyresampled
Try this... Not Using GD but i think it will work for u.
<?php
function Image($image, $crop = null, $size = null) {
$image = ImageCreateFromString(file_get_contents($image));
if (is_resource($image) === true) {
$x = 0;
$y = 0;
$width = imagesx($image);
$height = imagesy($image);
/*
CROP (Aspect Ratio) Section
*/
if (is_null($crop) === true) {
$crop = array($width, $height);
} else {
$crop = array_filter(explode(':', $crop));
if (empty($crop) === true) {
$crop = array($width, $height);
} else {
if ((empty($crop[0]) === true) || (is_numeric($crop[0]) === false)) {
$crop[0] = $crop[1];
} else if ((empty($crop[1]) === true) || (is_numeric($crop[1]) === false)) {
$crop[1] = $crop[0];
}
}
$ratio = array(0 => $width / $height, 1 => $crop[0] / $crop[1]);
if ($ratio[0] > $ratio[1]) {
$width = $height * $ratio[1];
$x = (imagesx($image) - $width) / 2;
}
else if ($ratio[0] < $ratio[1]) {
$height = $width / $ratio[1];
$y = (imagesy($image) - $height) / 2;
}
}
/*
Resize Section
*/
if (is_null($size) === true) {
$size = array($width, $height);
}
else {
$size = array_filter(explode('x', $size));
if (empty($size) === true) {
$size = array(imagesx($image), imagesy($image));
} else {
if ((empty($size[0]) === true) || (is_numeric($size[0]) === false)) {
$size[0] = round($size[1] * $width / $height);
} else if ((empty($size[1]) === true) || (is_numeric($size[1]) === false)) {
$size[1] = round($size[0] * $height / $width);
}
}
}
$result = ImageCreateTrueColor($size[0], $size[1]);
if (is_resource($result) === true) {
ImageSaveAlpha($result, true);
ImageAlphaBlending($result, true);
ImageFill($result, 0, 0, ImageColorAllocate($result, 255, 255, 255));
ImageCopyResampled($result, $image, 0, 0, $x, $y, $size[0], $size[1], $width, $height);
ImageInterlace($result, true);
ImageJPEG($result, null, 90);
}
}
return false;
}
header('Content-Type: image/jpeg');
Image('image.jpg', '2:1', '1200x');
?>
I've coded a function that crops an image to a given aspect ratio and finally then resizes it and outputs it as JPG:
<?php
function Image($image, $crop = null, $size = null)
{
$image = ImageCreateFromString(file_get_contents($image));
if (is_resource($image) === true)
{
$x = 0;
$y = 0;
$width = imagesx($image);
$height = imagesy($image);
/*
CROP (Aspect Ratio) Section
*/
if (is_null($crop) === true)
{
$crop = array($width, $height);
}
else
{
$crop = array_filter(explode(':', $crop));
if (empty($crop) === true)
{
$crop = array($width, $height);
}
else
{
if ((empty($crop[0]) === true) || (is_numeric($crop[0]) === false))
{
$crop[0] = $crop[1];
}
else if ((empty($crop[1]) === true) || (is_numeric($crop[1]) === false))
{
$crop[1] = $crop[0];
}
}
$ratio = array
(
0 => $width / $height,
1 => $crop[0] / $crop[1],
);
if ($ratio[0] > $ratio[1])
{
$width = $height * $ratio[1];
$x = (imagesx($image) - $width) / 2;
}
else if ($ratio[0] < $ratio[1])
{
$height = $width / $ratio[1];
$y = (imagesy($image) - $height) / 2;
}
/*
How can I skip (join) this operation
with the one in the Resize Section?
*/
$result = ImageCreateTrueColor($width, $height);
if (is_resource($result) === true)
{
ImageSaveAlpha($result, true);
ImageAlphaBlending($result, false);
ImageFill($result, 0, 0, ImageColorAllocateAlpha($result, 255, 255, 255, 127));
ImageCopyResampled($result, $image, 0, 0, $x, $y, $width, $height, $width, $height);
$image = $result;
}
}
/*
Resize Section
*/
if (is_null($size) === true)
{
$size = array(imagesx($image), imagesy($image));
}
else
{
$size = array_filter(explode('x', $size));
if (empty($size) === true)
{
$size = array(imagesx($image), imagesy($image));
}
else
{
if ((empty($size[0]) === true) || (is_numeric($size[0]) === false))
{
$size[0] = round($size[1] * imagesx($image) / imagesy($image));
}
else if ((empty($size[1]) === true) || (is_numeric($size[1]) === false))
{
$size[1] = round($size[0] * imagesy($image) / imagesx($image));
}
}
}
$result = ImageCreateTrueColor($size[0], $size[1]);
if (is_resource($result) === true)
{
ImageSaveAlpha($result, true);
ImageAlphaBlending($result, true);
ImageFill($result, 0, 0, ImageColorAllocate($result, 255, 255, 255));
ImageCopyResampled($result, $image, 0, 0, 0, 0, $size[0], $size[1], imagesx($image), imagesy($image));
header('Content-Type: image/jpeg');
ImageInterlace($result, true);
ImageJPEG($result, null, 90);
}
}
return false;
}
?>
The function works as expected but I'm creating a non-required GD image resource, how can I fix it? I've tried joining both calls but I must be doing some miscalculations.
<?php
/*
Usage Examples
*/
Image('http://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png', '1:1', '600x');
Image('http://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png', '2:1', '600x');
Image('http://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png', '2:', '250x300');
?>
Any help is greatly appreciated, thanks.
You will have to modify your resizing code not to be based on the cropped image to start with. Since you want to do the cropping and resizing in one go you need to calculate it independently.
<?php
function Image($image, $crop = ':', $size = null) {
$image = ImageCreateFromString(file_get_contents($image));
if (is_resource($image)) {
$x = 0;
$y = 0;
$width = imagesx($image);
$height = imagesy($image);
// CROP (Aspect Ratio) Section
$crop = array_filter(explode(':', $crop));
if (empty($crop)) {
$crop = [$width, $height];
} else {
$crop[0] = $crop[0] ?: $crop[1];
$crop[1] = $crop[1] ?: $crop[0];
}
$ratio = [$width / $height, $crop[0] / $crop[1]];
if ($ratio[0] > $ratio[1]) {
$width = $height * $ratio[1];
$x = (imagesx($image) - $width) / 2;
} else {
$height = $width / $ratio[1];
$y = (imagesy($image) - $height) / 2;
}
// Resize Section
if (is_null($size)) {
$size = [$width, $height];
} else {
$size = array_filter(explode('x', $size));
if (empty($size)) {
$size = [imagesx($image), imagesy($image)];
} else {
$size[0] = $size[0] ?: round($size[1] * $width / $height);
$size[1] = $size[1] ?: round($size[0] * $height / $width);
}
}
$result = ImageCreateTrueColor($size[0], $size[1]);
if (is_resource($result)) {
ImageSaveAlpha($result, true);
ImageAlphaBlending($result, true);
ImageFill($result, 0, 0, ImageColorAllocate($result, 255, 255, 255));
ImageCopyResampled($result, $image, 0, 0, $x, $y, $size[0], $size[1], $width, $height);
ImageInterlace($result, true);
ImageJPEG($result, null, 90);
}
}
return false;
}
header('Content-Type: image/jpeg');
Image('http://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png', '1:1', '600x');
?>