PHP read_exif_data और ओरिएंटेशन समायोजित करें


79

अगर ओरिएंटेशन बंद है तो मैं अपलोड की गई jpeg छवि को घुमाने के लिए निम्न कोड का उपयोग कर रहा हूं। मुझे केवल iPhones और Android से अपलोड की गई छवियों के साथ समस्या हो रही है।

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';
        }

मैं जिस तरह से मैं jpeg से EXIF ​​डेटा पढ़ रहा हूँ के साथ कुछ गलत कर रहा हूँ? माना जाता है कि यह छवियों को नहीं घुमा रहा है।

ऐसा तब होता है जब मैं 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) }

ध्यान दें कि यह कोड स्रोत छवि को फिर से प्रिंट करेगा, भले ही कोई रोटेशन की आवश्यकता न हो।
मार्क बी

अभी मेरी समस्या यह है कि जिन छवियों को घुमाने की आवश्यकता है, उन्हें घुमाया नहीं जा रहा है।
जेफ थॉमस

var_dump($exif)रोटेशन डेटा के तरीके में एंड्रॉइड फोन क्या उत्पादन कर रहे हैं यह देखने के लिए एक करें ।
मार्क बी

1
ठीक है, मैं वहाँ डंप साफ किया। जाहिर है। उन्मुखीकरण क्षेत्र, एक 'IFD0' अनुभाग में नहीं है, यह है $exif['COMPUTED']['Orientation']और मूल्य 6. है
मार्क बी

1
$ exif ['ओरिएंटेशन']; मेरे लिए ठीक काम कर रहा है। यह $ exif ['some_section'] ['ओरिएंटेशन'] की तुलना में एक बेहतर विकल्प हो सकता है;
डेमोस्टेन

जवाबों:


63

इमेजरोटेट के लिए प्रलेखन आपके द्वारा उपयोग किए जाने वाले पहले पैरामीटर के लिए एक अलग प्रकार को संदर्भित करता है:

एक छवि संसाधन, छवि निर्माण कार्यों में से एक, जैसे कि imagecreatetruecolor ()।

इस फ़ंक्शन का उपयोग करने के लिए एक छोटा सा उदाहरण यहां दिया गया है:

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);
}

किसी कारण से, एंड्रॉइड 4.1.2 द्वारा बनाई गई छवियों को घुमाए जाने की आवश्यकता नहीं है, केवल "imagecreatefromjpen ()" द्वारा छवि को लोड करें और फिर इसे "imagejpeg ()" के साथ वापस सहेजें। तुम जानते हो क्यों?
डोरन

76

डैनियल के कोड के आधार पर मैंने एक फ़ंक्शन लिखा है जो बस एक छवि को घुमाता है, यदि आवश्यक हो, तो फिर से शुरू किए बिना।

गोलों का अंतर

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;
        }
    }
}

एक पंक्ति संस्करण (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;
        }
    }
}

इमेजिक के लिए मैं ओरिएंटेशन प्राप्त करने के लिए getImageOrientation () का उपयोग करता हूं और फिर इमेज को रोटेट करने के बाद मैंने $ Ex Image के जरिए सही Exif ओरिएंटेशन वैल्यू सेट की है-> setImageOrientation (\ Imagick :: ORIATION_T_TLELEFT);
तिलमैन

क्या आपके पास वाइडइमेज का हल है?
यामी मदीना

कुछ मामलों में कल्पनाशील फ़ंक्शन getImageOrientation()ने मेरे लिए सही रूप से परिवर्तित छवियों के साथ भी सही ढंग से काम नहीं किया। ऊपर दिए गए कोड ने पूरी तरह से काम किया।
'13:01 पर rokdd

पहले संस्करण (GD) में मुझे उस फ़ंक्शन के लिए और $ छवि के लिए क्या करना चाहिए जहां मैं कॉल कर रहा हूं?
भारत माहेश्वरी

2
जिनके लिए समझ में नहीं आता है कि स्थानीय फ़ाइल से छवि पैरामीटर कैसे पारित किया जाए, इस तरह का उपयोग करें: $ im = @imagecreatefromjpeg ($ local_filename); image_fix_orientation ($ im, $ local_filename); if ($ im) {imagejpeg ($ im, $ local_filename); imagedestroy ($ im); }
वोहरदास

43

एक छवि अपलोड करने वालों के लिए सरल कार्य, यदि आवश्यक हो तो यह केवल ऑटोरॉट करता है।

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);
    }
}

1
इस उत्तर को एक सरल कंपोज़र पैकेज में बनाया गया, जिसे जीथब पर पाया जा सकता है (केवल एक विधि के साथ वर्ग): github.com/diversen/image-auto-rotate
dennis

आप गलत डिग्री मूल्यों का उपयोग करते हैं। मामले में 6 आपको 90 की जरूरत है और मामले में आपको 8 डिग्री की जरूरत है।
बर्नहार्ड

बहुत उपयोगी कार्य, अगर किसी को यह चेतावनी दिखाई देती है तो अवैध IFD आकार आप @ ऑपरेटर का उपयोग कर सकते हैं जैसे : $exif = @exif_read_data($filename);
chebaby

@ user462990 यह फ़ंक्शन अच्छी तरह से काम करता है, लेकिन केवल स्थानीय स्तर पर छवियों के लिए। एक छवि url पास करने के बारे में कैसे जाना जाएगा? मेरे पास s3 पर एक छवि है जिसे मुझे अभिविन्यास में हेरफेर करने की आवश्यकता है।
अल्ट्रासाउंड

12

