crop variant with aspect ratio 1:1 don't generate square image using fluid viewhelper - typo3

I have defined two crop variants “default” and “isotope”. The “default” contains some basic aspect rations like 1:1, 3:4, 16:9 and so on. The “isotope” variant only contains one aspect ratio 1:1, which is also defined as default (selectedRatio = 1:1). In my case, this definition is done by PageTS, which looks like this:
TCEFORM.sys_file_reference.crop.config.cropVariants {
default {
title = Default desktop
selectedRatio = NaN
allowedAspectRatios {
NaN {
title = Frei
value = 0.0
}
1:1 {
title = 1:1
value = 1.0
}
3:2 {
title = 3:2
value = 1.5
}
2:3 {
title = 2:3
value = 0.6666666667
}
4:3 {
title = 4:3
value = 1.3333333333
}
3:4 {
title = 3:4
value = 0.75
}
16:9 {
title = 16:9
value = 1.7777777778
}
}
}
isotope {
title = Auswahl für Isotope Plugin
selectedRatio = 1:1
allowedAspectRatios {
1:1 {
title = 1:1
value = 1.0
}
}
}
}
After adding this piece of code, the variants appears in all places, where file references can be defined, like inside e.g. news records (from news extension).
Now, after adding an image to a news record and clicking on the image manipulation button, I can select the new defined “isotope” crop variant and choose the desired 1:1 (square) crop area. So far so good.
My problem is now, that I don’t get the right output, when using this crop variant inside my fluid template using the the standard image viewhelper from TYPO3.
This:
<f:image image="{image}" cropVariant="isotope" maxWidth="400" />
don't generates square images, which I would expect.
If the source image has an aspect ratio of 4:3, I get flat-pressed rectangles, if the source image has an aspect ratio of 3:4, I get sky scrapers.
I also tried every possible combination of min/max/width/height attributes with/without additional "c", with no luck.
Sometime the result looks better for 4:3 source images, sometime for 3:4 images.
But I could no found a solution to get square (cropped) images for all kind of aspect ratios
[EDIT 04.07.2017]
Further experiments show different behaviors with different types of source image formats.
If the images are jpgs, I must set width="400c" and height="400c" to get square images. If the source images are pngs, a simple maxWidth="400" together with the cropVariant="isotope" do the job. Gif-Images seems to follow there own laws, which I have not yet looked through.
[EDIT 08.07.2017]
My current experience, after building an extension to test hundred of possible combinations: gif cropping is currently not working like expected.
To make things worse, the generated gif images are displayed differently in different browsers.
An example is this generated image:
View this image in FF, Chrome, Safari to see the different

Related

Dynamically resizing images using MediaQuery in Flutter

I have two pictures of different dimensions meant to be rendered as per the screen size of the phone the app is being run on which I suppose is something that can be achieved using MediaQuery in the following way:
if(MediaQuery.of(context).size.height < initialSize) {
return Image.asset('Image meant for smaller screens')
} else {
return Image.asset('Image meant for bigger screens')
}
What I don't understand is what initialSize value I should be putting in to check and resize accordingly? Hope I have been able to make my question clear!
initialSize differentiate the small image and large image screen based on screen height.
Let say if device's height is less than 200px we want to show X image, else show Y image.
Image getImage() {
if (MediaQuery.of(context).size.height < 200) {
return Image.asset('Image meant for smaller screens');
} else {
return Image.asset('Image meant for bigger screens');
}
}
You need to choose how you like to define small and large screen image, like here 200, initialSize.

CoreImage: CIImage write JPG is shifting colors [macOS]

