function Encode_PIM($tag, $Byte_Align) { // Create a string to receive the packed data $packed_data = ""; // Check that this tag is for Print Image Matching Info if ($tag['Type'] == "PIM") { // Check that the tag has been decoded - otherwise we don't need to do anything if (is_array($tag['Data']) && count($tag['Data']) > 0) { // Add the header to the packed data $packed_data .= "PrintIM"; // Add the version to the packed data $packed_data .= $tag['Data']['Version'] . ""; // Create a string to receive the tag data $tag_data_str = ""; // Cycle through each tag $tag_count = 0; foreach ($tag['Data'] as $key => $curr_tag) { // Make sure this is a tag and not supplementary info if (is_numeric($key)) { // Count how many tags are created $tag_count++; // Add the tag number to the packed tag data $tag_data_str .= put_IFD_Data_Type($curr_tag['Tag Number'], 3, $Byte_Align); // Add the tag data to the packed tag data $tag_data_str .= $curr_tag['Data']; } } // Add the tag count to the packed data $packed_data .= put_IFD_Data_Type($tag_count, 3, $Byte_Align); // Add the packed tag data to the packed data $packed_data .= $tag_data_str; } } // Return the resulting packed data return $packed_data; }
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); } 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']); } 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']); } 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']); } 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']; } 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); } 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, ""); // 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); } // 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; }