कोई भी प्रतिबिंबित मामलों 2,4,5,7 पर विचार क्यों नहीं कर रहा है? एक्सिफ ओरिएंटेशन लैंड में 4 और मामले हैं:

यहाँ छवि विवरण दर्ज करें

यहाँ एक फ़ाइलनाम लेने का पूरा समाधान है:

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;
}

उत्कृष्ट समाधान। यह एक अच्छा बिंदु था क्योंकि कई उपयोगकर्ता प्रतिबिंबित चित्र अपलोड करते हैं और उन्हें अपनी अंतिम छवि के साथ समस्या होती है।
अल्बर्ट थॉम्पसन

6

बस किसी के पास इस मामले में आता है। क्या मैं ऊपर के कुछ स्विच स्टेटमेंट को गलत बना सकता हूं।

यहाँ जानकारी के आधार पर , यह होना चाहिए:

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;
} 

6

शायद यह उल्लेख करना सार्थक है कि यदि आप कमांड लाइन से ImageMagick का उपयोग कर रहे हैं, तो आप -ऑटो-ओरिएंट विकल्प का उपयोग कर सकते हैं जो मौजूदा EXIF ​​अभिविन्यास डेटा के आधार पर छवि को घुमाएगा।

convert -auto-orient /tmp/uploadedImage.jpg /save/to/path/image.jpg

कृपया ध्यान दें: यदि प्रक्रिया से पहले EXIF ​​डेटा छीन लिया गया था, तो यह वर्णित के रूप में काम नहीं करेगा।


2

यहाँ मैं पूरी बात समझा रहा हूँ, मैं लारवेल का उपयोग करता हूँ और इमेज इंटरवेंशन पैकेज का उपयोग करता हूँ।

सबसे पहले, मैं अपनी छवि प्राप्त करता हूं और इसे आकार देने और कुछ अन्य कार्यक्षमता के लिए अपने दूसरे फ़ंक्शन पर भेजता हूं, अगर हमें इसकी आवश्यकता नहीं है, तो आप इसे छोड़ सकते हैं ...

मेरे नियंत्रक में एक विधि के साथ फ़ाइल को पकड़ो,

 public  function getImageFile(Request $request){
    $image = $request->image;
    $this->imageUpload($image);
}

अब, मैं इसे आकार और छवि नाम और एक्सटेंशन प्राप्त करने के लिए भेजता हूं ...

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;
}

अब मैं अपने इमेज ओरिएंटेशन फंक्शन को कॉल करता हूं,

 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);
    }

}

और बस यही...


1

मैं अभी तक अभिविन्यास मूल्यों के एक और सेट के साथ झंकार से नफरत करता हूं, लेकिन ऊपर सूचीबद्ध किसी भी मूल्य का उपयोग करते हुए मेरे अनुभव में, मैं हमेशा एक iPhone से सीधे पोर्ट्रेट ओरिएंटेशन शॉट्स अपलोड करते समय छवियों के साथ समाप्त हो गया। यहाँ स्विच स्टेटमेंट दिया गया है।

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;
    }

1

jhead -autorot jpegfile.jpg

इसके लिए एक उपयोगी तरीका भी है।

Linux में jhead एक मानक प्रोग्राम है ('sudo apt-get install jhead' का उपयोग करने के लिए), यह विकल्प ओरिएंटेशन को देखता है और आवश्यक रूप से केवल छवि को सही और दोषरहित रूप से घुमाता है। यह तब EXIF ​​डेटा को भी सही ढंग से अपडेट करता है।

इस तरह आप एक जेपीईजी (या एक फ़ोल्डर में कई jpegs) को सरल एक-पास तरीके से संसाधित कर सकते हैं जो रोटेशन की समस्याओं को स्थायी रूप से ठीक करता है।

उदाहरण: jhead -autorot * .jpg जेपीआर छवियों के एक पूरे फ़ोल्डर को ठीक उसी तरह से ठीक करेगा जिस तरह से प्रारंभिक प्रश्न में ओपी की आवश्यकता होती है।

हालांकि यह तकनीकी रूप से PHP नहीं है, मैंने इस धागे को पढ़ा और फिर इसके बजाय अपने jhead सुझाव का उपयोग किया, परिणाम प्राप्त करने के लिए PHP सिस्टम () कॉल से कॉल किया, जिसके बाद मैं OPs के साथ संयोग कर रहा था: छवियों को घुमाने के लिए किसी भी सॉफ्टवेयर (जैसे 'fbi) 'रस्पियन में) उन्हें सही ढंग से प्रदर्शित कर सकता था।

इसके प्रकाश में, मुझे लगा कि दूसरों को यह जानने से फायदा हो सकता है कि कितनी आसानी से इस समस्या को हल करता है और जानकारीपूर्ण प्रयोजनों के लिए यहां केवल जानकारी पोस्ट की है - क्योंकि किसी ने भी पहले इसका उल्लेख नहीं किया था।


आपके उत्तर को निम्न गुणवत्ता के रूप में चिह्नित किया गया था क्योंकि यह छोटा था। अपने समाधान को अधिक गहराई से समझाने का प्रयास करें।
डेरेक ब्राउन

1

मैंने orientate()फॉर्म इंटरवेंशन का भी उपयोग किया है, और यह त्रुटिपूर्ण रूप से काम करता है।

    $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);

1

यहाँ मेरा PHP 7 फ़ंक्शन @ 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;
}

उपयोग:

    $rotatedFile = rotateImageByExifOrientation($absoluteFilePath);
    if (is_resource($rotatedFile)) {
        imagejpeg($rotatedFile, $absoluteFilePath, 100);
    }

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.