Using CoreImage to filter photos, I have found that saving to JPG file will result in an image that has a subtle but visible blue hue. In this example using a B&W image, the histogram reveals how the colors have been shifted in the saved file.
---Input
Output [] Histogram shows the color layers are offset
-- Issue demonstrated with MacOS 'Preview' App
I can show a similar result using only the Preview App.
test image here: https://i.stack.imgur.com/Y3f03.jpg
Open the JPG image using Preview.
Export to JPEG at any 'Quality' other than the default (85%?)
Open the exported file and look at the Histogram, and the same color shifting can be seen as I experience within my app.
-- Issue demonstrated in custom MacOS App
The code here is as bare bones as possible, creating a CIImage from the photo and immediately saving it without performing any filters. In this example I chose 0.61 for compression as it resulted in a similar file size as the original. The distortion seems to be broader if using a higher compression ratio, but I could not find any value that would eliminate it.
if let img = CIImage(contentsOf: url) {
let dest = procFolder.url(named: "InOut.jpg")
img.jpgWrite(url: dest)
}
extension CIImage {
func jpgWrite(url: URL) {
let prop: [NSBitmapImageRep.PropertyKey: Any] = [
.compressionFactor: 0.61
]
let bitmap = NSBitmapImageRep(ciImage: self)
let data = bitmap.representation(using: NSBitmapImageRep.FileType.jpeg, properties: prop)
do {
try data?.write(to: url, options: .atomic)
} catch {
log.error(error)
}
}
}
Update 1: Using #Frank Schlegel's answer for saving JPG file
The JPG now carries a Color Sync Profile, and I can (unscientifically) track a ~10% performance boost for portrait images (less for landscape), which are nice improvements. But, unfortunately the resulting file is still skewing the colors in the same way demonstrated in the histograms above.
extension CIImage {
static let writeContext = CIContext(mtlDevice: MTLCreateSystemDefaultDevice()!, options: [
// using an extended working color space allows you to retain wide gamut information, e.g., if the input is in DisplayP3
.workingColorSpace: CGColorSpace(name: CGColorSpace.extendedSRGB)!,
.workingFormat: CIFormat.RGBAh // 16 bit color depth, needed in extended space
])
func jpgWrite(url: URL) {
// write the output in the same color space as the input; fallback to sRGB if it can't be determined
let outputColorSpace = colorSpace ?? CGColorSpace(name: CGColorSpace.sRGB)!
do {
try CIImage.writeContext.writeJPEGRepresentation(of: self, to: url, colorSpace: outputColorSpace, options: [:])
} catch {
}
}
}
Question:
How can I open a B&W JPG as a CIImage, and re-save a JPG file avoiding any color shifting?
This looks like a color sync issue (as Leo pointed out) – more specifically a mismatch/misinterpretation of color spaces between input, processing, and output.
When you are calling NSBitmapImageRep(ciImage:), there's actually a lot happening under the hood. The system actually needs to render the CIImage you are providing to get the bitmap data of the result. It does so by creating a CIContext with default (device-specific) settings, using it to process your image (with all filters and transformations applied to it), and then giving you the raw bitmap data of the result. In the process, there are multiple color space conversions happening that you can't control when using this API (and seemingly don't lead to the result you intended). I don't like these "convenience" APIs for rendering CIImages for this reason and I see a lot of questions on SO that are related to them.
I recommend you instead use a CIContext to render your CIImage into a JPEG file. This gives you direct control over color spaces and more:
let input = CIImage(contentsOf: url)
// ideally you create this context once and re-use it because it's an expensive object
let context = CIContext(mtlDevice: MTLCreateSystemDefaultDevice()!, options: [
// using an extended working color space allows you to retain wide gamut information, e.g., if the input is in DisplayP3
.workingColorSpace: CGColorSpace(name: CGColorSpace.extendedSRGB)!,
.workingFormat: CIFormat.RGBAh // 16 bit color depth, needed in extended space
])
// write the output in the same color space as the input; fallback to sRGB if it can't be determined
let outputColorSpace = input.colorSpace ?? CGColorSpace(name: CGColorSpace.sRGB)!
context.writeJPEGRepresentation(of: input, to: dest, colorSpace: outputColorSpace, options: [kCGImageDestinationLossyCompressionQuality: 0.61])
Please let me know if you still see a discrepancy when using this API.
I never found the underlying cause of this issue and therefore no 'true' solution as I was seeking. In discussion with #Frank Schlegel, it led to a belief that it is an artifact of Apple's jpeg converter. And the issue was certainly more apparent when using test files that appear monochrome but actually had small amount of color info in them.
The simplest fix for my app was to ensure there was no color in the source image, so I drop the saturation to 0 prior to saving the file.
let params = [
"inputBrightness": brightness, // -1...1, This filter calculates brightness by adding a bias value: color.rgb + vec3(brightness)
"inputContrast": contrast, // 0...2, this filter uses the following formula: (color.rgb - vec3(0.5)) * contrast + vec3(0.5)
"inputSaturation": saturation // 0...2
]
image.applyingFilter("CIColorControls", parameters: params)

Display loaded UI Image in Container with native size

I want to display UI logo images in their aspect ratio but in proper size that fit within its container. Already all logo images as per aspect ratio but few are too big or small compare to requirements.
At present this kind of thing happening:
Here is the code that I am using:
private void ShowGamePlayLogoViewed ()
{
for (int i = 0; i < DataCollection.companyDetailsList.Count; i++) {
Company company = DataCollection.companyDetailsList [i];
if (company.ViewedCounter > 0) {
GameObject companyItemObj = Instantiate (companyItemPref, gridViewContainer) as GameObject;
CompanyItem companyItem = companyItemObj.GetComponent<CompanyItem> ();
companyItem.companyId = company.CompanyId;
companyItem.UpdateCompanyLogo (company.CompanyLogo);
companyItem.UpdateCompanyName (company.CompanyName);
}
}
}
public void UpdateCompanyLogo (Sprite logoSprite)
{
logoImage.sprite = logoSprite;
logoImage.SetNativeSize ();
}
As you are seeing, logos overlapping the container. I want to display properly them in their respective containers also in aspect ratio too.
Let me clarify one more thing: all logos loaded from web server and they all are dynamic at a time, based on server data it will appear in mobile screen.
I have found solution through Unity Forum and I want to say thanks to #Hosnkobf for reply.
Here is the exact reply that worked for me properly:
adjust the image game object inside unity so that it has the height you are looking for. also adjust the anchors so that it scales with different resolutions properly.
Add an "AspectRatioFitter" component to the object. Make it "Height controls width".
Instead of logoImage.SetNativeSize (); do the following:
float aspectRatio = logoSprite.rect.width / logoSprite.rect.height;
var fitter = logoImage.GetComponent<UnityEngine.UI.AspectRatioFitter>();
fitter.aspectRatio = aspectRatio;
I hope this become useful to other members :)

