📄 exif.php
字号:
// Check if the data is over 4 bytes long
if ( strlen( $data ) > 4 )
{
// Data is longer than 4 bytes - it needs to be offset
// Check if this entry is the Maker Note
if ( ( $Tag_Definitions_Name == "EXIF" ) && ( $tag[ 'Tag Number' ] == 37500 ) )
{
// This is the makernote - It will have already been stored
// at its original offset to help preserve it
// all we need to do is add the Offset to the IFD packed data
$data_offset = $tag[ 'Offset' ];
$ifd_body_str .= put_IFD_Data_Type( $data_offset, 4, $Byte_Align );
}
else
{
// This is NOT the makernote
// Calculate the data offset
$data_offset = $IFD_offset + $IFD_len + strlen($ifd_data_str);
// Add the offset to the IFD packed data
$ifd_body_str .= put_IFD_Data_Type( $data_offset, 4, $Byte_Align );
// Add the data to the offset packed data
$ifd_data_str .= $data;
}
}
else
{
// Data is less than or equal to 4 bytes - Add it to the packed IFD data as is
$ifd_body_str .= $data;
}
}
}
// Assemble the IFD body onto the packed data
$packed_data .= $ifd_body_str;
// Check if there is another IFD after this one
if( $Another_IFD === TRUE )
{
// There is another IFD after this
// Calculate the Next-IFD offset so that it goes immediately after this IFD
$next_ifd_offset = $IFD_offset + $IFD_len + strlen($ifd_data_str);
}
else
{
// There is NO IFD after this - indicate with offset=0
$next_ifd_offset = 0;
}
// Add the Next-IFD offset to the packed data
$packed_data .= put_IFD_Data_Type( $next_ifd_offset, 4, $Byte_Align );
// Add the offset data to the packed data
$packed_data .= $ifd_data_str;
// Return the resulting packed data
return $packed_data;
}
/******************************************************************************
* End of Function: get_IFD_Packed_Data
******************************************************************************/
/******************************************************************************
*
* Internal Function: process_TIFF_Header
*
* Description: Decodes the information stored in a TIFF header and it's
* Image File Directories (IFD's). This information is returned
* in an array
*
* Parameters: filehnd - The handle of a open image file, positioned at the
* start of the TIFF header
* Tag_Definitions_Name - The name of the Tag Definitions group
* within the global array IFD_Tag_Definitions
*
*
* Returns: OutputArray - Array of IFD records
* FALSE - If an error occured in decoding
*
******************************************************************************/
function process_TIFF_Header( $filehnd, $Tag_Definitions_Name )
{
// Save the file position where the TIFF header starts, as offsets are relative to this position
$Tiff_start_pos = ftell( $filehnd );
// Read the eight bytes of the TIFF header
$DataStr = network_safe_fread( $filehnd, 8 );
// Check that we did get all eight bytes
if ( strlen( $DataStr ) != 8 )
{
return FALSE; // Couldn't read the TIFF header properly
}
$pos = 0;
// First two bytes indicate the byte alignment - should be 'II' or 'MM'
// II = Intel (LSB first, MSB last - Little Endian)
// MM = Motorola (MSB first, LSB last - Big Endian)
$Byte_Align = substr( $DataStr, $pos, 2 );
// Check the Byte Align Characters for validity
if ( ( $Byte_Align != "II" ) && ( $Byte_Align != "MM" ) )
{
// Byte align field is invalid - we won't be able to decode file
return FALSE;
}
// Skip over the Byte Align field which was just read
$pos += 2;
// Next two bytes are TIFF ID - should be value 42 with the appropriate byte alignment
$TIFF_ID = substr( $DataStr, $pos, 2 );
if ( get_IFD_Data_Type( $TIFF_ID, 3, $Byte_Align ) != 42 )
{
// TIFF header ID not found
return FALSE;
}
// Skip over the TIFF ID field which was just read
$pos += 2;
// Next four bytes are the offset to the first IFD
$offset_str = substr( $DataStr, $pos, 4 );
$offset = get_IFD_Data_Type( $offset_str, 4, $Byte_Align );
// Done reading TIFF Header
// Move to first IFD
if ( fseek( $filehnd, $Tiff_start_pos + $offset ) !== 0 )
{
// Error seeking to position of first IFD
return FALSE;
}
// Flag that a makernote has not been found yet
$GLOBALS[ "Maker_Note_Tag" ] = FALSE;
// Read the IFD chain into an array
$Output_Array = read_Multiple_IFDs( $filehnd, $Tiff_start_pos, $Byte_Align, $Tag_Definitions_Name );
// Check if a makernote was found
if ( $GLOBALS[ "Maker_Note_Tag" ] != FALSE )
{
// Makernote was found - Process it
// The makernote needs to be processed after all other
// tags as it may require some of the other tags in order
// to be processed properly
$GLOBALS[ "Maker_Note_Tag" ] = Read_Makernote_Tag( $GLOBALS[ "Maker_Note_Tag" ], $Output_Array, $filehnd );
}
$Output_Array[ 'Makernote_Tag' ] = $GLOBALS[ "Maker_Note_Tag" ];
// Save the Name of the Tags used in the output array
$Output_Array[ 'Tags Name' ] = $Tag_Definitions_Name;
// Save the Byte alignment
$Output_Array['Byte_Align'] = $Byte_Align;
// Return the output array
return $Output_Array ;
}
/******************************************************************************
* End of Function: process_TIFF_Header
******************************************************************************/
/******************************************************************************
*
* Internal Function: read_Multiple_IFDs
*
* Description: Reads and interprets a chain of standard Image File Directories (IFD's),
* and returns the entries in an array. This chain is made up from IFD's
* which have a pointer to the next IFD. IFD's are read until the next
* pointer indicates there are no more
*
* Parameters: filehnd - a handle for the image file being read, positioned at the
* start of the IFD chain
* Tiff_offset - The offset of the TIFF header from the start of the file
* Byte_Align - either "MM" or "II" indicating Motorola or Intel Byte alignment
* Tag_Definitions_Name - The name of the Tag Definitions group within the global array IFD_Tag_Definitions
* local_offsets - True indicates that offset data should be interpreted as being relative to the start of the currrent entry
* False (normal) indicates offests are relative to start of Tiff header as per IFD standard
* read_next_ptr - True (normal) indicates that a pointer to the next IFD should be read at the end of the IFD
* False indicates that no pointer follows the IFD
*
*
* Returns: OutputArray - Array of IFD entries
*
******************************************************************************/
function read_Multiple_IFDs( $filehnd, $Tiff_offset, $Byte_Align, $Tag_Definitions_Name, $local_offsets = FALSE, $read_next_ptr = TRUE )
{
// Start at the offset of the first IFD
$Next_Offset = 0;
do
{
// Read an IFD
list($IFD_Array , $Next_Offset) = read_IFD_universal( $filehnd, $Tiff_offset, $Byte_Align, $Tag_Definitions_Name, $local_offsets, $read_next_ptr );
// Move to the position of the next IFD
if ( fseek( $filehnd, $Tiff_offset + $Next_Offset ) !== 0 )
{
// Error seeking to position of next IFD
echo "<p>Error: Corrupted EXIF</p>\n";
return FALSE;
}
$Output_Array[] = $IFD_Array;
} while ( $Next_Offset != 0 ); // Until the Next IFD Offset is zero
// return resulting array
return $Output_Array ;
}
/******************************************************************************
* End of Function: read_Multiple_IFDs
******************************************************************************/
/******************************************************************************
*
* Internal Function: read_IFD_universal
*
* Description: Reads and interprets a standard or Non-standard Image File
* Directory (IFD), and returns the entries in an array
*
* Parameters: filehnd - a handle for the image file being read, positioned at the start
* of the IFD
* Tiff_offset - The offset of the TIFF header from the start of the file
* Byte_Align - either "MM" or "II" indicating Motorola or Intel Byte alignment
* Tag_Definitions_Name - The name of the Tag Definitions group within the global array IFD_Tag_Definitions
* local_offsets - True indicates that offset data should be interpreted as being relative to the start of the currrent entry
* False (normal) indicates offests are relative to start of Tiff header as per IFD standard
* read_next_ptr - True (normal) indicates that a pointer to the next IFD should be read at the end of the IFD
* False indicates that no pointer follows the IFD
*
* Returns: OutputArray - Array of IFD entries
* Next_Offset - Offset to next IFD (zero = no next IFD)
*
******************************************************************************/
function read_IFD_universal( $filehnd, $Tiff_offset, $Byte_Align, $Tag_Definitions_Name, $local_offsets = FALSE, $read_next_ptr = TRUE )
{
if ( ( $filehnd == NULL ) || ( feof( $filehnd ) ) )
{
return array (FALSE , 0);
}
// Record the Name of the Tag Group used for this IFD in the output array
$OutputArray[ 'Tags Name' ] = $Tag_Definitions_Name;
// Record the offset of the TIFF header in the output array
$OutputArray[ 'Tiff Offset' ] = $Tiff_offset;
// First 2 bytes of IFD are number of entries in the IFD
$No_Entries_str = network_safe_fread( $filehnd, 2 );
$No_Entries = get_IFD_Data_Type( $No_Entries_str, 3, $Byte_Align );
// If the data is corrupt, the number of entries may be huge, which will cause errors
// This is often caused by a lack of a Next-IFD pointer
if ( $No_Entries> 10000 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -