📄 exif.php
字号:
/******************************************************************************
*
* INTERNAL FUNCTIONS
*
******************************************************************************/
/******************************************************************************
*
* Internal Function: get_TIFF_Packed_Data
*
* Description: Packs TIFF IFD data from EXIF or Meta into a form ready for
* either a JPEG EXIF/Meta segment or a TIFF file
* This function attempts to protect the contents of an EXIF makernote,
* by ensuring that it remains in the same position relative to the
* TIFF header
*
* Parameters: tiff_data - the EXIF array,as read from get_EXIF_JPEG or get_Meta_JPEG
*
* Returns: packed_data - A string containing packed segment
*
******************************************************************************/
function get_TIFF_Packed_Data( $tiff_data )
{
// Check that the segment is valid
if ( $tiff_data === FALSE )
{
return FALSE;
}
// Get the byte alignment
$Byte_Align = $tiff_data['Byte_Align'];
// Add the Byte Alignment to the Packed data
$packed_data = $Byte_Align;
// Add the TIFF ID to the Packed Data
$packed_data .= put_IFD_Data_Type( 42, 3, $Byte_Align );
// Create a string for the makernote
$makernote = "";
// Check if the makernote exists
if ( $tiff_data[ 'Makernote_Tag' ] !== FALSE )
{
// A makernote exists - We need to ensure that it stays in the same position as it was
// Put the Makernote before any of the IFD's by padding zeros to the correct offset
$makernote .= str_repeat("\x00",( $tiff_data[ 'Makernote_Tag' ][ 'Offset' ] - 8 ) );
$makernote .= $tiff_data[ 'Makernote_Tag' ]['Data'];
}
// Calculage where the zeroth ifd will be
$ifd_offset = strlen( $makernote ) + 8;
// Add the Zeroth IFD pointer to the packed data
$packed_data .= put_IFD_Data_Type( $ifd_offset, 4, $Byte_Align );
// Add the makernote to the packed data (if there was one)
$packed_data .= $makernote;
//Add the IFD's to the packed data
$packed_data .= get_IFD_Array_Packed_Data( $tiff_data, $ifd_offset, $Byte_Align );
// Return the result
return $packed_data;
}
/******************************************************************************
* End of Function: get_TIFF_Packed_Data
******************************************************************************/
/******************************************************************************
*
* Internal Function: get_IFD_Array_Packed_Data
*
* Description: Packs a chain of IFD's from EXIF or Meta segments into a form
* ready for either a JPEG EXIF/Meta segment or a TIFF file
*
* Parameters: ifd_data - the IFD chain array, as read from get_EXIF_JPEG or get_Meta_JPEG
* Zero_IFD_offset - The offset to the first IFD from the start of the TIFF header
* Byte_Align - the Byte alignment to use - "MM" or "II"
*
* Returns: packed_data - A string containing packed IFD's
*
******************************************************************************/
function get_IFD_Array_Packed_Data( $ifd_data, $Zero_IFD_offset, $Byte_Align )
{
// Create a string to receive the packed output
$packed_data = "";
// Count the IFDs
$ifd_count = 0;
foreach( $ifd_data as $key => $IFD )
{
// Make sure we only count the IFD's, not other information keys
if ( is_numeric( $key ) )
{
$ifd_count++;
}
}
// Cycle through each IFD,
for ( $ifdno = 0; $ifdno < $ifd_count; $ifdno++ )
{
// Check if this IFD is the last one
if ( $ifdno == $ifd_count - 1 )
{
// This IFD is the last one, get it's packed data
$packed_data .= get_IFD_Packed_Data( $ifd_data[ $ifdno ], $Zero_IFD_offset +strlen($packed_data), $Byte_Align, FALSE );
}
else
{
// This IFD is NOT the last one, get it's packed data
$packed_data .= get_IFD_Packed_Data( $ifd_data[ $ifdno ], $Zero_IFD_offset +strlen($packed_data), $Byte_Align, TRUE );
}
}
// Return the packed output
return $packed_data;
}
/******************************************************************************
* End of Function: get_IFD_Array_Packed_Data
******************************************************************************/
/******************************************************************************
*
* Internal Function: get_IFD_Packed_Data
*
* Description: Packs an IFD from EXIF or Meta segments into a form
* ready for either a JPEG EXIF/Meta segment or a TIFF file
*
* Parameters: ifd_data - the IFD chain array, as read from get_EXIF_JPEG or get_Meta_JPEG
* IFD_offset - The offset to the IFD from the start of the TIFF header
* Byte_Align - the Byte alignment to use - "MM" or "II"
* Another_IFD - boolean - false if this is the last IFD in the chain
* - true if it is not the last
*
* Returns: packed_data - A string containing packed IFD's
*
******************************************************************************/
function get_IFD_Packed_Data( $ifd_data, $IFD_offset, $Byte_Align, $Another_IFD )
{
$ifd_body_str = "";
$ifd_data_str = "";
$Tag_Definitions_Name = $ifd_data[ 'Tags Name' ];
// Count the Tags in this IFD
$tag_count = 0;
foreach( $ifd_data as $key => $tag )
{
// Make sure we only count the Tags, not other information keys
if ( is_numeric( $key ) )
{
$tag_count++;
}
}
// Add the Tag count to the packed data
$packed_data = put_IFD_Data_Type( $tag_count, 3, $Byte_Align );
// Calculate the total length of the IFD (without the offset data)
$IFD_len = 2 + $tag_count * 12 + 4;
// Cycle through each tag
foreach( $ifd_data as $key => $tag )
{
// Make sure this is a tag, not another information key
if ( is_numeric( $key ) )
{
// Add the tag number to the packed data
$ifd_body_str .= put_IFD_Data_Type( $tag[ 'Tag Number' ], 3, $Byte_Align );
// Add the Data type to the packed data
$ifd_body_str .= put_IFD_Data_Type( $tag['Data Type'], 3, $Byte_Align );
// Check if this is a Print Image Matching entry
if ( $tag['Type'] == "PIM" )
{
// This is a Print Image Matching entry,
// encode it
$data = Encode_PIM( $tag, $Byte_Align );
}
// Check if this is a IPTC/NAA Record within the EXIF IFD
else if ( ( ( $Tag_Definitions_Name == "EXIF" ) || ( $Tag_Definitions_Name == "TIFF" ) ) &&
( $tag[ 'Tag Number' ] == 33723 ) )
{
// This is a IPTC/NAA Record, encode it
$data = put_IPTC( $tag['Data'] );
}
// Change: Check for embedded XMP as of version 1.11
// Check if this is a XMP Record within the EXIF IFD
else if ( ( ( $Tag_Definitions_Name == "EXIF" ) || ( $Tag_Definitions_Name == "TIFF" ) ) &&
( $tag[ 'Tag Number' ] == 700 ) )
{
// This is a XMP Record, encode it
$data = write_XMP_array_to_text( $tag['Data'] );
}
// Change: Check for embedded IRB as of version 1.11
// Check if this is a Photoshop IRB Record within the EXIF IFD
else if ( ( ( $Tag_Definitions_Name == "EXIF" ) || ( $Tag_Definitions_Name == "TIFF" ) ) &&
( $tag[ 'Tag Number' ] == 34377 ) )
{
// This is a Photoshop IRB Record, encode it
$data = pack_Photoshop_IRB_Data( $tag['Data'] );
}
// Exif Thumbnail Offset
else if ( ( $tag[ 'Tag Number' ] == 513 ) && ( $Tag_Definitions_Name == "TIFF" ) )
{
// The Exif Thumbnail Offset is a pointer but of type Long, not Unknown
// Hence we need to put the data into the packed string separately
// Calculate the thumbnail offset
$data_offset = $IFD_offset + $IFD_len + strlen($ifd_data_str);
// Create the Offset for the IFD
$data = put_IFD_Data_Type( $data_offset, 4, $Byte_Align );
// Store the thumbnail
$ifd_data_str .= $tag['Data'];
}
// Exif Thumbnail Length
else if ( ( $tag[ 'Tag Number' ] == 514 ) && ( $Tag_Definitions_Name == "TIFF" ) )
{
// Encode the Thumbnail Length
$data = put_IFD_Data_Type( strlen($ifd_data[513]['Data']), 4, $Byte_Align );
}
// Sub-IFD
else if ( $tag['Type'] == "SubIFD" )
{
// This is a Sub-IFD
// Calculate the offset to the start of the Sub-IFD
$data_offset = $IFD_offset + $IFD_len + strlen($ifd_data_str);
// Get the packed data for the IFD chain as the data for this tag
$data = get_IFD_Array_Packed_Data( $tag['Data'], $data_offset, $Byte_Align );
}
else
{
// Not a special tag
// Create a string to receive the data
$data = "";
// Check if this is a type Unknown tag
if ( $tag['Data Type'] != 7 )
{
// NOT type Unknown
// Cycle through each data value and add it to the data string
foreach( $tag[ 'Data' ] as $data_val )
{
$data .= put_IFD_Data_Type( $data_val, $tag['Data Type'], $Byte_Align );
}
}
else
{
// This is a type Unknown - just add the data as is to the data string
$data .= $tag[ 'Data' ];
}
}
// Pad the data string out to at least 4 bytes
$data = str_pad ( $data, 4, "\x00" );
// Check if the data type is an ASCII String or type Unknown
if ( ( $tag['Data Type'] == 2 ) || ( $tag['Data Type'] == 7 ) )
{
// This is an ASCII String or type Unknown
// Add the Length of the string to the packed data as the Count
$ifd_body_str .= put_IFD_Data_Type( strlen($data), 4, $Byte_Align );
}
else
{
// Add the array count to the packed data as the Count
$ifd_body_str .= put_IFD_Data_Type( count($tag[ 'Data' ]), 4, $Byte_Align );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -