private function _graphicsMagickGetMetadata($ps_filepath) { $va_metadata = array(); /* EXIF metadata */ if (function_exists('exif_read_data') && !$this->opo_config->get('dont_use_exif_read_data')) { if (is_array($va_exif = caSanitizeArray(@exif_read_data($ps_filepath, 'EXIF', true, false)))) { $va_metadata['EXIF'] = $va_exif; } } // if the builtin EXIF extraction is not used or failed for some reason, try ExifTool if (!isset($va_metadata['EXIF']) || !is_array($va_metadata['EXIF'])) { if (caExifToolInstalled()) { $va_metadata['EXIF'] = caExtractMetadataWithExifTool($ps_filepath, true); } } // else try GraphicsMagick if (!isset($va_metadata['EXIF']) || !is_array($va_metadata['EXIF'])) { exec($this->ops_graphicsmagick_path . ' identify -format "%[EXIF:*]" ' . caEscapeShellArg($ps_filepath) . (caIsPOSIX() ? " 2> /dev/null" : ""), $va_output, $vn_return); if (is_array($va_output) && sizeof($va_output) > 1) { foreach ($va_output as $vs_output_line) { $va_tmp = explode('=', $vs_output_line); // format is "Make=NIKON CORPORATION" if (isset($va_tmp[0]) && isset($va_tmp[1])) { $va_metadata['EXIF'][$va_tmp[0]] = $va_tmp[1]; } } } $va_output = array(); } $o_xmp = new XMPParser(); if ($o_xmp->parse($ps_filepath)) { if (is_array($va_xmp_metadata = $o_xmp->getMetadata()) && sizeof($va_xmp_metadata)) { $va_metadata['XMP'] = array(); foreach ($va_xmp_metadata as $vs_xmp_tag => $va_xmp_values) { $va_metadata['XMP'][$vs_xmp_tag] = join('; ', $va_xmp_values); } } } /* IPTC metadata */ $vs_iptc_file = tempnam(caGetTempDirPath(), 'gmiptc'); @rename($vs_iptc_file, $vs_iptc_file . '.iptc'); // GM uses the file extension to figure out what we want $vs_iptc_file .= '.iptc'; exec($this->ops_graphicsmagick_path . " convert " . caEscapeShellArg($ps_filepath) . " " . caEscapeShellArg($vs_iptc_file) . (caIsPOSIX() ? " 2> /dev/null" : ""), $va_output, $vn_return); $vs_iptc_data = file_get_contents($vs_iptc_file); @unlink($vs_iptc_file); $va_iptc_raw = iptcparse($vs_iptc_data); $va_iptc_tags = array('2#004' => 'Genre', '2#005' => 'DocumentTitle', '2#010' => 'Urgency', '2#015' => 'Category', '2#020' => 'Subcategories', '2#025' => 'Keywords', '2#040' => 'SpecialInstructions', '2#055' => 'CreationDate', '2#060' => 'TimeCreated', '2#080' => 'AuthorByline', '2#085' => 'AuthorTitle', '2#090' => 'City', '2#095' => 'State', '2#100' => 'CountryCode', '2#101' => 'Country', '2#103' => 'OTR', '2#105' => 'Headline', '2#110' => 'Credit', '2#115' => 'PhotoSource', '2#116' => 'Copyright', '2#120' => 'Caption', '2#122' => 'CaptionWriter'); $va_iptc = array(); if (is_array($va_iptc_raw)) { foreach ($va_iptc_raw as $vs_iptc_tag => $va_iptc_tag_data) { if (isset($va_iptc_tags[$vs_iptc_tag])) { $va_iptc[$va_iptc_tags[$vs_iptc_tag]] = join('; ', $va_iptc_tag_data); } } } if (sizeof($va_iptc)) { $va_metadata['IPTC'] = $va_iptc; } /* DPX metadata */ exec($this->ops_graphicsmagick_path . " identify -format '%[DPX:*]' " . caEscapeShellArg($ps_filepath) . (caIsPOSIX() ? " 2> /dev/null" : ""), $va_output, $vn_return); if ($va_output[0]) { $va_metadata['DPX'] = $va_output; } return $va_metadata; }
private function _gmagickRead($ps_filepath) { try { $handle = new Gmagick($ps_filepath); $this->setResourceLimits($handle); $handle->setimageindex(0); // force use of first image in multi-page TIFF $this->handle = $handle; $this->filepath = $ps_filepath; $this->metadata = array(); // handle metadata /* EXIF */ if (function_exists('exif_read_data') && !$this->opo_config->get('dont_use_exif_read_data')) { if (is_array($va_exif = caSanitizeArray(@exif_read_data($ps_filepath, 'EXIF', true, false)))) { $va_metadata['EXIF'] = $va_exif; } } // if the builtin EXIF extraction is not used or failed for some reason, try ExifTool if (!isset($va_metadata['EXIF']) || !is_array($va_metadata['EXIF'])) { if (caExifToolInstalled()) { $va_metadata['EXIF'] = caExtractMetadataWithExifTool($ps_filepath, true); } } // Rotate incoming image as needed if (isset($va_metadata['EXIF']['IFD0']['Orientation'])) { $vn_orientation = $va_metadata['EXIF']['IFD0']['Orientation']; $vs_tmp_basename = tempnam(caGetTempDirPath(), 'ca_image_tmp'); $vb_is_rotated = false; switch ($vn_orientation) { case 3: $this->handle->rotateimage("#FFFFFF", 180); unset($va_metadata['EXIF']['IFD0']['Orientation']); $vb_is_rotated = true; break; case 6: $this->handle->rotateimage("#FFFFFF", 90); unset($va_metadata['EXIF']['IFD0']['Orientation']); $vb_is_rotated = true; break; case 8: $this->handle->rotateimage("#FFFFFF", -90); unset($va_metadata['EXIF']['IFD0']['Orientation']); $vb_is_rotated = true; break; } if ($vb_is_rotated) { if ($this->handle->writeimage($vs_tmp_basename)) { $va_tmp = $this->handle->getimagegeometry(); $this->properties["faces"] = $this->opa_faces = caDetectFaces($vs_tmp_basename, $va_tmp['width'], $va_tmp['height']); } @unlink($vs_tmp_basename); } } // get XMP $o_xmp = new XMPParser(); if ($o_xmp->parse($ps_filepath)) { if (is_array($va_xmp_metadata = $o_xmp->getMetadata()) && sizeof($va_xmp_metadata)) { $va_metadata['XMP'] = array(); foreach ($va_xmp_metadata as $vs_xmp_tag => $va_xmp_values) { $va_metadata['XMP'][$vs_xmp_tag] = join('; ', $va_xmp_values); } } } // try to get IPTC and DPX with GraphicsMagick, if available if (caMediaPluginGraphicsMagickInstalled()) { /* IPTC metadata */ $vs_iptc_file = tempnam(caGetTempDirPath(), 'gmiptc'); @rename($vs_iptc_file, $vs_iptc_file . '.iptc'); // GM uses the file extension to figure out what we want $vs_iptc_file .= '.iptc'; exec($this->ops_graphicsmagick_path . " convert " . caEscapeShellArg($ps_filepath) . " " . caEscapeShellArg($vs_iptc_file) . (caIsPOSIX() ? " 2> /dev/null" : ""), $va_output, $vn_return); $vs_iptc_data = file_get_contents($vs_iptc_file); @unlink($vs_iptc_file); $va_iptc_raw = iptcparse($vs_iptc_data); $va_iptc_tags = array('2#004' => 'Genre', '2#005' => 'DocumentTitle', '2#010' => 'Urgency', '2#015' => 'Category', '2#020' => 'Subcategories', '2#025' => 'Keywords', '2#040' => 'SpecialInstructions', '2#055' => 'CreationDate', '2#060' => 'TimeCreated', '2#080' => 'AuthorByline', '2#085' => 'AuthorTitle', '2#090' => 'City', '2#095' => 'State', '2#100' => 'CountryCode', '2#101' => 'Country', '2#103' => 'OTR', '2#105' => 'Headline', '2#110' => 'Credit', '2#115' => 'PhotoSource', '2#116' => 'Copyright', '2#120' => 'Caption', '2#122' => 'CaptionWriter'); $va_iptc = array(); if (is_array($va_iptc_raw)) { foreach ($va_iptc_raw as $vs_iptc_tag => $va_iptc_tag_data) { if (isset($va_iptc_tags[$vs_iptc_tag])) { $va_iptc[$va_iptc_tags[$vs_iptc_tag]] = join('; ', $va_iptc_tag_data); } } } if (sizeof($va_iptc)) { $va_metadata['IPTC'] = $va_iptc; } /* DPX metadata */ exec($this->ops_graphicsmagick_path . " identify -format '%[DPX:*]' " . caEscapeShellArg($ps_filepath) . (caIsPOSIX() ? " 2> /dev/null" : ""), $va_output, $vn_return); if ($va_output[0]) { $va_metadata['DPX'] = $va_output; } } $this->metadata = $va_metadata; return $handle; } catch (Exception $e) { $this->postError(1610, _t("Could not read image file"), "WLPlugGmagick->read()"); return false; // gmagick couldn't read file, presumably } }
/** * Extracts media metadata using ExifTool * * @param string $ps_filepath file path * @param bool $pb_skip_unknown If set to true, exiftool won't try to extract unknown tags from the source file * Use this if metadata extraction fails for unknown reasons. Sometimes tools like Photoshop write weird * binary data into the files that causes json_decode to barf. * * @return array|null Extracted metadata, null if exiftool is not installed or something went wrong */ function caExtractMetadataWithExifTool($ps_filepath, $pb_skip_unknown = false) { if (caExifToolInstalled()) { $vs_unknown_param = $pb_skip_unknown ? '' : '-u'; $vs_path_to_exif_tool = caGetExternalApplicationPath('exiftool'); exec("{$vs_path_to_exif_tool} -json -a {$vs_unknown_param} -g1 " . caEscapeShellArg($ps_filepath) . " 2> /dev/null", $va_output, $vn_return); if ($vn_return == 0) { $va_data = json_decode(join("\n", $va_output), true); if (!is_array($va_data)) { return null; } $va_data = array_shift($va_data); if (sizeof($va_data) > 0) { return $va_data; } } } return null; }
/** * Embed media metadata into given file. Embedding is performed on a copy of the file and placed into the * system tmp directory. The given file is never modified. * * @param string $ps_file The file to embed metadata into * @param string $ps_table Table name of the subject record. This is used to figure out the appropriate mapping to use from media_metadata.conf * @param int $pn_pk Primary key of the subject record. This is used to run the export for the right record. * @param string $ps_type_code Optional type code for the subject record * @param int $pn_rep_pk Primary key of the subject representation. * If there are export mapping for object representations, we run them after the mapping for the subject table. * Fields that get exported here should overwrite fields from the subject table export. * @param string $ps_rep_type_code type code for object representation * @return string File name of a temporary file with the embedded metadata, false on failure */ function caEmbedMediaMetadataIntoFile($ps_file, $ps_table, $pn_pk, $ps_type_code, $pn_rep_pk, $ps_rep_type_code) { require_once __CA_MODELS_DIR__ . '/ca_data_exporters.php'; if (!caExifToolInstalled()) { return false; } // we need exiftool for embedding $vs_path_to_exif_tool = caGetExternalApplicationPath('exiftool'); if (!file_exists($ps_file)) { return false; } if (!preg_match("/^image\\//", mime_content_type($ps_file))) { return false; } // Don't try to embed in files other than images // make a temporary copy (we won't touch the original) copy($ps_file, $vs_tmp_filepath = caGetTempDirPath() . "/" . time() . md5($ps_file)); // // SUBJECT TABLE // if ($vs_subject_table_export = caExportMediaMetadataForRecord($ps_table, $ps_type_code, $pn_pk)) { $vs_export_filename = caGetTempFileName('mediaMetadataSubjExport', 'xml'); if (@file_put_contents($vs_export_filename, $vs_subject_table_export) === false) { return false; } exec("{$vs_path_to_exif_tool} -tagsfromfile {$vs_export_filename} -all:all " . caEscapeShellArg($vs_tmp_filepath), $va_output, $vn_return); @unlink($vs_export_filename); @unlink("{$vs_tmp_filepath}_original"); } // // REPRESENTATION // if ($vs_representation_Export = caExportMediaMetadataForRecord('ca_object_representations', $ps_rep_type_code, $pn_rep_pk)) { $vs_export_filename = caGetTempFileName('mediaMetadataRepExport', 'xml'); if (@file_put_contents($vs_export_filename, $vs_representation_Export) === false) { return false; } exec("{$vs_path_to_exif_tool} -tagsfromfile {$vs_export_filename} -all:all " . caEscapeShellArg($vs_tmp_filepath), $va_output, $vn_return); @unlink($vs_export_filename); @unlink("{$vs_tmp_filepath}_original"); } return $vs_tmp_filepath; }
public function getMappingErrors($t_mapping) { if (!caExifToolInstalled()) { $va_errors[] = _t('ExifTool must be installed and available!'); } $va_errors = array(); $va_top = $t_mapping->getTopLevelItems(); $va_namespace_keys = array(); foreach (array_keys($this->opa_namespaces) as $vs_key) { $va_namespace_keys[] = str_replace('xmlns:', '', $vs_key); } foreach ($va_top as $va_item) { $vs_element_ns = preg_replace("/\\:.+\$/", '', $va_item['element']); if (!in_array($vs_element_ns, $va_namespace_keys)) { $va_errors[] = _t('%1 is not a valid element for ExifTool exports. It must be in of one of the ExifTool namespaces.', $va_item['element']); } $t_item = new ca_data_exporter_items($va_item['item_id']); $va_children = $t_item->getHierarchyChildren(); if (is_array($va_children) && sizeof($va_children) > 0) { $va_errors[] = _t("ExifTool mappings can't be hierarchical. It looks like element %1 has children.", $va_item['element']); } } return $va_errors; }
/** * Extracts media metadata using ExifTool * * @param string $ps_filepath file path * @param string $ps_exiftool_path optional path to ExifTool binary. If omitted the path configured in external_applications.conf is used. * * @return array Extracted metadata */ function caExtractMetadataWithExifTool($ps_filepath, $ps_mediainfo_path = null) { if (caExifToolInstalled()) { if (!$vs_path_to_exif_tool) { $vs_path_to_exif_tool = caGetExternalApplicationPath('exiftool'); } exec("{$vs_path_to_exif_tool} -json -a -u -g1 " . caEscapeShellArg($ps_filepath) . " 2> /dev/null", $va_output, $vn_return); if (!is_array($va_data = array_pop(json_decode(join(" ", $va_output), true)))) { return false; } return $va_data; } return null; }
private function _CoreImageGetMetadata($ps_filepath) { if (caMediaPluginCoreImageInstalled($this->ops_CoreImage_path)) { $va_metadata = array(); if (function_exists('exif_read_data') && !$this->opo_config->get('dont_use_exif_read_data')) { if (is_array($va_exif = caSanitizeArray(@exif_read_data($ps_filepath, 'EXIF', true, false)))) { $va_metadata['EXIF'] = $va_exif; } } // if the builtin EXIF extraction is not used or failed for some reason, try ExifTool if (!isset($va_metadata['EXIF']) || !is_array($va_metadata['EXIF'])) { if (caExifToolInstalled()) { $va_metadata['EXIF'] = caExtractMetadataWithExifTool($ps_filepath, true); } } $o_xmp = new XMPParser(); if ($o_xmp->parse($ps_filepath)) { if (is_array($va_xmp_metadata = $o_xmp->getMetadata()) && sizeof($va_xmp_metadata)) { $va_metadata['XMP'] = $va_xmp_metadata; } } return $va_metadata; } return null; }