Używam następującego kodu, aby obrócić przesłany obraz JPEG, jeśli orientacja jest wyłączona. Mam problemy tylko z obrazami przesłanymi z iPhone'ów i Androida.
if(move_uploaded_file($_FILES['photo']['tmp_name'], $upload_path . $newfilename)){
chmod($upload_path . $newfilename, 0755);
$exif = exif_read_data($upload_path . $newfilename);
$ort = $exif['IFD0']['Orientation'];
switch($ort)
{
case 3: // 180 rotate left
$image->imagerotate($upload_path . $newfilename, 180, -1);
break;
case 6: // 90 rotate right
$image->imagerotate($upload_path . $newfilename, -90, -1);
break;
case 8: // 90 rotate left
$image->imagerotate($upload_path . $newfilename, 90, -1);
break;
}
imagejpeg($image, $upload_path . $newfilename, 100);
$success_message = 'Photo Successfully Uploaded';
}else{
$error_count++;
$error_message = 'Error: Upload Unsuccessful<br />Please Try Again';
}
Czy robię coś złego w sposobie odczytywania danych EXIF z jpeg? Nie obraca obrazów tak, jak powinien.
Oto, co się dzieje, gdy uruchamiam var_dump ($ exif);
array(41) {
["FileName"]=> string(36) "126e7c0efcac2b76b3320e6187d03cfd.JPG"
["FileDateTime"]=> int(1316545667)
["FileSize"]=> int(1312472)
["FileType"]=> int(2)
["MimeType"]=> string(10) "image/jpeg"
["SectionsFound"]=> string(30) "ANY_TAG, IFD0, THUMBNAIL, EXIF"
["COMPUTED"]=> array(8) {
["html"]=> string(26) "width="2048" height="1536""
["Height"]=> int(1536)
["Width"]=> int(2048)
["IsColor"]=> int(1)
["ByteOrderMotorola"]=> int(1)
["ApertureFNumber"]=> string(5) "f/2.8"
["Thumbnail.FileType"]=> int(2)
["Thumbnail.MimeType"]=> string(10) "image/jpeg" }
["Make"]=> string(5) "Apple"
["Model"]=> string(10) "iPhone 3GS"
["Orientation"]=> int(6)
["XResolution"]=> string(4) "72/1"
["YResolution"]=> string(4) "72/1" ["ResolutionUnit"]=> int(2) ["Software"]=> string(5) "4.3.5" ["DateTime"]=> string(19) "2011:09:16 21:18:46" ["YCbCrPositioning"]=> int(1) ["Exif_IFD_Pointer"]=> int(194) ["THUMBNAIL"]=> array(6) { ["Compression"]=> int(6) ["XResolution"]=> string(4) "72/1" ["YResolution"]=> string(4) "72/1" ["ResolutionUnit"]=> int(2) ["JPEGInterchangeFormat"]=> int(658) ["JPEGInterchangeFormatLength"]=> int(8231) } ["ExposureTime"]=> string(4) "1/15" ["FNumber"]=> string(4) "14/5" ["ExposureProgram"]=> int(2) ["ISOSpeedRatings"]=> int(200) ["ExifVersion"]=> string(4) "0221" ["DateTimeOriginal"]=> string(19) "2011:09:16 21:18:46" ["DateTimeDigitized"]=> string(19) "2011:09:16 21:18:46" ["ComponentsConfiguration"]=> string(4) "" ["ShutterSpeedValue"]=> string(8) "3711/949" ["ApertureValue"]=> string(9) "4281/1441" ["MeteringMode"]=> int(1) ["Flash"]=> int(32) ["FocalLength"]=> string(5) "77/20" ["SubjectLocation"]=> array(4) { [0]=> int(1023) [1]=> int(767) [2]=> int(614) [3]=> int(614) } ["FlashPixVersion"]=> string(4) "0100" ["ColorSpace"]=> int(1) ["ExifImageWidth"]=> int(2048) ["ExifImageLength"]=> int(1536) ["SensingMethod"]=> int(2) ["ExposureMode"]=> int(0) ["WhiteBalance"]=> int(0) ["SceneCaptureType"]=> int(0) ["Sharpness"]=> int(1) }
php
orientation
exif
Jeff Thomas
źródło
źródło
var_dump($exif)
aby zobaczyć, co produkują telefony z Androidem w zakresie danych rotacji.$exif['COMPUTED']['Orientation']
ma wartość 6.Odpowiedzi:
Dokumentacja imagerotate odnosi się do innego typu pierwszego parametru niż używany:
Oto mały przykład użycia tej funkcji:
function resample($jpgFile, $thumbFile, $width, $orientation) { // Get new dimensions list($width_orig, $height_orig) = getimagesize($jpgFile); $height = (int) (($width / $width_orig) * $height_orig); // Resample $image_p = imagecreatetruecolor($width, $height); $image = imagecreatefromjpeg($jpgFile); imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig); // Fix Orientation switch($orientation) { case 3: $image_p = imagerotate($image_p, 180, 0); break; case 6: $image_p = imagerotate($image_p, -90, 0); break; case 8: $image_p = imagerotate($image_p, 90, 0); break; } // Output imagejpeg($image_p, $thumbFile, 90); }
źródło
Na podstawie kodu Daniela napisałem funkcję, która w razie potrzeby po prostu obraca obraz, bez ponownego próbkowania.
GD
function image_fix_orientation(&$image, $filename) { $exif = exif_read_data($filename); if (!empty($exif['Orientation'])) { switch ($exif['Orientation']) { case 3: $image = imagerotate($image, 180, 0); break; case 6: $image = imagerotate($image, -90, 0); break; case 8: $image = imagerotate($image, 90, 0); break; } } }
Wersja jednoprzewodowa (GD)
function image_fix_orientation(&$image, $filename) { $image = imagerotate($image, array_values([0, 0, 0, 180, 0, 0, -90, 0, 90])[@exif_read_data($filename)['Orientation'] ?: 0], 0); }
ImageMagick
function image_fix_orientation($image) { if (method_exists($image, 'getImageProperty')) { $orientation = $image->getImageProperty('exif:Orientation'); } else { $filename = $image->getImageFilename(); if (empty($filename)) { $filename = 'data://image/jpeg;base64,' . base64_encode($image->getImageBlob()); } $exif = exif_read_data($filename); $orientation = isset($exif['Orientation']) ? $exif['Orientation'] : null; } if (!empty($orientation)) { switch ($orientation) { case 3: $image->rotateImage('#000000', 180); break; case 6: $image->rotateImage('#000000', 90); break; case 8: $image->rotateImage('#000000', -90); break; } } }
źródło
getImageOrientation()
nie działała poprawnie nawet w przypadku przekonwertowanych obrazów surowych. Powyższy kod działał idealnie.Prostsza funkcja dla osób przesyłających obraz, po prostu automatycznie obraca się, jeśli to konieczne.
function image_fix_orientation($filename) { $exif = exif_read_data($filename); if (!empty($exif['Orientation'])) { $image = imagecreatefromjpeg($filename); switch ($exif['Orientation']) { case 3: $image = imagerotate($image, 180, 0); break; case 6: $image = imagerotate($image, -90, 0); break; case 8: $image = imagerotate($image, 90, 0); break; } imagejpeg($image, $filename, 90); } }
źródło
$exif = @exif_read_data($filename);
Dlaczego nikt nie bierze pod uwagę przypadków lustrzanych 2,4,5,7? W krainie orientacji exif są jeszcze 4 przypadki:
Oto kompletne rozwiązanie przyjmujące nazwę pliku:
function __image_orientate($source, $quality = 90, $destination = null) { if ($destination === null) { $destination = $source; } $info = getimagesize($source); if ($info['mime'] === 'image/jpeg') { $exif = exif_read_data($source); if (!empty($exif['Orientation']) && in_array($exif['Orientation'], [2, 3, 4, 5, 6, 7, 8])) { $image = imagecreatefromjpeg($source); if (in_array($exif['Orientation'], [3, 4])) { $image = imagerotate($image, 180, 0); } if (in_array($exif['Orientation'], [5, 6])) { $image = imagerotate($image, -90, 0); } if (in_array($exif['Orientation'], [7, 8])) { $image = imagerotate($image, 90, 0); } if (in_array($exif['Orientation'], [2, 5, 7, 4])) { imageflip($image, IMG_FLIP_HORIZONTAL); } imagejpeg($image, $destination, $quality); } } return true; }
źródło
Na wypadek, gdyby ktoś się z tym spotkał. Z tego, co mogę stwierdzić, niektóre z powyższych stwierdzeń dotyczących przełącznika są błędne.
Bazując na informacjach tutaj , powinno to być:
switch ($exif['Orientation']) { case 3: $image = imagerotate($image, -180, 0); break; case 6: $image = imagerotate($image, 90, 0); break; case 8: $image = imagerotate($image, -90, 0); break; }
źródło
Prawdopodobnie warto wspomnieć, że jeśli używasz ImageMagick z wiersza poleceń, możesz użyć opcji -auto-orient , która automatycznie obróci obraz na podstawie istniejących danych orientacji EXIF.
Uwaga: jeśli dane EXIF zostały usunięte przed procesem, nie będą działać zgodnie z opisem.
źródło
Tutaj wyjaśniam całą sprawę, używam Laravel i używam pakietu interwencji obrazu.
Przede wszystkim dostaję swój obraz i wysyłam go do mojej innej funkcji w celu zmiany rozmiaru i innej funkcjonalności, jeśli tego nie potrzebujemy, możesz pominąć ...
Pobierz plik za pomocą metody w moim kontrolerze,
public function getImageFile(Request $request){ $image = $request->image; $this->imageUpload($image); }
Teraz wysyłam go, aby zmienić rozmiar i uzyskać nazwę obrazu i rozszerzenie ...
public function imageUpload($file){ ini_set('memory_limit', '-1'); $directory = 'uploads/'; $name = str_replace([" ", "."], "_", $file->getClientOriginalName()) . "_"; $file_name = $name . time() . rand(1111, 9999) . '.' . $file->getClientOriginalExtension(); //path set $img_url = $directory.$file_name; list($width, $height) = getimagesize($file); $h = ($height/$width)*600; Image::make($file)->resize(600, $h)->save(public_path($img_url)); $this->image_fix_orientation($file,$img_url); return $img_url; }
Teraz nazywam moją funkcję orientacji obrazu,
public function image_fix_orientation($file,$img_url ) { $data = Image::make($file)->exif(); if (!empty($data['Orientation'])) { $image = imagecreatefromjpeg($file); switch ($data['Orientation']) { case 3: $image = imagerotate($image, 180, 0); break; case 6: $image = imagerotate($image, -90, 0); break; case 8: $image = imagerotate($image, 90, 0); break; } imagejpeg($image, $img_url, 90); } }
I to wszystko...
źródło
Nienawidzę dzwonić z kolejnym zestawem wartości orientacji, ale z mojego doświadczenia przy korzystaniu z którejkolwiek z wartości wymienionych powyżej zawsze kończyło się na odwróconych obrazach podczas przesyłania zdjęć w orientacji pionowej bezpośrednio z iPhone'a. Oto instrukcja przełącznika, z którą skończyłem.
switch ($exif['Orientation']) { case 3: $image = imagerotate($image, -180, 0); break; case 6: $image = imagerotate($image, -90, 0); break; case 8: $image = imagerotate($image, 90, 0); break; }
źródło
jhead -autorot jpegfile.jpg
Jest to również przydatny sposób podejścia do tego.
jhead to standardowy program w Linuksie (użyj 'sudo apt-get install jhead', aby zainstalować), ta opcja sprawdza orientację i obraca obraz poprawnie i bezstratnie tylko wtedy, gdy tego wymaga. Następnie poprawnie aktualizuje dane EXIF.
W ten sposób możesz przetworzyć plik jpeg (lub wiele plików jpeg w folderze) w prosty, jednoprzebiegowy sposób, który trwale rozwiązuje problemy z obracaniem.
Np. Jhead -autorot * .jpg naprawi cały folder z obrazami jpeg w sposób, jakiego OP wymaga w pierwszym pytaniu.
Chociaż technicznie nie jest to PHP, przeczytałem ten wątek, a następnie zamiast tego użyłem mojej sugestii jhead, wywołanej z wywołania systemu PHP (), aby osiągnąć wyniki, po których byłem, a które były zbieżne z operacjami: aby obracać obrazy, więc dowolne oprogramowanie (takie jak 'fbi 'w Raspbian) może wyświetlać je poprawnie.
W świetle tego pomyślałem, że inni mogą skorzystać na wiedzy, jak łatwo jhead rozwiązuje ten problem i zamieścił tutaj informacje tylko w celach informacyjnych - ponieważ nikt wcześniej o tym nie wspomniał.
źródło
Użyłem też
orientate()
formularza Intervention i działa bez zarzutu.$image_resize = Image::make($request->file('photo')); $image_resize->resize(1600, null,function ($constraint) { $constraint->aspectRatio(); }); $filename = $this->checkFilename(); $image_resize->orientate()->save($this->photo_path.$filename,80);
źródło
Oto moja funkcja PHP 7 zainspirowana @ user462990:
/** * @param string $filePath * * @return resource|null */ function rotateImageByExifOrientation(string $filePath) { $result = null; $exif = exif_read_data($filePath); if (!empty($exif['Orientation'])) { $image = imagecreatefromjpeg($filePath); if (is_resource($image)) { switch ($exif['Orientation']) { case 3: $result = imagerotate($image, 180, 0); break; case 6: $result = imagerotate($image, -90, 0); break; case 8: $result = imagerotate($image, 90, 0); break; } } } return $result; }
stosowanie:
$rotatedFile = rotateImageByExifOrientation($absoluteFilePath); if (is_resource($rotatedFile)) { imagejpeg($rotatedFile, $absoluteFilePath, 100); }
źródło
Obraz interwencyjny ma metodę
orientate()
.$img = Image::make('foo.jpg')->orientate();
źródło