180, 6=>90, 8=>-90, ]; public function getIDLinkAttribute() { return $this->HTMLLinkAttribute($this->id,'p/info'); } public function getHtmlImageURL(): string { return sprintf('',url('p/thumbnail',$this->id)); } /** * Return the image, rotated, minus exif data */ public function image() { if (is_null($imo = $this->o())) return NULL; if (array_key_exists('exif',$imo->getImageProfiles())) $imo->removeImageProfile('exif'); return $this->rotate($imo); } /** * Calculate the GPS coordinates */ public static function latlon(array $coordinate,$hemisphere) { if (! $coordinate OR ! $hemisphere) return NULL; for ($i=0; $i<3; $i++) { $part = explode('/', $coordinate[$i]); if (count($part) == 1) $coordinate[$i] = $part[0]; elseif (count($part) == 2) $coordinate[$i] = floatval($part[0])/floatval($part[1]); else $coordinate[$i] = 0; } list($degrees,$minutes,$seconds) = $coordinate; $sign = ($hemisphere == 'W' || $hemisphere == 'S') ? -1 : 1; return round($sign*($degrees+$minutes/60+$seconds/3600),($degrees>100 ? 3 : 4)); } /** * Return an Imagick object or attribute */ protected function o($attr=NULL) { if (! file_exists($this->file_path()) OR ! is_readable($this->file_path())) return NULL; if (is_null($this->_o)) $this->_o = new \Imagick($this->file_path()); return is_null($attr) ? $this->_o : $this->_o->getImageProperty($attr); } /** * Display the orientation of a photo */ public function orientation() { switch ($this->orientation) { case 1: return 'None!'; case 3: return 'Upside Down'; case 6: return 'Rotate Right'; case 8: return 'Rotate Left'; default: return 'unknown?'; } } /** * Rotate the image */ private function rotate(\Imagick $imo) { if (array_key_exists($this->orientation,$this->_rotate)) $imo->rotateImage(new \ImagickPixel('none'),$this->_rotate[$this->orientation]); $imo->setImageFormat('jpg'); return $imo->getImageBlob(); } public function property(string $property) { if (! $this->o()) return NULL; switch ($property) { case 'creationdate': if ($this->property('exif:DateTimeOriginal') == '0000:00:00 00:00:00' && $this->property('exif:DateTimeOriginal') == '0000:00:00 00:00:00') return NULL; return strtotime( $this->property('exif:DateTimeOriginal') && $this->property('exif:DateTimeOriginal') != '0000:00:00 00:00:00' ? $this->property('exif:DateTimeOriginal') : $this->property('exif:DateTime')); break; case 'height': return $this->_o->getImageHeight(); case 'orientation': return $this->_o->getImageOrientation(); case 'signature': return $this->_o->getImageSignature(); case 'width': return $this->_o->getImageWidth(); default: return $this->_o->getImageProperty($property); } } public function properties() { return $this->o() ? $this->_o->getImageProperties() : []; } public function setLocation() { $this->gps_lat = static::latlon(preg_split('/,\s?/',$this->property('exif:GPSLatitude')),$this->property('exif:GPSLatitudeRef')); $this->gps_lon = static::latlon(preg_split('/,\s?/',$this->property('exif:GPSLongitude')),$this->property('exif:GPSLongitudeRef')); } public function setMakeModel() { $ma = NULL; if ($this->property('exif:Make')) $ma = Make::firstOrCreate([ 'name'=>$this->property('exif:Make'), ]); $mo = Model::firstOrCreate([ 'name'=>$this->property('exif:Model') ?: NULL, 'make_id'=>$ma ? $ma->id : NULL, ]); $so = Software::firstOrCreate([ 'name'=>$this->property('exif:Software') ?: NULL, 'model_id'=>$mo->id, ]); $this->software_id = $so->id; } public function setSubSecTime(): int { $this->subsectime = (int)$this->property('exif:SubSecTimeOriginal'); // In case of an error. if ($this->subsectime > 32767) $this->subsectime = 32767; if ($this->subsectime === FALSE) $this->subsectime = 0; } public function setThumbnail() { try { $this->thumbnail = exif_thumbnail($this->file_path()); } catch (\Exception $e) { // @todo Couldnt get the thumbnail, so we should create one. Log::info(sprintf('Unable to create thumbnail for %s (%s)',$this->id,$e->getMessage())); } if ($this->thumbnail === FALSE) $this->thumbnail = NULL; } /** * Return the image's thumbnail */ public function thumbnail($rotate=TRUE) { if (! $this->thumbnail) { if ($this->isReadable() AND $this->o()->thumbnailimage(200,200,true,false)) { $this->_o->setImageFormat('jpg'); return $this->_o->getImageBlob(); } else { return NULL; } } if (! $rotate OR ! array_key_exists($this->orientation,$this->_rotate) OR ! extension_loaded('imagick')) return $this->thumbnail; $imo = new \Imagick(); $imo->readImageBlob($this->thumbnail); $imo->setImageFormat('jpg'); return $this->rotate($imo); } /** * Return the extension of the image * @todo mime-by-ext? */ public function type($mime=FALSE) { return strtolower($mime ? 'image/jpeg' : pathinfo($this->filename,PATHINFO_EXTENSION)); } }