2024 年日本 PHP 研討會

exif_read_data

(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)

exif_read_data從影像檔讀取 EXIF 標頭

說明

exif_read_data(
    資源|字串 $file,
    ?字串 $required_sections = null,
    布林 $as_arrays = false,
    布林值 $read_thumbnail = false
): 陣列|false

exif_read_data() 會從影像檔讀取 EXIF 標頭。透過這種方式,您可以讀取數位相機產生的詮釋資料。

數位相機產生的 JPEG/TIFF 影像通常會包含 EXIF 標頭,但可惜的是,每個數位相機製造商對於如何標記影像都有不同的想法,所以您不能總是依賴特定的 Exif 標頭存在。

Height(高度)和 Width(寬度)的計算方式與 getimagesize() 相同,因此它們的值不應該包含在任何返回的標頭中。此外,html 是一個高度/寬度文字字串,用於一般 HTML 中。

當 Exif 標頭包含版權說明時,它本身可以包含兩個值。由於 Exif 2.10 標準中的解決方案並不一致,COMPUTED 區段會返回 Copyright.Photographer(攝影師版權)和 Copyright.Editor(編輯者版權)兩個項目,而 IFD0 區段則包含以 NULL 字元分隔兩個項目的位元組陣列。或者,如果資料類型錯誤,則只包含第一個項目(Exif 的正常行為)。COMPUTED 區段還會包含 Copyright 項目,它可以是原始版權字串,也可以是以逗號分隔的攝影師和編輯者版權列表。

UserComment 標籤與版權標籤有相同的問題。它可以儲存兩個值。首先是使用的編碼,其次是值本身。如果是這樣,IFD 區段只包含編碼或位元組陣列。COMPUTED 區段會將兩者儲存在 UserCommentEncodingUserComment 項目中。兩種情況下都會提供 UserComment 項目,因此應該優先使用它,而不是 IFD0 區段中的值。

