WordPressにメディアをアップするときに、ついでにAI画像のメタデータを読み込んで保存しておければ便利だなと思って作りました。
保存されたデータはwebui_prompt、webui_Negativeprompt、webui_metaというカスタムフィールドに登録されます。
webui_metaは配列となっていてwebui_meta[“step”]などで更に細かい情報を読み込めます。
こんな感じで表示されます。

//メタデータ追加処理
add_action('add_attachment', 'add_custom_metadata');
function add_custom_metadata($attachment_id)
{
// metadataの加工処理
$metadata = get_webui_metadata($attachment_id);
if(empty($metadata))return $post;
update_post_meta($attachment_id, "webui_prompt", $metadata["prompt"]);
update_post_meta($attachment_id, "webui_Negativeprompt", $metadata["Negativeprompt"]);
update_post_meta($attachment_id, "webui_meta", $metadata["meta"]);
foreach ($metadata["meta"] as $key => $value) {
update_post_meta($attachment_id, "webui_" . $key, $value);
}
// metadataを保存
return $post;
}
//メタデータ読み込み
function get_webui_metadata($attachment_id)
{
$metadata = array();
if(!$attachment_id)return $metadata;
$webui_prompt = get_post_meta($attachment_id,"webui_prompt",true);
if($webui_prompt){
$metadata = get_Existing_metadata($attachment_id);
}else{
$extension = pathinfo(get_attached_file($attachment_id), PATHINFO_EXTENSION);
//pngとjpgで処理変更
if ($extension == 'jpg' || $extension == 'jpeg') {
$metadata = get_jpg_metadata($attachment_id);
}
if ($extension == 'png') {
$metadata = get_png_metadata($attachment_id);
}
}
return $metadata;
}
// すでにメタデータがある場合
function get_Existing_metadata($attachment_id){
$metadata = array(
"prompt" => get_post_meta($attachment_id,"webui_prompt",true),
"Negativeprompt" => get_post_meta($attachment_id,"webui_Negativeprompt",true),
"meta" => get_post_meta($attachment_id,"webui_meta",true),
);
return $metadata;
}
//pngの処理
function get_png_metadata($attachment_id)
{
//PNGシグネチャ
define('PNG_SIGNATURE', "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a");
$chunksize = 65536;
$metadata = array();
$path = get_attached_file($attachment_id);
if(empty($path))return $metadata;
$fp = fopen($path, 'rb');
$total_read = 0;
if (PNG_SIGNATURE === fread($fp, 8)) {
$total_read = 8;
error_log("read01:\n",3,get_stylesheet_directory( ) . "/total.log");
while ($chunkHeader = fread($fp, 8)) {
//先頭8バイトから、チャンクデータの長さと種別を取得する
$chunk = unpack('Nsize/a4type', $chunkHeader);
//チャンクデータの種別
$type = $chunk['type'];
//チャンクデータの長さ
$size = $chunk['size'];
//チャンクデータ本体
//Note: サイズ0の場合、fread関数がエラーを出すため空文字とする
$data = (0 < $size) ? fread($fp, $size) : '';
$crc = fread($fp, 4);
//現在のチャンクデータを新しいファイルのデータに追加する
if ($type === "tEXt") {
error_log("read2:\n",3,get_stylesheet_directory( ) . "/total.log");
$separator = strpos($data, chr(0));
$keyword = substr($data, 0, $separator++);
$data = substr($data, $separator);
if ($keyword == "parameters") {
error_log("read3:\n",3,get_stylesheet_directory( ) . "/total.log");
$pos = strpos($data, "\nSteps:");
if ($pos !== false) {
error_log("read4:\n",3,get_stylesheet_directory( ) . "/total.log");
$Negative_pos = strpos($data, "\nNegative prompt: ");
if ($Negative_pos !== false) {
$metadata["prompt"] = substr($data, 0, $Negative_pos);
error_log(print_r($metadata,true),3,get_stylesheet_directory( ) . "/total.log");
$metadata["Negativeprompt"] = substr($data, $Negative_pos + strlen("\nNegative prompt: "), $pos - $Negative_pos - strlen("\nNegative prompt: "));
error_log(print_r($metadata,true),3,get_stylesheet_directory( ) . "/total.log");
} else {
error_log("read4-2:\n",3,get_stylesheet_directory( ) . "/total.log");
$metadata["prompt"] = substr($data, 0, $pos);
$metadata["Negativeprompt"] = "";
}
error_log(print_r($metadata,true),3,get_stylesheet_directory( ) . "/total.log");
}
$metas = substr($data, $pos);
$meta_splits = explode(",", $metas ?? array());
foreach ($meta_splits as $meta_split) {
$keyvalue = explode(":", $meta_split ?? array());
$metadata['meta'][trim($keyvalue[0])] = $keyvalue[1];
}
}
}
$total_read = $total_read + 12 + $size;
if ($total_read > $chunksize) break;
}
}
fclose($fp);
return $metadata;
}
//jpgの処理
function get_jpg_metadata($attachment_id){
$metadata = array();
$path = get_attached_file($attachment_id);
$exif = exif_read_data($path, 0, true);
$data = $exif["COMPUTED"]["UserComment"]??"";
$pos = strpos($data, "\nSteps:");
if ($pos !== false) {
$Negative_pos = strpos($data, "\nNegative prompt: ");
if ($Negative_pos !== false) {
$metadata["prompt"] = substr($data, 0, $Negative_pos);
$metadata["Negativeprompt"] = substr($data, $Negative_pos + strlen("\nNegative prompt: "), $pos - $Negative_pos - strlen("\nNegative prompt: "));
} else {
$metadata["prompt"] = substr($data, 0, $pos);
$metadata["Negativeprompt"] = "";
}
}
$metas = substr($data, $pos);
$meta_splits = explode(",", $metas ?? array());
foreach ($meta_splits as $meta_split) {
$keyvalue = explode(":", $meta_split ?? array());
$metadata['meta'][trim($keyvalue[0])] = $keyvalue[1];
}
return $metadata;
}
//メディア詳細に表示
add_filter('attachment_fields_to_edit', 'add_custom_fields', 10, 2);
function add_custom_fields($form_fields, $post)
{
$post_id = $post->ID;
// 入力欄の追加
$metadata = get_webui_metadata($post_id);
if (get_post_meta($post_id, "webui_prompt", true)) {
$prompt = get_post_meta($post_id, "webui_prompt", true);
} else {
$prompt = $metadata["prompt"];
}
$form_fields['webui_prompt'] = array(
'label' => "Prompt",
'input' => 'html',
'html' => '<textarea name="attachments[webui][webui_prompt]" class="widefat" />' . esc_attr($prompt) . '</textarea>'
);
if (get_post_meta($post_id, "webui_Negativeprompt", true)) {
$prompt = get_post_meta($post_id, "webui_Negativeprompt", true);
} else {
$prompt = $metadata["Negativeprompt"];
}
$form_fields['webui_Negativeprompt'] = array(
'label' => "Negative Prompt",
'input' => 'html',
'html' => '<textarea name="attachments[webui][webui_Negativeprompt]" class="widefat" />' . esc_attr($prompt) . '</textarea>'
);
foreach ($metadata['meta'] as $key => $value) {
$metakey = "webui_" . $key;
if (get_post_meta($post_id, $metakey, true)) {
$prompt = get_post_meta($post_id, $metakey, true);
} else {
$prompt = $value;
}
$form_fields[$metakey] = array(
'label' => $key,
'input' => 'html',
'html' => '<input name="attachments[webui][' . $metakey . ']" class="widefat" value="' . esc_attr($prompt) . '"/>'
);
}
return $form_fields;
}
//メディアファイル保存時カスタムフィールド更新
add_filter('attachment_fields_to_save', 'save_custom_fields', 10, 2);
function save_custom_fields($post, $attachment)
{
$post_id = $post["post_ID"];
$metadata = $post["attachments"]["webui"];
foreach ($metadata as $key => $value) {
update_post_meta($post_id, $key, $value);
}
// metadataを保存
return $post;
}