1<?php 2 3 4namespace ComboStrap; 5 6 7class ImageRaster extends Image 8{ 9 10 const CANONICAL = "raster"; 11 12 13 public function __construct($path, $attributes = null) 14 { 15 parent::__construct($path, $attributes); 16 $this->getAttributes()->setLogicalTag(self::CANONICAL); 17 } 18 19 private $imageWidth = null; 20 /** 21 * @var int 22 */ 23 private $imageWeight = null; 24 /** 25 * See {@link image_type_to_mime_type} 26 * @var int 27 */ 28 private $imageType; 29 private $wasAnalyzed = false; 30 31 32 /** 33 * @var mixed - the mime from the {@link RasterImageLink::analyzeImageIfNeeded()} 34 */ 35 private $mime; 36 37 /** 38 * @return int - the width of the image from the file 39 * @throws ExceptionCombo 40 */ 41 public function getIntrinsicWidth(): int 42 { 43 $this->analyzeImageIfNeeded(); 44 return $this->imageWidth; 45 } 46 47 /** 48 * @return int - the height of the image from the file 49 * @throws ExceptionCombo 50 */ 51 public function getIntrinsicHeight(): int 52 { 53 $this->analyzeImageIfNeeded(); 54 return $this->imageWeight; 55 } 56 57 /** 58 * @throws ExceptionCombo 59 */ 60 private 61 function analyzeImageIfNeeded() 62 { 63 64 if (!$this->wasAnalyzed) { 65 66 if ($this->exists()) { 67 68 /** 69 * Based on {@link media_image_preview_size()} 70 * $dimensions = media_image_preview_size($this->id, '', false); 71 */ 72 $imageInfo = array(); 73 $path = $this->getPath(); 74 if ($path instanceof DokuPath) { 75 $path = $path->toLocalPath(); 76 } 77 $imageSize = getimagesize($path->toAbsolutePath()->toString(), $imageInfo); 78 if ($imageSize === false) { 79 throw new ExceptionCombo("We couldn't retrieve the type and dimensions of the image ($this). The image format seems to be not supported.", self::CANONICAL); 80 } 81 $this->imageWidth = (int)$imageSize[0]; 82 if (empty($this->imageWidth)) { 83 throw new ExceptionCombo("We couldn't retrieve the width of the image ($this)", self::CANONICAL); 84 } 85 $this->imageWeight = (int)$imageSize[1]; 86 if (empty($this->imageWeight)) { 87 throw new ExceptionCombo("We couldn't retrieve the height of the image ($this)", self::CANONICAL); 88 } 89 $this->imageType = (int)$imageSize[2]; 90 $this->mime = $imageSize[3]; 91 92 } 93 } 94 $this->wasAnalyzed = true; 95 } 96 97 98 /** 99 * @throws ExceptionCombo 100 */ 101 public function getUrl() 102 { 103 return $this->getUrlAtBreakpoint(); 104 } 105 106 107 /** 108 * @param int|null $breakpointWidth - the breakpoint width - use for responsive image 109 * @return string|null 110 * @throws ExceptionCombo 111 */ 112 public function getUrlAtBreakpoint(int $breakpointWidth = null) 113 { 114 115 /** 116 * Default 117 */ 118 if ($breakpointWidth == null) { 119 $breakpointWidth = $this->getTargetWidth(); 120 } 121 122 if (!$this->exists()) { 123 LogUtility::msg("The image ($this) does not exist, you can't ask the URL", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 124 return false; 125 } 126 127 /** 128 * Link attribute 129 */ 130 $att = array(); 131 132 /** 133 * The image ratio is fixed 134 * Width is driving the computation 135 */ 136 // Height for the given width 137 $breakpointHeight = $this->getBreakpointHeight($breakpointWidth); 138 139 /** 140 * If the request is not the original image 141 * and not cropped, add the width and height 142 */ 143 if ($breakpointWidth != null && 144 ( 145 $breakpointWidth < $this->getIntrinsicWidth() 146 || 147 $breakpointHeight < $this->getIntrinsicHeight() 148 )) { 149 150 $att['w'] = $breakpointWidth; 151 152 if (!empty($breakpointHeight)) { 153 $att['h'] = $breakpointHeight; 154 $this->checkLogicalRatioAgainstTargetRatio($breakpointWidth, $breakpointHeight); 155 } 156 157 } 158 159 if (!empty($this->getCache())) { 160 $att[CacheMedia::CACHE_KEY] = $this->getCache(); 161 } 162 163 /** 164 * Smart Cache 165 */ 166 $this->addCacheBusterToQueryParameters($att); 167 168 $direct = true; 169 170 if ($this->getPath() === null) { 171 LogUtility::msg("The Url of a image not in the media library is not yet supported", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 172 return ""; 173 } 174 return ml($this->getPath()->getDokuwikiId(), $att, $direct, DokuwikiUrl::AMPERSAND_CHARACTER, true); 175 176 177 } 178 179 /** 180 * @throws ExceptionCombo 181 */ 182 public 183 function getAbsoluteUrl() 184 { 185 186 return $this->getUrl(); 187 188 } 189 190 /** 191 * We overwrite the {@link Image::getTargetWidth()} 192 * because we don't scale up for raster image 193 * to not lose quality. 194 * 195 * @return int 196 * @throws ExceptionCombo 197 */ 198 public 199 function getTargetWidth(): int 200 { 201 202 $requestedWidth = $this->getRequestedWidth(); 203 204 /** 205 * May be 0 (ie empty) 206 */ 207 if (!empty($requestedWidth)) { 208 // it should not be bigger than the media Height 209 $mediaWidth = $this->getIntrinsicWidth(); 210 if (!empty($mediaWidth)) { 211 if ($requestedWidth > $mediaWidth) { 212 global $ID; 213 if ($ID != "wiki:syntax") { 214 // There is a bug in the wiki syntax page 215 // {{wiki:dokuwiki-128.png?200x50}} 216 // https://forum.dokuwiki.org/d/19313-bugtypo-how-to-make-a-request-to-change-the-syntax-page-on-dokuwikii 217 LogUtility::msg("For the image ($this), the requested width of ($requestedWidth) can not be bigger than the intrinsic width of ($mediaWidth). The width was then set to its natural width ($mediaWidth)", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 218 } 219 $requestedWidth = $mediaWidth; 220 } 221 } 222 return $requestedWidth; 223 } 224 225 return parent::getTargetWidth(); 226 } 227 228 /** 229 * @throws ExceptionCombo 230 */ 231 public function getTargetHeight(): int 232 { 233 234 $requestedHeight = $this->getRequestedHeight(); 235 if (!empty($requestedHeight)) { 236 // it should not be bigger than the media Height 237 $mediaHeight = $this->getIntrinsicHeight(); 238 if (!empty($mediaHeight)) { 239 if ($requestedHeight > $mediaHeight) { 240 LogUtility::msg("For the image ($this), the requested height of ($requestedHeight) can not be bigger than the intrinsic height of ($mediaHeight). The height was then set to its natural height ($mediaHeight)", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 241 return $mediaHeight; 242 } 243 } 244 } 245 246 return parent::getTargetHeight(); 247 } 248 249 250} 251