Fix thumbnail orientation and add Copy Exif function

This commit is contained in:
2019-09-01 21:01:40 +02:00
parent 08bc60e44b
commit 8cd00d77c1

View File

@@ -174,7 +174,7 @@ class ToolBox
return $iCount > 1; return $iCount > 1;
} }
public static function createThumbnail($sInPath, $iMaxWidth, $iMaxHeight=0, $sOutPath='', $bDeleteIn=false, $asImageExts=array('jpg', 'jpeg', 'gif', 'png'), $bCrop=false) public static function createThumbnail($sInPath, $iMaxWidth, $iMaxHeight=0, $sOutPath='', $bDeleteIn=false, $asImageExts=array('jpg', 'jpeg', 'gif', 'png'), $bCrop=false, $bCopyExif=false)
{ {
$asResult = array('error'=>''); $asResult = array('error'=>'');
@@ -194,7 +194,24 @@ class ToolBox
elseif($iMaxWidth==0 && $iMaxHeight==0) $asResult['error'] = 'At least one dimension must be resized (width and/or height)'; elseif($iMaxWidth==0 && $iMaxHeight==0) $asResult['error'] = 'At least one dimension must be resized (width and/or height)';
else else
{ {
//Recalculate max width/height in case of rotated picture
$sRotate = 0;
$asExif = @exif_read_data($sInPath);
if($asExif && array_key_exists('Orientation', $asExif)) {
switch($asExif['Orientation'])
{
case 3: $sRotate = 180; break; //Flip over
case 6: $sRotate = -90; break; //Clockwise
case 8: $sRotate = 90; break; //Trigo
}
}
list($iWidth, $iHeight) = getimagesize($sInPath); list($iWidth, $iHeight) = getimagesize($sInPath);
if(abs($sRotate) == 90) {
$iTempWidth = $iWidth;
$iWidth = $iHeight;
$iHeight = $iTempWidth;
}
//Limit on only 1 parameter //Limit on only 1 parameter
if($iMaxWidth==0) $iMaxWidth = $iWidth * $iMaxHeight / $iHeight; if($iMaxWidth==0) $iMaxWidth = $iWidth * $iMaxHeight / $iHeight;
@@ -256,6 +273,9 @@ class ToolBox
{ {
//create image from source //create image from source
$oSource = call_user_func('imagecreatefrom'.$sImageExt, $sInPath); $oSource = call_user_func('imagecreatefrom'.$sImageExt, $sInPath);
//Fix rotation
if($sRotate) $oSource = imagerotate($oSource, $sRotate, 0);
//Resize //Resize
$oThumb = imagecreatetruecolor($iThumbWidth, $iThumbHeight); $oThumb = imagecreatetruecolor($iThumbWidth, $iThumbHeight);
@@ -267,6 +287,7 @@ class ToolBox
{ {
$asResult['error'] = 'Unable to create thumbnail : '.$sOutPath; $asResult['error'] = 'Unable to create thumbnail : '.$sOutPath;
} }
imagedestroy($oThumb);
} }
} }
elseif($sInPath != $sOutPath) elseif($sInPath != $sOutPath)
@@ -280,11 +301,75 @@ class ToolBox
$asResult['out'] = $sOutPath; $asResult['out'] = $sOutPath;
} }
if($bCopyExif && $asResult['error'] == '') self::copyExif($sInPath, $sOutPath);
if($bDeleteIn && $asResult['error'] == '' && $sInPath != $sOutPath) unlink($sInPath); if($bDeleteIn && $asResult['error'] == '' && $sInPath != $sOutPath) unlink($sInPath);
return $asResult; return $asResult;
} }
public function copyExif($srcfile, $destfile) {
// Function transfers EXIF (APP1) and IPTC (APP13) from $srcfile and adds it to $destfile
// JPEG file has format 0xFFD8 + [APP0] + [APP1] + ... [APP15] + <image data> where [APPi] are optional
// Segment APPi (where i=0x0 to 0xF) has format 0xFFEi + 0xMM + 0xLL + <data> (where 0xMM is
// most significant 8 bits of (strlen(<data>) + 2) and 0xLL is the least significant 8 bits
// of (strlen(<data>) + 2)
if (file_exists($srcfile) && file_exists($destfile)) {
$srcsize = @getimagesize($srcfile, $imageinfo);
// Prepare EXIF data bytes from source file
$exifdata = (is_array($imageinfo) && key_exists("APP1", $imageinfo)) ? $imageinfo['APP1'] : null;
if ($exifdata) {
$exiflength = strlen($exifdata) + 2;
if ($exiflength > 0xFFFF) return false;
// Construct EXIF segment
$exifdata = chr(0xFF) . chr(0xE1) . chr(($exiflength >> 8) & 0xFF) . chr($exiflength & 0xFF) . $exifdata;
}
// Prepare IPTC data bytes from source file
$iptcdata = (is_array($imageinfo) && key_exists("APP13", $imageinfo)) ? $imageinfo['APP13'] : null;
if ($iptcdata) {
$iptclength = strlen($iptcdata) + 2;
if ($iptclength > 0xFFFF) return false;
// Construct IPTC segment
$iptcdata = chr(0xFF) . chr(0xED) . chr(($iptclength >> 8) & 0xFF) . chr($iptclength & 0xFF) . $iptcdata;
}
$destfilecontent = @file_get_contents($destfile);
if (!$destfilecontent) return false;
if (strlen($destfilecontent) > 0) {
$destfilecontent = substr($destfilecontent, 2);
$portiontoadd = chr(0xFF) . chr(0xD8); // Variable accumulates new & original IPTC application segments
$exifadded = !$exifdata;
$iptcadded = !$iptcdata;
while ((substr($destfilecontent, 0, 2) & 0xFFF0) === 0xFFE0) {
$segmentlen = (substr($destfilecontent, 2, 2) & 0xFFFF);
$iptcsegmentnumber = (substr($destfilecontent, 1, 1) & 0x0F); // Last 4 bits of second byte is IPTC segment #
if ($segmentlen <= 2) return false;
$thisexistingsegment = substr($destfilecontent, 0, $segmentlen + 2);
if ((1 <= $iptcsegmentnumber) && (!$exifadded)) {
$portiontoadd .= $exifdata;
$exifadded = true;
if (1 === $iptcsegmentnumber) $thisexistingsegment = '';
}
if ((13 <= $iptcsegmentnumber) && (!$iptcadded)) {
$portiontoadd .= $iptcdata;
$iptcadded = true;
if (13 === $iptcsegmentnumber) $thisexistingsegment = '';
}
$portiontoadd .= $thisexistingsegment;
$destfilecontent = substr($destfilecontent, $segmentlen + 2);
}
if (!$exifadded) $portiontoadd .= $exifdata; // Add EXIF data if not added already
if (!$iptcadded) $portiontoadd .= $iptcdata; // Add IPTC data if not added already
$outputfile = fopen($destfile, 'w');
if ($outputfile) return fwrite($outputfile, $portiontoadd . $destfilecontent); else return false;
} else {
return false;
}
} else {
return false;
}
}
public static function utf8_compliant($sText) public static function utf8_compliant($sText)
{ {
if(strlen($sText) == 0) return true; if(strlen($sText) == 0) return true;