Drupal 8 - Get the image width / height / alt / etc.. in a twig or preprocess file - drupal-8

I'm trying to get the width and height of an image in a preprocess file.
I managed to generate the image with a style defined in the media/styles in the admin but I'm not able to render the width and/or height of the generated image (some will say I should just hardcode it in the twig file but I'm actually interested in learning how to get elements I'll need later :))
Here is what I'm using to get the image of a certain content type:
Let's assume my field's machine name is "field_image" and my content type is "article";
if (!empty($node->field_image->entity->getFileUri())) {
$style = ImageStyle::load('medium');
$image = $node->field_image->entity;
$variables['image'] = [
'src' => $style->buildUrl($image->getFileUri())
];
}
After that, all I need to do in node--article.html.twig is:
<img src="{{ image.src }}" />
But I also want to get the width and height attributes. How can I do that?

if ($node = \Drupal::routeMatch()->getParameter('node')) {
if ($node->hasField('field_image')) {
$imageField = $node->field_image;
$properties = $imageField->getProperties();
}
}
$properties will hold an array of the attributes your asking for.
$imageField is an instance of the Drupal\image\Plugin\Field\FieldType\ImageItem class. You can read the documentation here https://api.drupal.org/api/drupal/core%21modules%21image%21src%21Plugin%21Field%21FieldType%21ImageItem.php/class/ImageItem/8.2.x

This is the simplest solution I have found
if ($node = \Drupal::routeMatch()->getParameter('node')) {
if ($node->hasField('field_image')) {
//get first image on multi value field
$image = $node->field_image[0]->getValue();
$width = $image['width'];
$height = $image['height'];
}
}

Related

Calculate videoHeight relative to videoWidth (aspect-ratio) plus 30px - JavaScript

I have a specific video-player which is embedded with an iframe. It has a toolbar at the bottom with a fixed height of 30px.
The video-width is scaled within a bootstrap framework and I want to calculate the height based on the current width.
Like: videoHeight = (videoWidth * 0.5625) + 30px
The value 0.5625 is based on 16*9 aspect-ratio.
Now have I tried the following code:
$(document).ready(function() {
var wide = $('#video-container').css('width');
var calculate = parseInt(wide, 10) * 0.5625;
var videoheight = calculate + 30;
$('#video-container').css('height', videoheight);
});
It works partially, it does calculate the aspect-ratio correctly but it does not add the 30px. Can anybody tell me where I'm going wrong?

How to calculate Height of any control which is loaded in DataTemplate?

I want to get the height of the control which is loaded in DataTemplate when the width is set to 100. I have used the below code, but always returns the size 0,20. Any suggestion on this?
<DataTemplate x:Name="dataTemplate">
<Grid>
<TextBlock Text="{Binding Path=Name}" TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
var record = new UserInfo() { Name = "ASKL ALASO DKADOLD ADKIKAM AMDKI ADKAI AKDKI" };
var contentControl = new ContentControl();
contentControl.Measure(new Size());
contentControl.Content = record;
contentControl.ContentTemplate = App.Current.Resources["dataTemplate"] as DataTemplate;
contentControl.Measure(new Size(100, Double.PositiveInfinity));
var size = contentControl.DesiredSize;
I have used the below code, but always returns the size 0,20. Any suggestion on this?
This is because you didn't render your ContentControl on the layout, you can render it for example like this:
var record = new UserInfo() { Name = "ASKL ALASO DKADOLD ADKIKAM AMDKI ADKAI AKDKI" };
var contentControl = new ContentControl();
stackPanel.Children.Add(contentControl); //Add this ContentControl to the childeren collection of a StackPanel to show it
//contentControl.Measure(new Size());
contentControl.Content = record;
contentControl.ContentTemplate = App.Current.Resources["dataTemplate"] as DataTemplate;
contentControl.Measure(new Size(100, Double.PositiveInfinity));
var size = contentControl.DesiredSize;
Then now, you can get the size of your ContentControl, by my side it is 94,100.
I'm not sure this size is the one you actually want, from your title, you want to calculate Height of any control which is loaded in DataTemplate, but this size is the size of ContentControl, I think what you need is the height of the Grid, or TextBlock inside of this ContentControl. To get this two control, you can code like this after the ContentControl is fully rendered:
var grid = contentControl.ContentTemplateRoot as Grid;
var textblock = grid.Children.FirstOrDefault() as TextBlock;
And be aware that the DesiredSize is not the rendered size of the control, you can refer to the Remarks part of UIElement.DesiredSize property.

Constrain RaphaelJS print to boundaries and position

