Collect metadata from glb file

Signed-off-by: Justin Georgi <justin.georgi@gmail.com>
This commit is contained in:
2024-11-10 19:52:08 -07:00
parent 0e91a69d29
commit 0c5c1c61d3
7 changed files with 125 additions and 4 deletions

View File

@@ -5,6 +5,8 @@ use ImageHandler;
use Html;
class GlModelHandler extends ImageHandler {
private const glmvVersion = '0.1';
/**
* Model cannot be displayed directly in a browser but can be rendered.
*
@@ -120,6 +122,7 @@ class GlModelHandler extends ImageHandler {
/**
* Get an associative array mapping magic word IDs to parameter names.
*
* @return string[]
*/
public function getParamMap() {
@@ -130,6 +133,97 @@ class GlModelHandler extends ImageHandler {
];
}
/**
* This is used to generate an array element for each metadata value. That array is then used to generate the table of metadata values on the image page.
*
* @param array &$array An array containing elements for each type of visibility and each of those elements being an array of metadata items. This function adds a value to that array.
* @param string $visibility ('visible' or 'collapsed') if this value is hidden by default.
* @param string $type Type of metadata tag (currently always 'exif')
* @param string $id The name of the metadata tag (like 'artist' for example). its name in the table displayed is the message "$type-$id" (Ex exif-artist ).
* @param string $value Thingy goes into a wikitext table; it used to be escaped but that was incompatible with previous practise of customized display with wikitext formatting via messages such as 'exif-model-value'. So the escaping is taken back out, but generally this seems a confusing interface.
* @param bool | string $param Value to pass to the message for the name of the field as $1. Currently this parameter doesn't seem to ever be used.
*/
//public static function addMeta (&$array, $visibility, $type, $id, $value, $param = false ) {
// $array[$visibility][] = [
// 'id' => "$type-$id",
// 'name' => $name,
// 'value' => $value
// ];
//}
/**
* Get image size information and metadata array.
*
* @param MediaHandlerState $state An object for
* saving process-local state. This is normally a
* File object which will be passed back to other
* MediaHandler methods like pageCount(), if they
* are called in the same request. The handler
* can use this object to save its state.
* @param string $path The filename
*
* @return array|null Null to fall back to
* getImageSize(), or an array with width, height,
* bits, and metadata keys. All keys are optional.
*/
public function getSizeAndMetadata ($state, $path) {
$gltf = fopen($path, 'r');
fseek($gltf,12);
$glMetaLength = unpack("Iint", fread($gltf, 4));
fseek($gltf,20);
$glMeta = json_decode(fread($gltf,$glMetaLength['int']),true);
fclose($gltf);
$newMeta = array(
'Type' => $glType
);
foreach($glMeta['asset'] as $key => $value) {
switch ($key) {
case 'author':
$newMeta['Author'] = $value;
break;
case 'copyright':
$newMeta['Copyright'] = $value;
break;
case 'generator':
$newMeta['glmv-generator'] = $value;
break;
case 'version':
$newMeta['glmv-version'] = $value;
break;
}
}
$newMeta['glmv-meshes'] = count($glMeta['meshes']);
$newMeta['glmv-textures'] = count($glMeta['textures']);
$newMeta['glmv-metadata'] = self::glmvVersion;
return array(
'width' => 600,
'height' => 800,
'metadata' => $newMeta
);
}
/**
* Check if the metadata is valid for this handler.
*
* If it returns MediaHandler::METADATA_BAD (or false), Image will reload the metadata from the file and update the database.
* MediaHandler::METADATA_GOOD for if the metadata is a-ok,
* MediaHandler::METADATA_COMPATIBLE if metadata is old but backwards compatible (which may or may not trigger a metadata reload).
*
* TODO: This version is for testing/dev only. Better checking will be requried in the future
* @param File $image
* @return bool|int
*/
public function isFileMetadataValid ($image) {
$meta = $image->getMetadataItems('glmv-metadata');
if (!isset($meta['glmv-metadata']) || $meta['glmv-metadata'] != self::glmvVersion) {
return self::METADATA_BAD;
}
return self::METADATA_GOOD;
}
/**
* Small helper function to display information on the browser console
*

View File

@@ -42,9 +42,17 @@ class GlModelHooks {
* @param OutputPage $out compiled page html and manipulation methods
*/
public static function onBeforePageDisplay($out) {
preg_match('/(<model-viewer src="\S*?\.(glb|gltf"))/',$out->getHTML(),$findGltf);
$file = MediaWikiServices::getInstance()->getRepoGroup()->findFile($out->getTitle());
if ($file) {
echo '<script>';
self::console_log('Metadata:');
self::console_log($file->getMetadata());
echo '</script>';
}
preg_match('/(<model-viewer src="\S*?\.(glb|gltf"))/',$out->getHTML(),$findGltf);
if ($findGltf[0]) {
$out->addHeadItems(
$out->addHeadItems(
Html::rawElement(
'script',
array(

View File

@@ -143,7 +143,7 @@ class GlModelTransformOutput extends MediaTransformOutput {
//Add important additional attributes and render model-viewer with hotspots
$attrModelView = array_merge(['src' => $srcUrl, 'class' => 'mv-model', 'interpolation-decay' => '100', 'interaction-prompt' => 'none'], $attrModelView);
$attrModelView['style'] = 'width: 100%; height: 100%;';
$attrModelView['onload'] = 'modelLoaded()';
$attrModelView['onload'] = 'modelLoaded(event)';
$hotspotHtml = (isset($hotspots)) ? implode($hotspots) : '';
$elModel = Html::rawElement('model-viewer', $attrModelView, $hotspotHtml);