How to autosize text on a textmesh

How do you auto-size text on a textmesh.
I have dice, with six sides, that I want to put words on. The words will constantly be changing, so I need them to auto size based on the size of the cube, which doesn't change.
The dice are not UI elements and thus sit outside the canvas.
Here is how I am adding the text.
LocationSide1.GetComponent<TextMesh>().text = "1";
LocationSide2.GetComponent<TextMesh>().text = "2";
LocationSide3.GetComponent<TextMesh>().text = "3";
LocationSide4.GetComponent<TextMesh>().text = "4";
LocationSide5.GetComponent<TextMesh>().text = "5";
LocationSide6.GetComponent<TextMesh>().text = "6";
Imagine I want the dice to say "pickle" instead of the 6. The next role it might say "cantaloupe" then "pea". The text will change sizes.
Example how the text sticks over the edge.
The answer you seek can be found on another thread - http://answers.unity3d.com/questions/218222/how-to-calculate-a-textmesh-width-without-renderin.html
public class TextBehaviour : MonoBehaviour
{
public TextMesh textmesh;
void Start ()
{
Bounds bound = BoundOfTextMesh("New Text");
print ("Size X = "+bound.size.x +"Size Y = "+bound.size.y);// Size of X and Y or Vector2
}
Bounds BoundOfTextMesh(string textMeshName)
{
textmesh = GameObject.Find (textMeshName).GetComponent<TextMesh>();
return textmesh.renderer.bounds ;
}
}
TextMesh doesn't have an auto-sizing feature, so to resize the text to fit in its container, you would have to follow Scott Barnes' suggestion of manipulating the Renderer for the desired effect.
If you're looking for alternatives that have the effect you're looking for, you might consider TextMesh Pro. It's a free asset on the Unity store that has Auto-Sizing functionality. The text comes in both 2D UI and 3D Text formats, so it will work both inside and outside of canvases.
TextMesh Pro Auto-Sizing Video

LIBGDX - Image Button - join images

I am trying to use de Image Button on LIBGDX to create a button based on two images.
Using add to second image, works fine, but have one problem.
The images are of different sizes.
Note: I am testing with the same picture to see the result
Is there a way to correct this? Using some scale to the images?
levelsTexture = new Texture(Gdx.files.internal("level1.png"));
levels = new TextureRegion(levelsTexture).split(TILE_WIDTH, TILE_HEIGHT);
ImageButton levels_image = new ImageButton(new TextureRegionDrawable(new
TextureRegion(levels[0][0])));
levels_image.add(new Image (levels[0][0]));
stage.addActor(levels_image);
levels_image.setScale(2f);
The problem:
ImageButton is an extension of the Table class and typically the ImageButton images are set as the background. Using the "add" method for the second image like you did might work kind of, but it behaves differently than setting the background and it also might not be what you want if you want the the second image to also change when you click the button.
The easiest way to add two images to a single ImageButton would be to simply combine the two images in Photoshop (or equivalent) and use that single image on the ImageButton.
The more advanced (and more flexible) method would be to combine the two images programmatically and use this as the background for your ImageButton. This can be done by creating a custom class which extends BaseDrawable and have it take two Images in the constructor. If you want your images stacked on top of each other, set the minHeight of your custom drawable class to be the combined height of your two images. Then override the draw method and draw your two images on top of each other like this:
#Override
public void draw(Batch batch, float x, float y, float width, float height){
img1.getDrawable().draw(batch, x, y, img1.getWidth(), img1.getHeight());
img2.getDrawable().draw(batch, x, y+img1.getHeight(), img2.getWidth(), img2.getHeight());
}
}
The ImageButton takes a Drawable in its constructor, so you can pass this object right into the button when you create it and both of your Images should appear in the button and they will be treated as one.
I've done something similar to make a background for a table using multiple Images and this method works great.
I wrote my own SpriteButton class in which I implement this method for scaling my textures.
private Dimension getScaledDimension(Dimension imgSize, Dimension boundary) {
int original_width = imgSize.width;
int original_height = imgSize.height;
int bound_width = boundary.width;
int bound_height = boundary.height;
int new_width = original_width;
int new_height = original_height;
// first check if we need to scale width
if (original_width > bound_width) {
//scale width to fit
new_width = bound_width;
//scale height to maintain aspect ratio
new_height = (new_width * original_height) / original_width;
}
// then check if we need to scale even with the new height
if (new_height > bound_height) {
//scale height to fit instead
new_height = bound_height;
//scale width to maintain aspect ratio
new_width = (new_height * original_width) / original_height;
}
return new Dimension(new_width, new_height);
}
Then finally you draw the texture with the output dimension as as size to draw.
sb.begin();
sb.draw(this.texture2, this.x, this.y, dim_size_new.width, dim_size_new.height);
sb.end();
So you could technically draw the second image to the size of the the first image, if the first image size is correct.
Your implementation will look different from mine but you should be able to figure it out form here on out.