web-dev-qa-db-ja.com

写真のショット角度を検出し、デスクトップアプリが表示時に行うようにWebサイト表示用に自動回転する方法は?

カメラで写真を撮ると、装置の向き/角度が保存されるので、良いアプリでPCで画像を表示すると、0に自動回転して表示されます。

しかし、ウェブサイトにアップロードすると元の角度が表示されるため、画像がよく見えません。

PHPでこれを検出し、画像を回転させ、メタ情報からこの角度フラグをクリアするにはどうすればよいですか?.

21
Pentium10

これを行うには、JPEGファイルからEXIF情報を読み取る必要があります。 exif PHP拡張子または PEL を使用してこれを行うことができます。

基本的に、ファイル内のOrientationフラグを読み取る必要があります。これは、画像操作に exif PHP拡張子と WideImage を使用した例です。

<?php
$exif = exif_read_data($filename);
$ort = $exif['Orientation'];

$image = WideImage::load($filename);

// Gd doesn't support EXIF, so all information is removed.
$image->exifOrient($ort)->saveToFile($filename);

class WideImage_Operation_ExifOrient
{
  /**
   * Rotates and mirrors and image properly based on current orientation value
   *
   * @param WideImage_Image $img
   * @param int $orientation
   * @return WideImage_Image
   */
  function execute($img, $orientation)
  {
    switch ($orientation) {
      case 2:
        return $img->mirror();
        break;

      case 3:
        return $img->rotate(180);
        break;

      case 4:
        return $img->rotate(180)->mirror();
        break;

      case 5:
        return $img->rotate(90)->mirror();
        break;

      case 6:
        return $img->rotate(90);
        break;

      case 7:
        return $img->rotate(-90)->mirror();
        break;

      case 8:
        return $img->rotate(-90);
        break;

      default: return $img->copy();
    }
  }
}
25
Andrew Moore

Chrisの例を変更して、exif関数のチェックを追加し、ミラーリングを削除し、同じファイル名を使用してファイルをファイルシステムに書き戻しました。このようにして、move_uploaded_fileを呼び出した直後に、次のようにこの関数を呼び出すことができます。

move_uploaded_file($uploadedFile, $destinationFilename);
correctImageOrientation($destinationFilename);

function correctImageOrientation($filename) {
  if (function_exists('exif_read_data')) {
    $exif = exif_read_data($filename);
    if($exif && isset($exif['Orientation'])) {
      $orientation = $exif['Orientation'];
      if($orientation != 1){
        $img = imagecreatefromjpeg($filename);
        $deg = 0;
        switch ($orientation) {
          case 3:
            $deg = 180;
            break;
          case 6:
            $deg = 270;
            break;
          case 8:
            $deg = 90;
            break;
        }
        if ($deg) {
          $img = imagerotate($img, $deg, 0);        
        }
        // then rewrite the rotated image back to the disk as $filename 
        imagejpeg($img, $filename, 95);
      } // if there is some rotation necessary
    } // if have the exif orientation info
  } // if function exists      
}
21
Wes

GdとphpEXIF拡張機能を使用したいだけの場合は、次のように使用できます。

function _mirrorImage ( $imgsrc)
{
    $width = imagesx ( $imgsrc );
    $height = imagesy ( $imgsrc );

    $src_x = $width -1;
    $src_y = 0;
    $src_width = -$width;
    $src_height = $height;

    $imgdest = imagecreatetruecolor ( $width, $height );

    if ( imagecopyresampled ( $imgdest, $imgsrc, 0, 0, $src_x, $src_y, $width, $height, $src_width, $src_height ) )
    {
        return $imgdest;
    }

    return $imgsrc;
}

function adjustPicOrientation($full_filename){        
    $exif = exif_read_data($full_filename);
    if($exif && isset($exif['Orientation'])) {
        $orientation = $exif['Orientation'];
        if($orientation != 1){
            $img = imagecreatefromjpeg($full_filename);

            $mirror = false;
            $deg    = 0;

            switch ($orientation) {
              case 2:
                $mirror = true;
                break;
              case 3:
                $deg = 180;
                break;
              case 4:
                $deg = 180;
                $mirror = true;  
                break;
              case 5:
                $deg = 270;
                $mirror = true; 
                break;
              case 6:
                $deg = 270;
                break;
              case 7:
                $deg = 90;
                $mirror = true; 
                break;
              case 8:
                $deg = 90;
                break;
            }
            if ($deg) $img = imagerotate($img, $deg, 0); 
            if ($mirror) $img = _mirrorImage($img);
            $full_filename = str_replace('.jpg', "-O$orientation.jpg",  $full_filename); 
            imagejpeg($img, $full_filename, 95);
        }
    }
    return $full_filename;
}
17
Chris Cinelli

回転フラグはEXIFデータの一部として保存されます(詳細については、 この記事 を参照してください)。

PHPのEXIFデータから回転フラグを読み取り、それに合わせて画像を回転させる必要があります。さまざまなPHP EXIFライブラリがある場合は、拡張機能がインストールされたWebサーバーをセットアップすると、 PHPが提供するライブラリ を使用できるようになります。

アップロード時に画像を1回回転させることをお勧めします(たとえば、 Gdライブラリ -ほとんどのPHPインストールには付属しているようです)を使用してください)。 EXIFローテーションデータのクリアについて心配する必要があります(これがPHPでどれほど簡単かはわかりませんが、試したことはありません)。

2
user7094