PHP read_exif_data 和调整方向

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7489742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 02:47:08  来源:igfitidea点击:

PHP read_exif_data and Adjust Orientation

phporientationexif

提问by Jeff Thomas

I am using the following code to rotate an uploaded jpeg image if the orientation is off. I am only having problems with images uploaded from iPhones and Android.

如果方向关闭,我将使用以下代码旋转上传的 jpeg 图像。我只遇到从 iPhone 和 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';
        }

Am I doing something wrong with the way I am reading the EXIF data from the jpeg? It is not rotating the images as it is supposed to.

我从 jpeg 中读取 EXIF 数据的方式是否有问题?它没有按照预期旋转图像。

This is what happens when I run a var_dump($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) }

采纳答案by Daniel Bleisteiner

The documentation for imagerotaterefers to a different type for the first parameter than you use:

imagerotate的文档引用了与您使用的第一个参数不同的类型:

An image resource, returned by one of the image creation functions, such as imagecreatetruecolor().

图像资源,由图像创建函数之一返回,例如 imagecreatetruecolor()。

Here is a small example for using this function:

下面是一个使用这个函数的小例子:

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

回答by Jonathan

Based on Daniel's code I wrote a function that simply rotates an image if necessary, without resampling.

基于 Daniel 的代码,我编写了一个函数,可以在必要时简单地旋转图像,而无需重新采样。

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

One line version (GD)

单线版 (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;
        }
    }
}

回答by user462990

Simpler function for those uploading an image, it just autorotates if necessary.

对于上传图像的人来说,功能更简单,必要时它会自动旋转。

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

回答by David Vielhuber

Why is nobody considering mirrored cases 2,4,5,7? There are 4 more cases in exif orientation land:

为什么没有人考虑镜像案例 2、4、5、7?exif方向地还有4种情况:

enter image description here

在此处输入图片说明

Here is a complete solution taking a filename:

这是采用文件名的完整解决方案:

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

回答by mr_crazy_pants

Just in case someone comes across this. From what I can make out some of the switch statements above are wrong.

以防万一有人遇到这个。从我可以看出上面的一些 switch 语句是错误的。

Based on information here, it should be:

根据这里的信息,它应该是:

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

回答by Cat

It's probably worthwhile to mention that if you are using ImageMagick from command line, you can use the -auto-orientoption which will auto rotate the image based on the existing EXIF orientation data.

值得一提的是,如果您从命令行使用 ImageMagick,您可以使用-auto-orient选项,该选项将根据现有的 EXIF 方向数据自动旋转图像。

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

Please note: If the EXIF data was stripped before the process, it will not work as described.

请注意:如果 EXIF 数据在此过程之前被剥离,它将无法按描述工作。

回答by MD. ABU TALHA

Here I'am explaining the whole thing, I use Laravel and use the Image Intervention Package.

我在这里解释整个事情,我使用 Laravel 并使用图像干预包。

First of all, I get my image and send it to my another function for resizing and some other functionality, if we do not need this, you can skip...

首先,我得到我的图像并将它发送到我的另一个函数来调整大小和其他一些功能,如果我们不需要这个,你可以跳过......

Grab the file with a method in my controller,

使用控制器中的方法抓取文件,

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

Now, I send it to resize and getting the image name and extension...

现在,我发送它来调整大小并获取图像名称和扩展名...

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

Now I call my image orientation function,

现在我调用我的图像方向函数,

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

}

And That's all...

就这样...

回答by G.P.W.

jhead -autorot jpegfile.jpg

jhead -autorot jpegfile.jpg

Is also a useful way to approach this.

也是处理此问题的有用方法。

jhead is a standard program in Linux (use 'sudo apt-get install jhead' to install), this option looks at the orientation and rotates the image correctly and losslessly only if it requires. It then also updates the EXIF data correctly.

jhead 是 Linux 中的标准程序(使用 'sudo apt-get install jhead' 安装),此选项仅在需要时查看方向并正确无损地旋转图像。然后它还会正确更新 EXIF 数据。

In this way you can process a jpeg (or multiple jpegs in a folder) in a simple one-pass way that fixes rotation issues permanently.

通过这种方式,您可以以简单的一次性方式处理一个 jpeg(或文件夹中的多个 jpeg),永久修复旋转问题。

E.g: jhead -autorot *.jpg will fix a whole folder of jpeg images in just the manner the OP requires in the initial question.

例如: jhead -autorot *.jpg 将按照 OP 在初始问题中要求的方式修复整个 jpeg 图像文件夹。

While it's not technically PHP I did read this thread and then used my jhead suggestion instead, called from a PHP system() call to achieve the results I was after which were coincident with the OPs: to rotate images so any software (like 'fbi' in Raspbian) could display them correctly.

虽然从技术上讲它不是 PHP,但我确实阅读了这个线程,然后使用了我的 jhead 建议,从 PHP system() 调用中调用以实现我所追求的结果,这与 OP 重合:旋转图像,以便任何软件(如'fbi ' 在 Raspbian 中)可以正确显示它们。

In light of this I thought others may benefit from knowing how easily jhead solves this problem and posted the information here only for informative purposes - because no one had mentioned it previously.

有鉴于此,我认为其他人可能会从了解 jhead 解决此问题的轻松程度中受益,并在此处发布信息仅供参考 - 因为之前没有人提到过。

回答by Brad Root

I hate to chime in with yet another set of orientation values, but in my experience using any of the values listed above, I always ended up with upside down images when uploading portrait orientation shots directly from an iPhone. Here's the switch statement I ended up with.

我不想加入另一组方向值,但根据我使用上面列出的任何值的经验,当直接从 iPhone 上传纵向照片时,我总是以颠倒的图像结束。这是我最终得到的 switch 语句。

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

回答by c0ld

I've also used orientate()form Intervention, and it works flawlessly.

我也使用过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);