photogeodata/app/Filament/Resources/PhotoGeoData/Pages/Concerns/HandlesImageMetadata.php
2026-05-12 20:43:17 +02:00

87 lines
2.2 KiB
PHP

<?php
namespace App\Filament\Resources\PhotoGeoData\Pages\Concerns;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
trait HandlesImageMetadata
{
protected function syncMetadataFromImage(): void
{
$metadata = $this->extractImageMetadata($this->record->image_path);
if ($metadata === null) {
return;
}
$this->record->update(['metadata' => $metadata]);
}
private function extractImageMetadata(mixed $imagePath): ?array
{
if (empty($imagePath)) {
return null;
}
$path = is_array($imagePath) ? reset($imagePath) : $imagePath;
$fullPath = Storage::disk('public')->path($path);
if (!file_exists($fullPath)) {
Log::warning('extractImageMetadata: file not found', ['path' => $fullPath]);
return null;
}
$exif = @exif_read_data($fullPath, null, true);
if ($exif === false) {
Log::debug('extractImageMetadata: no EXIF data', ['path' => $fullPath]);
return null;
}
return $exif;
}
private function extractGpsCoordinates(array $exif): ?array
{
$gps = $exif['GPS'] ?? null;
if (!$gps) {
return null;
}
$lat = $this->rationalToDecimal($gps['GPSLatitude'] ?? null);
$lng = $this->rationalToDecimal($gps['GPSLongitude'] ?? null);
if ($lat === null || $lng === null) {
return null;
}
if (($gps['GPSLatitudeRef'] ?? 'N') === 'S') {
$lat = -$lat;
}
if (($gps['GPSLongitudeRef'] ?? 'E') === 'W') {
$lng = -$lng;
}
return ['lat' => $lat, 'lng' => $lng];
}
private function rationalToDecimal(?array $rational): ?float
{
if (!$rational || count($rational) < 3) {
return null;
}
return $this->rationalValue($rational[0])
+ $this->rationalValue($rational[1]) / 60
+ $this->rationalValue($rational[2]) / 3600;
}
private function rationalValue(string $rational): float
{
[$num, $den] = array_pad(explode('/', $rational, 2), 2, '1');
return $den != 0 ? (float) $num / (float) $den : 0.0;
}
}