exif_read_data() 也會根據 EXIF 規格(» http://exif.org/Exif2-2.PDF,第 20 頁)驗證 EXIF 資料標籤。

參數

file(檔案)

影像檔的位置。這可以是檔案的路徑(也支援串流包裝器)或串流 資源

required_sections(必要區段)

是以逗號分隔的區段列表,這些區段必須存在於檔案中才能產生 陣列 結果。如果找不到任何請求的區段,則返回值為 false

FILE(檔案) FileName(檔案名稱)、FileSize(檔案大小)、FileDateTime(檔案日期時間)、SectionsFound(找到的區段)
COMPUTED(計算值) html、Width(寬度)、Height(高度)、IsColor(是否彩色),以及其他可用的資訊。Height 和 Width 的計算方式與 getimagesize() 相同,因此它們的值不應該包含在任何返回的標頭中。此外,html 是一個高度/寬度文字字串,用於一般 HTML 中。
ANY_TAG(任何標籤) 任何具有標籤的資訊,例如 IFD0EXIF 等。
IFD0 IFD0 的所有標籤資料。在一般的影像檔中,這包含影像大小等等。
THUMBNAIL(縮圖) 如果檔案具有第二個 IFD,則該檔案應該包含縮圖。所有關於嵌入縮圖的標籤資訊都儲存在這個區段中。
COMMENT(註釋) JPEG 影像的註釋標頭。
EXIF(可交換圖檔格式) EXIF 區段是 IFD0 的子區段。它包含更詳細的影像資訊。這些項目大多與數位相機相關。

as_arrays(作為陣列)

指定每個區段是否成為陣列。 required_sections 中的 COMPUTEDTHUMBNAILCOMMENT 永遠會成為陣列,因為它們可能包含名稱與其他區段衝突的值。

read_thumbnail(讀取縮圖)

當設定為 true 時,會讀取縮圖本身。否則,只會讀取標籤資料。

傳回值

它傳回一個關聯式 陣列,其中陣列索引是標頭名稱,陣列值是與這些標頭關聯的值。如果沒有資料可以傳回,exif_read_data() 將傳回 false

錯誤/例外

對於不支援的標籤或其他潛在的錯誤情況,可能會引發等級 E_WARNING 和/或 E_NOTICE 的錯誤,但函式仍會嘗試讀取所有可理解的資訊。

更新日誌

版本 說明
8.0.0 required_sections 現在可以為 null。
7.2.0 file 參數現在同時支援本地檔案和串流資源。
7.2.0

新增了以下 EXIF 格式的支援:

  • Samsung(三星)
  • DJI(大疆)
  • Panasonic(松下)
  • Sony(索尼)
  • Pentax(賓得士)
  • Minolta(美能達)
  • Sigma/Foveon(適馬/ፎቪዮን)
  • AGFA(愛克發)
  • Kyocera(京瓷)
  • Ricoh(理光)
  • Epson(愛普生)

範例

範例 #1 exif_read_data() 範例

<?php
echo "test1.jpg:<br />\n";
$exif = exif_read_data('tests/test1.jpg', 'IFD0');
echo
$exif===false ? "找不到標頭資料。<br />\n" : "影像包含標頭<br />\n";

$exif = exif_read_data('tests/test2.jpg', 0, true);
echo
"test2.jpg:<br />\n";
foreach (
$exif as $key => $section) {
foreach (
$section as $name => $val) {
echo
"$key.$name: $val<br />\n";
}
}
?>

第一次呼叫失敗,因為影像沒有標頭資訊。

上述範例將輸出類似以下的內容:

test1.jpg:
No header data found.
test2.jpg:
FILE.FileName: test2.jpg
FILE.FileDateTime: 1017666176
FILE.FileSize: 1240
FILE.FileType: 2
FILE.SectionsFound: ANY_TAG, IFD0, THUMBNAIL, COMMENT
COMPUTED.html: width="1" height="1"
COMPUTED.Height: 1
COMPUTED.Width: 1
COMPUTED.IsColor: 1
COMPUTED.ByteOrderMotorola: 1
COMPUTED.UserComment: Exif test image.
COMPUTED.UserCommentEncoding: ASCII
COMPUTED.Copyright: Photo (c) M.Boerger, Edited by M.Boerger.
COMPUTED.Copyright.Photographer: Photo (c) M.Boerger
COMPUTED.Copyright.Editor: Edited by M.Boerger.
IFD0.Copyright: Photo (c) M.Boerger
IFD0.UserComment: ASCII
THUMBNAIL.JPEGInterchangeFormat: 134
THUMBNAIL.JPEGInterchangeFormatLength: 523
COMMENT.0: Comment #1.
COMMENT.1: Comment #2.
COMMENT.2: Comment #3end
THUMBNAIL.JPEGInterchangeFormat: 134
THUMBNAIL.Thumbnail.Height: 1
THUMBNAIL.Thumbnail.Height: 1

範例 #2 從 PHP 7.2.0 開始,exif_read_data() 支援串流。

<?php
// 開啟檔案,需以二進位模式開啟
$fp = fopen('/path/to/image.jpg', 'rb');

if (!
$fp) {
echo
'錯誤:無法開啟圖片以讀取';
exit;
}

// 嘗試讀取 EXIF 標頭
$headers = exif_read_data($fp);

if (!
$headers) {
echo
'錯誤:無法讀取 EXIF 標頭';
exit;
}

// 顯示 'COMPUTED' 標頭
echo 'EXIF 標頭:' . PHP_EOL;

foreach (
$headers['COMPUTED'] as $header => $value) {
printf(' %s => %s%s', $header, $value, PHP_EOL);
}
?>

上述範例將輸出類似以下的內容:

EXIF Headers:
 Height => 576
 Width => 1024
 IsColor => 1
 ByteOrderMotorola => 0
 ApertureFNumber => f/5.6
 UserComment =>
 UserCommentEncoding => UNDEFINED
 Copyright => Denis
 Thumbnail.FileType => 2
 Thumbnail.MimeType => image/jpeg

注意事項

備註:

如果啟用了 mbstring,exif 會嘗試處理 unicode 並根據 exif.decode_unicode_motorolaexif.decode_unicode_intel 的指定選取字元集。exif 擴充功能不會嘗試自行判斷編碼,使用者必須在呼叫 exif_read_data() 之前,透過設定這兩個 ini 指令碼的其中一個,來正確指定用於解碼的編碼。

備註:

如果使用 file 將串流傳遞給此函式,則該串流必須是可搜尋的。請注意,此函式返回後,檔案指標位置不會改變。

參見

新增註記

使用者貢獻的註記 19 則註記

83
chadsmith729 at gmail dot com
11 年前
Apple 推出的 iOS6 更新為 iPad、iPod 和 iPhone 提供了透過 Safari 從裝置上傳檔案的功能。顯然地,這將開啟一系列過去不可能實現的應用。

問題在於,上傳照片時,照片的方向會取決於拍攝照片時「按鈕」的位置。想像一下,如果你的 iPhone 轉過來,按鈕在頂部,然後你拍了一張照片。上傳到伺服器的照片可能會「上下顛倒」。

以下程式碼將確保所有上傳的照片在方向上都是正確的
<?php
$image
= imagecreatefromstring(file_get_contents($_FILES['image_upload']['tmp_name']));
$exif = exif_read_data($_FILES['image_upload']['tmp_name']);
if(!empty(
$exif['Orientation'])) {
switch(
$exif['Orientation']) {
case
8:
$image = imagerotate($image,90,0);
break;
case
3:
$image = imagerotate($image,180,0);
break;
case
6:
$image = imagerotate($image,-90,0);
break;
}
}
// $image 現在包含一個已正確調整方向的圖片資源
?>

後續如何處理這個圖片資源完全取決於您。

希望這能幫助您識別並調整任何從 iPad、iPhone 或 iPod 上傳的圖片方向。照片的方向是正確旋轉的關鍵。
3
Tim
5 年前
以下程式碼
<?php
$data
= exif_read_data('foo.jpg');
var_dump($data['Keywords']);
?>
會產生 string(15) "???????????????"

在呼叫 exif_read_data 之前加入
<?php
ini_set
('exif.decode_unicode_motorola', 'UCS-2LE');
?>
會產生
string(15) "landscape;;field"
6
darkain at darkain dot com
16 年前
我需要一些簡單快速的函式來計算快門速度和光圈值。我在任何地方都找不到,所以我寫了一些。這需要一些研究

<?php
函數 exif_get_float($value) {
$pos = strpos($value, '/');
如果 (
$pos === false) 返回 (float) $value;
$a = (float) substr($value, 0, $pos);
$b = (float) substr($value, $pos+1);
返回 (
$b == 0) ? ($a) : ($a / $b);
}

函數
exif_get_shutter(&$exif) {
如果 (!isset(
$exif['ShutterSpeedValue'])) 返回 false;
$apex = exif_get_float($exif['ShutterSpeedValue']);
$shutter = pow(2, -$apex);
如果 (
$shutter == 0) 返回 false;
如果 (
$shutter >= 1) 返回 round($shutter) . 's';
返回
'1/' . round(1 / $shutter) . 's';
}

函數
exif_get_fstop(&$exif) {
如果 (!isset(
$exif['ApertureValue'])) 返回 false;
$apex = exif_get_float($exif['ApertureValue']);
$fstop = pow(2, $apex/2);
如果 (
$fstop == 0) 返回 false;
返回
'f/' . round($fstop,1);
}
?>
7
drpain at webster dot org dot za
12 年前
請注意,使用 GD 以及大多數影像處理腳本或應用程式調整影像大小時,您將會遺失 EXIF 資訊。我的解決方法是在重新調整影像大小之前,將這些資訊儲存到 MySQL。

<?php

// This function is used to determine the camera details for a specific image. It returns an array with the parameters.
function cameraUsed($imagePath) {

// Check if the variable is set and if the file itself exists before continuing
if ((isset($imagePath)) and (file_exists($imagePath))) {

// There are 2 arrays which contains the information we are after, so it's easier to state them both
$exif_ifd0 = read_exif_data($imagePath ,'IFD0' ,0);
$exif_exif = read_exif_data($imagePath ,'EXIF' ,0);

//error control
$notFound = "Unavailable";

// Make
if (@array_key_exists('Make', $exif_ifd0)) {
$camMake = $exif_ifd0['Make'];
} else {
$camMake = $notFound; }

// Model
if (@array_key_exists('Model', $exif_ifd0)) {
$camModel = $exif_ifd0['Model'];
} else {
$camModel = $notFound; }

// Exposure
if (@array_key_exists('ExposureTime', $exif_ifd0)) {
$camExposure = $exif_ifd0['ExposureTime'];
} else {
$camExposure = $notFound; }

// Aperture
if (@array_key_exists('ApertureFNumber', $exif_ifd0['COMPUTED'])) {
$camAperture = $exif_ifd0['COMPUTED']['ApertureFNumber'];
} else {
$camAperture = $notFound; }

// Date
if (@array_key_exists('DateTime', $exif_ifd0)) {
$camDate = $exif_ifd0['DateTime'];
} else {
$camDate = $notFound; }

// ISO
if (@array_key_exists('ISOSpeedRatings',$exif_exif)) {
$camIso = $exif_exif['ISOSpeedRatings'];
} else {
$camIso = $notFound; }

$return = array();
$return['make'] = $camMake;
$return['model'] = $camModel;
$return['exposure'] = $camExposure;
$return['aperture'] = $camAperture;
$return['date'] = $camDate;
$return['iso'] = $camIso;
return
$return;

} else {
return
false;
}
}

?>

以下是使用範例

<?php

$camera
= cameraUsed("/img/myphoto.jpg");
echo
"使用的相機: " . $camera['make'] . " " . $camera['model'] . "<br />";
echo
"曝光時間: " . $camera['exposure'] . "<br />";
echo
"光圈值: " . $camera['aperture'] . "<br />";
echo
"ISO 值: " . $camera['iso'] . "<br />";
echo
"拍攝日期: " . $camera['date'] . "<br />";

?>

將根據資料顯示以下內容

使用的相機: SONY DSC-S930
曝光時間: 1/400
光圈值: f/4.3
ISO 值: 100
拍攝日期: 2010:12:10 18:18:45

如果圖片已被調整大小且資訊不再可用,則在輸出相同內容時,您應該會收到以下訊息

使用的相機: 無法取得
曝光時間: 無法取得
光圈值: 無法取得
ISO 值: 無法取得
拍攝日期: 無法取得

有些相機並不會擷取所有資訊,例如黑莓機就不會記錄光圈值或 ISO 值,因此這些欄位會顯示「無法取得」。

希望對您有所幫助。
4
mafo at mafo removethis dot sk
17 年前
有些相機(大多數較高階的機種)配有位置感測器(陀螺儀?),拍攝位置會寫入 EXIF 中,以下是一個自動旋轉圖片的簡單腳本

<?php
$exif
= exif_read_data($filename);
$ort = $exif['IFD0']['Orientation'];
switch(
$ort)
{
case
1: // 無須動作
break;

case
2: // 水平翻轉
$image->flipImage($public,1);
break;

case
3: // 向左旋轉 180 度
$image->rotateImage($public,180);
break;

case
4: // 垂直翻轉
$image->flipImage($public,2);
break;

case
5: // 垂直翻轉 + 向右旋轉 90 度
$image->flipImage($public, 2);
$image->rotateImage($public, -90);
break;

case
6: // 向右旋轉 90 度
$image->rotateImage($public, -90);
break;

case
7: // 水平翻轉 + 向右旋轉 90 度
$image->flipImage($public,1);
$image->rotateImage($public, -90);
break;

case
8: // 向左旋轉 90 度
$image->rotateImage($public, 90);
break;
}

?>

$image->rotateImage() 的靈感來自於 https://php.dev.org.tw/manual/en/function.imagerotate.php 的範例
$image->flipImage() 的靈感來自於 https://php.dev.org.tw/manual/en/function.imagecopy.php#42803 (感謝)
1
omerg at lucidcode dot com dot tr
5 年前
用於顯示 exif 陣列內容的範例在最近的版本中無法正常運作,因為並非所有項目值都是陣列類型。

這是另一種 echo 迴圈

<?php
echo "test1.jpg:<br />\n";
$exif = exif_read_data('tests/test1.jpg', 'IFD0');
echo
$exif===false ? "No header data found.<br />\n" : "Image contains headers<br />\n";

$exif = exif_read_data('tests/test2.jpg', 0, true);
echo
"test2.jpg:<br />\n";
foreach (
$exif as $key => $section) {

if (!
is_array ($section)) {
echo
"$key: $section<br />\n";
} else {
foreach (
$section as $name => $val) {
echo
"$key.$name: $val<br />\n";
}
}

}
?>
1
TNTcode
7 年前
<?php

// auto rotates an image file based on exif data from camera
// if destination file is specified then it saves file there, otherwise it will display it to user
// note that images already at normal orientation are skipped (when exif data Orientation = 1)

if(!function_exists("gd_auto_rotate")){
function
gd_auto_rotate($original_file, $destination_file=NULL){

$original_extension = strtolower(pathinfo($original_file, PATHINFO_EXTENSION));
if(isset(
$destination_file) and $destination_file!=''){
$destination_extension = strtolower(pathinfo($destination_file, PATHINFO_EXTENSION));
}

// try to auto-rotate image by gd if needed (before editing it)
// by imagemagik it has an easy option
if(function_exists("exif_read_data")){

$exif_data = exif_read_data($original_file);
$exif_orientation = $exif_data['Orientation'];

// value 1 = normal ?! skip it ?!

if($exif_orientation=='3' or $exif_orientation=='6' or $exif_orientation=='8'){

$new_angle[3] = 180;
$new_angle[6] = -90;
$new_angle[8] = 90;

// load the image
if($original_extension == "jpg" or $original_extension == "jpeg"){
$original_image = imagecreatefromjpeg($original_file);
}
if(
$original_extension == "gif"){
$original_image = imagecreatefromgif($original_file);
}
if(
$original_extension == "png"){
$original_image = imagecreatefrompng($original_file);
}

$rotated_image = imagerotate($original_image, $new_angle[$exif_orientation], 0);

// if no destination file is set, then show the image
if(!$destination_file){
header('Content-type: image/jpeg');
imagejpeg($rotated_image, NULL, 100);
}

// save the smaller image FILE if destination file given
if($destination_extension == "jpg" or $destination_extension=="jpeg"){
imagejpeg($rotated_image, $destination_file,100);
}
if(
$destination_extension == "gif"){
imagegif($rotated_image, $destination_file);
}
if(
$destination_extension == "png"){
imagepng($rotated_image, $destination_file,9);
}

imagedestroy($original_image);
imagedestroy($rotated_image);

}
}
}
}

?>
1
Eion Robb
9 年前
我需要使用 exif_read_data() 讀取方向標記,卻發現虛擬主機沒有可用的 exif 擴充功能。因此,我修改了一個正規表達式,它可以作為一個相當不錯的替代方案。

<?php
$orientation
= 1;
if (
function_exists('exif_read_data')) {
$exif = exif_read_data($filename);
if (isset(
$exif['Orientation']))
$orientation = $exif['Orientation'];
} else if (
preg_match('@\x12\x01\x03\x00\x01\x00\x00\x00(.)\x00\x00\x00@', file_get_contents($filename), $matches)) {
$orientation = ord($matches[1]);
}
?>
0
dbareis at gmail dot com
5 個月前
Windows 欄位位於「WINXP」區段(我不清楚其格式),但它們也存在於其他位置,包括以空值終止的「UTF-16LE」格式的「註釋」和「主題」,這段程式碼對我有效

...
$PhotoInfo->Comments = GetPhotoValueWindows16Bit($IDFO, 'Comments');
$PhotoInfo->Subject = GetPhotoValueWindows16Bit($IDFO, 'Subject');

函數 GetPhotoValueWindows16Bit(&$Array, $Index)
{
$Value16 = GetPhotoValue($Array, $Index);
if ($Value16 === null)
$R = null;
else
{
$R = iconv('UTF-16LE', 'UTF-8', $Value16); //仍以空位元組結尾
$R = str_replace("\x00", '', $R); //移除尾端空值(但處理任何空值)。
}
return $R;
}
0
service at tianex dot com
11 個月前
取得 JPEG 檔案 EXIF 資訊時發生此錯誤

exif_read_data(): 檔案讀取錯誤: got=x3FFA(=16378) != itemlen-2=x4325(=17189)
0
b at asdflolinternet dot de
9 年前
當值 (例如 exif[IFD0][Title]) 中的 "S�o�m�e� �T�e�x�t��" 透過 Windows 右鍵點擊內容編輯,然後使用 read_exif_data() 函數讀取時,會發生問題。
試著

$exif_['IFD0']['Title']=mb_convert_encoding($exif_['IFD0']['Title'],"auto","byte2le");

適用於 UTF-8 等。

//
// 輸出所有可用的字元編碼並顯示在螢幕上
// foreach(mb_list_encodings() as $chr)
// {$test[$chr]=mb_convert_encoding($image[IFD0][Title],'auto',$chr);}
// exit(print_r($test));
//
0
Clive dot Moore at ma-design dot com
10 年前
接續 darkain at darkain dot com 的腳本,用於從 EXIF 資料中擷取 ShutterSpeedValue...
@https://php.dev.org.tw/manual/en/function.exif-read-data.php

我發現 ShutterSppedValue 顯示的選項在 EXIF 資料中也可以是 ExposureTime。

此外,編寫的程式碼會提供錯誤的返回值,因為返回值始終為 1,所以您會得到 1/1 秒。

以下是修正後的程式碼,或是在原始開發 5 年後明顯無法運作的修正版本:

以下是 $exif[ExposureTime] 的更新版本:

function exif_get_float($value) {
$pos = strpos($value, '/');
if ($pos === false) return (float) $value;
$a = (float) substr($value, 0, $pos);
$b = (float) substr($value, $pos+1);
return ($b == 0) ? ($a) : ($a / $b);
};

function exif_get_exposureTime(&$exif) {
if (!isset($exif['ExposureTime'])) return false;
$apex = exif_get_float($exif['ExposureTime']);
$shutter = 1/$apex;
// 超過 1 秒的曝光時間:
if ($shutter <= 1) return round($apex) . ' 秒';

return '1/' . round(1 / $apex) . '秒';
};
0
hoangvu4000 at gmail dot com
11 年前
這是用於調整影像大小且不旋轉具有 EXIF 資訊的影像的函數

必須啟用 PHP
extension=php_mbstring.dll
extension=php_exif.dll

<?php
function CreateThumbnail($pic,$thumb,$thumbwidth, $quality = 100)
{

$im1=ImageCreateFromJPEG($pic);

//if(function_exists("exif_read_data")){
$exif = exif_read_data($pic);
if(!empty(
$exif['Orientation'])) {
switch(
$exif['Orientation']) {
case
8:
$im1 = imagerotate($im1,90,0);
break;
case
3:
$im1 = imagerotate($im1,180,0);
break;
case
6:
$im1 = imagerotate($im1,-90,0);
break;
}
}
//}
$info = @getimagesize($pic);

$width = $info[0];

$w2=ImageSx($im1);
$h2=ImageSy($im1);
$w1 = ($thumbwidth <= $info[0]) ? $thumbwidth : $info[0] ;

$h1=floor($h2*($w1/$w2));
$im2=imagecreatetruecolor($w1,$h1);

imagecopyresampled ($im2,$im1,0,0,0,0,$w1,$h1,$w2,$h2);
$path=addslashes($thumb);
ImageJPEG($im2,$path,$quality);
ImageDestroy($im1);
ImageDestroy($im2);
}
?>
0
michael [at[ thisiswilson [dot[ com
16 年前
來自 - darkain at darkain dot com 的範例。

如果所有資料都來自同一張影像 - 只需

<?php
$exif_data
= exif_read_data ( $_FILES['photo']

$emake =$exif_data['Make'];
$emodel = $exif_data['Model'];
$eexposuretime = $exif_data['ExposureTime'];
$efnumber = $exif_data['FNumber'];
$eiso = $exif_data['ISOSpeedRatings'];
$edate = $exif_data['DateTime'];
?>

這樣可以運作,我嘗試使用 PEL 函式庫,雖然很酷,但我完全搞不懂如何呼叫某些東西,如果你的系統很基本或者你趕時間的話,這樣比較簡單。如果你有時間,可以試試 PEL。 儘管它目前沒有維護了。

http://pel.sourceforge.net/
0
匿名
17 年前
從 'WINXP' 群組讀取 EXIF 資訊時,您可能需要將使用的編碼從預設的 "ISO-8859-15" 改為 "UTF-8"。這可以在 php.ini 或您的程式碼中完成

<?php
ini_set
('exif.encode_unicode', 'UTF-8');

$exif = exif_read_data('TEST.JPG', 0, true);
echo
$exif['WINXP']['Title'];
?>

關於 EXIF 的有用文件
http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html
另請參閱 XPTitle 和 XPAuthor 旁邊的註釋。
-1
iam at thatguy dot co dot za
10 年前
我發布了這個函式的原始版本,但在使用一段時間後,我發現我沒有做足夠的錯誤檢查。

我對它進行了一些重構,現在如果它無法讀取圖像的 exif,它將返回一個空陣列。如果可以讀取,它將返回它能夠檢索到的詳細資訊。而且這應該不會出錯。

我正在抑制錯誤,因為如果您傳遞無法解析的圖像,您將收到警告。

<?php

# Modified Version of cameraUsed, no longer returns date.
public function cameraUsed($imagePath)
{
# The default empty return
$return = array(
'make' => "",
'model' => "",
'exposure' => "",
'aperture' => "",
'iso' => ""
);

// Check if the variable is set and if the file itself exists before continuing
if ((isset($imagePath)) AND (file_exists($imagePath)))
{
// There are 2 arrays which contains the information we are after, so it's easier to state them both
$exif_ifd0 = @read_exif_data($imagePath ,'IFD0' ,0);
$exif_exif = @read_exif_data($imagePath ,'EXIF' ,0);

# Ensure that we actually got some information
if (($exif_ifd0 !== false) AND ($exif_exif !== false))
{
// Make
if (@array_key_exists('Make', $exif_ifd0))
{
$return['make'] = $exif_ifd0['Make'];
}

// Model
if (@array_key_exists('Model', $exif_ifd0))
{
$return['model'] = $exif_ifd0['Model'];
}

// Exposure
if (@array_key_exists('ExposureTime', $exif_ifd0))
{
$return['exposure'] = $exif_ifd0['ExposureTime'];
}

// Aperture
if (@array_key_exists('ApertureFNumber', $exif_ifd0['COMPUTED']))
{
$return['aperture'] = $exif_ifd0['COMPUTED']['ApertureFNumber'];
}

// ISO
if (@array_key_exists('ISOSpeedRatings',$exif_exif))
{
$return['iso'] = $exif_exif['ISOSpeedRatings'];
}
}
}

# Return either an empty array, or the details which we were able to extrapolate.
return $return;
}

?>
-1
wdierkes at 5dollarwhitebox dot org
17 年前
除非 exif 和 mbstring 都是靜態編譯的,否則使用 exif 方法讀取 WINXP 資料會返回意外的結果。請參考以下錯誤報告

錯誤 #31980
錯誤 #23105


具體來說,是 #23105 的最後一條評論

"[2003 年 4 月 8 日下午 4:26 UTC] edink@php.net

由於 mbstring 已從 PHP 核心移除(它已被「取消綁定」),並且核心檔案和其他擴展在 mbstring 編譯為共享函式庫 (dll) 時無法使用 mbstring 功能,因此無法修復此問題。
"

如果 exif 是靜態編譯的 (--enable-exif) 而 mbstring 編譯為 DSO 模組 (--enable-mbstring=shared),則 exif_read_data 可能只返回單個字元而不是整個字串。

將 exif 和 mbstring 都靜態編譯 (--enable-exif --enable-mbstring) 可以解決此問題。
-3
lincolnzsilva at gmail dot com
16 年前
取得一些 EXIF 欄位(簡單的方法)

<?php
$exif_make
= exif_read_data ( $_FILES['photo']['tmp_name'] ,'IFD0' ,0 );
$emake = $exif_make['Make'];

$exif_model = exif_read_data ( $_FILES['photo']['tmp_name'] ,'IFD0' ,0 );
$emodel = $exif_model['Model'];

$exif_exposuretime = exif_read_data ( $_FILES['photo']['tmp_name'] ,'EXIF' ,0 );
$eexposuretime = $exif_exposuretime['ExposureTime'];

$exif_fnumber = exif_read_data ( $_FILES['photo']['tmp_name'] ,'EXIF' ,0 );
$efnumber = $exif_fnumber['FNumber'];

$exif_iso = exif_read_data ( $_FILES['photo']['tmp_name'] ,'EXIF' ,0 );
$eiso = $exif_iso['ISOSpeedRatings'];

$exif_date = exif_read_data ( $_FILES['photo']['tmp_name'] ,'IFD0' ,0 );
$edate = $exif_date['DateTime'];
?>
-5
kurt at mandella dot biz
11 年前
在 Picasa 中處理過的照片通常在 "MAKERNOTE" 區段和 EXIF.MakerNote 下包含垃圾數據 (UTF8),例如:

[MakerNote] => r0~Þæ"î2OÔy  e §…b! ) ) EI "ÐÓ
#s &0{ 'Û (å -Ð`ÿÿ@ÿÿÿìE è€Ýÿÿ  ÿÿÿÿÿÿx "ú»Dóÿ H ?.}BúIMG:DIGITAL IXUS 100 IS JPEGFirmware Version 1.00s›xÇØÿÿÿ–l¥ÿÿÿ  ØÌÌxŒ ÿÿÌÌŸãÿÿÿ¼Ž(½ (½T‹U’‹d–~Ø“¥ÿÿÿ ÀÿœªãjáÀpgaXfaWb[Te«
8ú5:Áð-3åÿÿ5»ÿ ‹;ßÊ Š €à€` ¸ ddîÿîÿîÿîÿîÿîÿ
ÿÿŠ1—ÏàôÉæ׬gªiï

這無法寫入 MySQL 的 Blob 欄位。以下程式碼會移除垃圾標籤。

$exif = exif_read_data($process_photo, 0, 'EXIF');

if($exif['IFD0']['Software'] == "Picasa"){

foreach ($exif as $key => $section){

如果 ($key != "MAKERNOTE") {
foreach ($section as $name => $val) {
如果 ($name != 'MakerNote') {
$exifA[$key][$name] = $val;
}
}
$exifB[$key] = $exifA[$key];
}
}
$serialized_exif = serialize($exifB);
} else {
$serialized_exif = serialize($exif);
}
To Top