I am looking for a more efficient way to constrain/set text in Raphael.
I have text that can be written in a box. That text should be centered (based on a number that could change if user wanted to shift text left/right) and the text cannot go beyond the boundaries of the paper.
This is what I do now and its not manageable performance wise
// Build a path
var path = this.paper.print(x, x, text, font, size, 'middle')
// Center line by getting bounding box and shifting to half of that
var bb = path.getBBox()
path.transform('...T' + [-bb.width / 2, 0])
// Compare paper size vs bb
// if it goes beyond I adjust X and Y accordingly and redo the above
So ideally I would like to predict the size of the text before it prints - I am not sure this is possible though as it is probably font dependent. I have looked for a command to contrain text but do not see one?
The other thought I had was to create some kind of shadow paper that does not print to screen and use that to determine size before I render to user. I am not sure where the lag is though - if it's in the screen rendering good but if its in the general logic of creating the svg then that wont help.
I'd appreciate suggestions
You can use opentype.js for measuring text, also you can get svg path by using Path.toPathData method. There is no need of cufon compiled js fonts.
For text measure, create a canvas element somewhere in your DOM.
<canvas id="canvas" style="display: none;"></canvas>
this function will load text and count width, height
function measureText(text, font_name, size) {
var dfd = $.Deferred();
opentype.load('/fonts/' + font_name + '.ttf', function (err, font) {
if (err) {
dfd.reject('Font is not loaded');
console.log('Could not load font: ' + err);
} else {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
var tmp_path = font.getPath(text, 100, 100, size);
tmp_path.draw(ctx); // Draw path on the canvas
var ascent = 0;
var descent = 0;
var width = 0;
var scale = 1 / font.unitsPerEm * size;
var glyphs = font.stringToGlyphs(text_string);
for (var i = 0; i < glyphs.length; i++) {
var glyph = glyphs[i];
if (glyph.advanceWidth) {
width += glyph.advanceWidth * scale;
}
if (i < glyphs.length - 1) {
var kerningValue = font.getKerningValue(glyph, glyphs[i + 1]);
width += kerningValue * scale;
}
ascent = Math.max(ascent, glyph.yMax);
descent = Math.min(descent, glyph.yMin);
}
return dfd.resolve({
width: width,
height: ascent * scale,
actualBoundingBoxDescent: descent * scale,
fontBoundingBoxAscent: font.ascender * scale,
fontBoundingBoxDescent: font.descender * scale
});
}
});
return dfd.promise();
},
then use this function to get text dimensions:
$.when(measureText("ABCD", "arial", 48)).done(function(res) {
var height = res.height,
width = res.width;
...
});

Exporting 3d Models and their color information using Assimp

we're working on a custom 3d engine (OpenGL) in which people can create, import and export custom 3d models, and we are using Assimp for our importing/exporting. At this point, importing works great, but when it comes to exporting, we are unable to save out any materials other than the default. While Assimp's website and others have loads of information on importing, there is little to no documentation on exporting. We managed to work out majority of the export process, but there doesn't seem to be any way of setting Assimp's aiMaterials' color values.
Assimp's documentation explains how to GET the color information from existing materials, ie..
*aiColor3D color (0.f,0.f,0.f);
mat->Get(AI_MATKEY_COLOR_DIFFUSE,color);*
http://assimp.sourceforge.net/lib_html/materials.html
but doesn't include anything on SETTING color information based on the model's material. (FYI, all of our models are flat colors; no textures). If anyone has any experience in exporting materials/colors, any help would be greatly appreciated. Here is what we have now..
//Create an Assimp node element to be a container object to hold all graphic information
scene.mRootNode = new aiNode();
scene.mMaterials = new aiMaterial*[ 1 ];
scene.mMaterials[ 0 ] = nullptr;
scene.mNumMaterials = 1;
mAllChildren.clear();
//Get ALL children on the scene (including down the hierarchy)
FindAllChildren(CScriptingUtils::GetDoc()->GetScene());
std::vector<std::weak_ptr<CNode>> children = mAllChildren;
int size = (int)children.size();
scene.mMaterials[ 0 ] = new aiMaterial();
scene.mRootNode->mMeshes = new unsigned int[ size ];
scene.mRootNode->mNumMeshes = size;
scene.mMeshes = new aiMesh*[ size ];
scene.mNumMeshes = size;
//Iterate through all children, retrieve their graphical information and push it into the Assimp structure
for(int i = 0; i < size; i++)
{
std::shared_ptr<CNode> childNode = children[i].lock();
scene.mRootNode->mMeshes[ i ] = i;
scene.mMeshes[ i ] = nullptr;
scene.mMeshes[ i ] = new aiMesh();
scene.mMeshes[ i ]->mMaterialIndex = 0;
aiMaterial* mat = scene.mMaterials[0];
And we need to do something like..
mat.color = childNode.color;
try that:
mat->AddProperty<aiColor3D>(color, 1, AI_MATKEY_COLOR_DIFFUSE);
It helps me. Also, I trying to export textures
newMat->AddProperty(matName, AI_MATKEY_NAME);
newMat->AddProperty(texturePath, AI_MATKEY_TEXTURE_DIFFUSE(0));
where 'matName' and 'texturePath' types are 'aiString'. What additiional parameters (besides path of texture) needed for correct displaying texture (because now textures not displayed, only color)?

XTK not displaying uncompressed DICOM in 2D render

I am trying to display some local DICOM / .dcm files with XTK in the 2D render model that are LUNG CT IMAGES from the RIDER dataset hosted on the cancer imaging archive and there are no errors thrown by the console but the images are being outputted as blank. The files and the relative links to the files in the js are correct but still no output.
I also did the "Developer Heads Up" build: https://github.com/xtk/X/wiki/X:DevelopersHeadsUp,
as well as trying to use the nightly build: https://github.com/xtk/get/blob/gh-pages/xtk_nightly.js.
var _dicom = ['000008', '000009', '000010', '000011', '000012', '000013', '000014' , '000015' , '000016'];
var r = new X.renderer2D();
r.orientation = 'Z';
r.init();
var v = new X.volume();
v.file = _dicom.sort().map(function(v) {
return 'img/' + v + '.dcm';
});
r.add(v);
r.onWindowLevel();
r.render();
$('canvas').attr('id', 'xtkCanvas');
r.onShowtime = function() {
};
volume = v;
};
I have also verified that the DICOM files are uncompressed by using OsiriX...