image.php (11137B)
1 <?php 2 // Image extension, https://github.com/annaesvensson/yellow-image 3 4 class YellowImage { 5 const VERSION = "0.9.3"; 6 public $yellow; // access to API 7 8 // Handle initialisation 9 public function onLoad($yellow) { 10 $this->yellow = $yellow; 11 $this->yellow->system->setDefault("imageUploadWidthMax", "1280"); 12 $this->yellow->system->setDefault("imageUploadHeightMax", "1280"); 13 $this->yellow->system->setDefault("imageUploadJpegQuality", "80"); 14 $this->yellow->system->setDefault("imageThumbnailJpegQuality", "80"); 15 $this->yellow->system->setDefault("imageJpegExtension", "auto"); 16 } 17 18 // Handle update 19 public function onUpdate($action) { 20 if ($action=="clean") { 21 $statusCode = 200; 22 $path = $this->yellow->lookup->findMediaDirectory("coreThumbnailLocation"); 23 foreach ($this->yellow->toolbox->getDirectoryEntries($path, "/.*/", false, false) as $entry) { 24 if (!$this->yellow->toolbox->deleteFile($entry)) $statusCode = 500; 25 } 26 if ($statusCode==500) $this->yellow->toolbox->log("error", "Can't delete files in directory '$path'!"); 27 } 28 } 29 30 // Handle page content element 31 public function onParseContentElement($page, $name, $text, $attributes, $type) { 32 $output = null; 33 if ($name=="image" && $type=="inline") { 34 list($name, $alt, $style, $width, $height) = $this->yellow->toolbox->getTextArguments($text); 35 if (!preg_match("/^\w+:/", $name)) { 36 if (is_string_empty($alt)) $alt = $this->yellow->language->getText("imageDefaultAlt"); 37 if (is_string_empty($width)) $width = "100%"; 38 if (is_string_empty($height)) $height = $width; 39 $path = $this->yellow->lookup->findMediaDirectory("coreImageLocation"); 40 list($src, $width, $height) = $this->getImageInformation($path.$name, $width, $height); 41 } else { 42 if (is_string_empty($alt)) $alt = $this->yellow->language->getText("imageDefaultAlt"); 43 $src = $this->yellow->lookup->normaliseUrl("", "", "", $name); 44 $width = $height = 0; 45 } 46 $output = "<img src=\"".htmlspecialchars($src)."\""; 47 if ($width && $height) $output .= " width=\"".htmlspecialchars($width)."\" height=\"".htmlspecialchars($height)."\""; 48 if (!is_string_empty($alt)) $output .= " alt=\"".htmlspecialchars($alt)."\" title=\"".htmlspecialchars($alt)."\""; 49 if (!is_string_empty($style)) $output .= " class=\"".htmlspecialchars($style)."\""; 50 $output .= " />"; 51 } 52 return $output; 53 } 54 55 // Handle media file changes 56 public function onEditMediaFile($file, $action, $email) { 57 if ($action=="upload") { 58 $fileName = $file->get("fileNameTemp"); 59 list($widthInput, $heightInput, $orientation, $type) = 60 $this->yellow->toolbox->detectImageInformation($fileName, $file->get("type")); 61 $widthMax = $this->yellow->system->get("imageUploadWidthMax"); 62 $heightMax = $this->yellow->system->get("imageUploadHeightMax"); 63 if ($type=="gif" || $type=="jpeg" || $type=="png") { 64 if ($widthInput>$widthMax || $heightInput>$heightMax) { 65 list($widthOutput, $heightOutput) = $this->getImageDimensionsFit($widthInput, $heightInput, $widthMax, $heightMax); 66 $image = $this->loadImage($fileName, $type); 67 $image = $this->resizeImage($image, $widthInput, $heightInput, $widthOutput, $heightOutput); 68 $image = $this->orientImage($image, $orientation); 69 if (!$this->saveImage($image, $fileName, $type, $this->yellow->system->get("imageUploadJpegQuality"))) { 70 $file->error(500, "Can't write file '$fileName'!"); 71 } 72 } elseif ($orientation>1) { 73 $image = $this->loadImage($fileName, $type); 74 $image = $this->orientImage($image, $orientation); 75 if (!$this->saveImage($image, $fileName, $type, $this->yellow->system->get("imageUploadJpegQuality"))) { 76 $file->error(500, "Can't write file '$fileName'!"); 77 } 78 } 79 } 80 if ($type=="jpeg") { 81 $file->fileName = dirname($file->fileName)."/".pathinfo($file->fileName, PATHINFO_FILENAME).$this->getImageExtension($file->fileName, $type); 82 $file->set("type", $this->yellow->toolbox->getFileType($file->fileName)); 83 } 84 } 85 } 86 87 // Return image information, create thumbnail on demand 88 public function getImageInformation($fileName, $widthOutput, $heightOutput) { 89 $fileNameShort = substru($fileName, strlenu($this->yellow->lookup->findMediaDirectory("coreImageLocation"))); 90 list($widthInput, $heightInput, $orientation, $type) = $this->yellow->toolbox->detectImageInformation($fileName); 91 $widthOutput = $this->convertValueAndUnit($widthOutput, $widthInput); 92 $heightOutput = $this->convertValueAndUnit($heightOutput, $heightInput); 93 if (($widthInput==$widthOutput && $heightInput==$heightOutput) || $type=="svg" || $type=="") { 94 $src = $this->yellow->system->get("coreServerBase").$this->yellow->system->get("coreImageLocation").$fileNameShort; 95 $width = $widthOutput; 96 $height = $heightOutput; 97 } else { 98 $pathThumb = $this->yellow->lookup->findMediaDirectory("coreThumbnailLocation"); 99 $fileNameThumb = ltrim(str_replace(array("/", "\\", "."), "-", dirname($fileNameShort)."/".pathinfo($fileName, PATHINFO_FILENAME)), "-"); 100 $fileNameThumb .= "-".$widthOutput."x".$heightOutput; 101 $fileNameThumb .= $this->getImageExtension($fileName, $type); 102 $fileNameOutput = $pathThumb.$fileNameThumb; 103 if ($this->isFileNotUpdated($fileName, $fileNameOutput)) { 104 $image = $this->loadImage($fileName, $type); 105 $image = $this->resizeImage($image, $widthInput, $heightInput, $widthOutput, $heightOutput); 106 $image = $this->orientImage($image, $orientation); 107 if (is_file($fileNameOutput)) $this->yellow->toolbox->deleteFile($fileNameOutput); 108 if (!$this->saveImage($image, $fileNameOutput, $type, $this->yellow->system->get("imageThumbnailJpegQuality")) || 109 !$this->yellow->toolbox->modifyFile($fileNameOutput, $this->yellow->toolbox->getFileModified($fileName))) { 110 $this->yellow->page->error(500, "Can't write file '$fileNameOutput'!"); 111 } 112 } 113 $src = $this->yellow->system->get("coreServerBase").$this->yellow->system->get("coreThumbnailLocation").$fileNameThumb; 114 list($width, $height) = $this->yellow->toolbox->detectImageInformation($fileNameOutput); 115 } 116 return array($src, $width, $height); 117 } 118 119 // Return image dimensions that fit, scale proportional 120 public function getImageDimensionsFit($widthInput, $heightInput, $widthMax, $heightMax) { 121 $widthOutput = $widthMax; 122 $heightOutput = $widthMax * ($heightInput / $widthInput); 123 if ($heightOutput>$heightMax) { 124 $widthOutput = $widthOutput * ($heightMax / $heightOutput); 125 $heightOutput = $heightOutput * ($heightMax / $heightOutput); 126 } 127 return array(intval($widthOutput), intval($heightOutput)); 128 } 129 130 // Return image extension 131 public function getImageExtension($fileName, $type) { 132 $jpegExtension = $this->yellow->system->get("imageJpegExtension"); 133 $fileExtension = ".".pathinfo($fileName, PATHINFO_EXTENSION); 134 if ($jpegExtension!="auto" && $type=="jpeg") $fileExtension = $jpegExtension; 135 return $fileExtension; 136 } 137 138 // Load image from file 139 public function loadImage($fileName, $type) { 140 $image = false; 141 switch ($type) { 142 case "gif": $image = @imagecreatefromgif($fileName); break; 143 case "jpeg": $image = @imagecreatefromjpeg($fileName); break; 144 case "png": $image = @imagecreatefrompng($fileName); break; 145 } 146 return $image; 147 } 148 149 // Save image to file 150 public function saveImage($image, $fileName, $type, $quality) { 151 $ok = false; 152 switch ($type) { 153 case "gif": $ok = @imagegif($image, $fileName); break; 154 case "jpeg": $ok = @imagejpeg($image, $fileName, $quality); break; 155 case "png": $ok = @imagepng($image, $fileName); break; 156 } 157 return $ok; 158 } 159 160 // Create image from scratch 161 public function createImage($width, $height) { 162 $image = imagecreatetruecolor($width, $height); 163 imagealphablending($image, false); 164 imagesavealpha($image, true); 165 return $image; 166 } 167 168 // Resize image 169 public function resizeImage($image, $widthInput, $heightInput, $widthOutput, $heightOutput) { 170 $widthFit = $widthInput * ($heightOutput / $heightInput); 171 $heightFit = $heightInput * ($widthOutput / $widthInput); 172 $widthDiff = abs($widthOutput - $widthFit); 173 $heightDiff = abs($heightOutput - $heightFit); 174 $imageOutput = $this->createImage($widthOutput, $heightOutput); 175 if ($heightFit>$heightOutput) { 176 imagecopyresampled($imageOutput, $image, 0, $heightDiff/-2, 0, 0, $widthOutput, $heightFit, $widthInput, $heightInput); 177 } else { 178 imagecopyresampled($imageOutput, $image, $widthDiff/-2, 0, 0, 0, $widthFit, $heightOutput, $widthInput, $heightInput); 179 } 180 return $imageOutput; 181 } 182 183 // Orient image automatically 184 public function orientImage($image, $orientation) { 185 switch ($orientation) { 186 case 2: imageflip($image, IMG_FLIP_HORIZONTAL); break; 187 case 3: $image = imagerotate($image, 180, 0); break; 188 case 4: imageflip($image, IMG_FLIP_VERTICAL); break; 189 case 5: $image = imagerotate($image, 90, 0); imageflip($image, IMG_FLIP_VERTICAL); break; 190 case 6: $image = imagerotate($image, -90, 0); break; 191 case 7: $image = imagerotate($image, 90, 0); imageflip($image, IMG_FLIP_HORIZONTAL); break; 192 case 8: $image = imagerotate($image, 90, 0); break; 193 } 194 return $image; 195 } 196 197 // Return value according to unit 198 public function convertValueAndUnit($text, $valueBase) { 199 $value = $unit = ""; 200 if (preg_match("/([\d\.]+)(\S*)/", $text, $matches)) { 201 $value = $matches[1]; 202 $unit = $matches[2]; 203 if ($unit=="%") $value = $valueBase * $value / 100; 204 } 205 return intval($value); 206 } 207 208 // Check if file needs to be updated 209 public function isFileNotUpdated($fileNameInput, $fileNameOutput) { 210 return $this->yellow->toolbox->getFileModified($fileNameInput)!=$this->yellow->toolbox->getFileModified($fileNameOutput); 211 } 212 }