iText7 Bug: Endless loop in ImageRenderer - itext

i came across an endless-loop-issue due to floating point arithmetic in iText7 DotNet ImageRenderer.
I've added an image with 2464x3692 pixels to an PDF page area of 523x770 pixels, causing the Layout() function to loop endlessly because every iteration returned LayoutResult.NOTHING.
The main issue is that the image height is calculated inside the Layout-function using the following statement:
Line 90: height = (float)width / imageWidth * imageHeight;
Due to the floating point operation the height got a value of something like 770.0001.
This is greater than the area height, causing the loop to return LayoutResult.NOTHING, so the image gets autoscaled again.
Inside the AutoScale-function only the image width is checked, which IS inside the area boundaries and so nothing is scaled.
I've fixed this issue by changing the following code inside ImageRenderer.cs:
90 - height = (float)width / imageWidth * imageHeight;
90 + float? propHeight = RetrieveHeight();
91 + height = propHeight == null ? (float)width / imageWidth * imageHeight : propHeight.Value;
214 - SetProperty(Property.HEIGHT, UnitValue.CreatePointValue(area.GetBBox().GetHeight()));
215 + SetProperty(Property.HEIGHT, area.GetBBox().GetHeight());
ImageRenderer now uses the height that is set inside AutoScale without recalculating it if not necessary.
Hopefully this will be fixed in one of the next releases. :)
Regards
Yosh

Related

how to make horizontal padding in iOS danielgindi charts

I'm using the ios-charts library and I would like to add some horizontal padding to my line charts so that the line does not start immediately at the border of the graph.
This is my current chart:
but I would like the blue line to have some padding as shown below. The rest should remain as it is. The reference gray lines should still take the entire width as they currently do.
I found it. This "padding" is actually ruled by the chart.xAxis.axisMinimum and chart.xAxis.axisMaximum. Those values are automatically set to the data min x and max x.
So if I want a left padding I just have to set a chart.xAxis.axisMinimum
In my case, I want around 10% of the x values to be padded, so I calculate it as
// dates is an array of Date representing my x values
if let maxX = dates
.map(\.timeIntervalSince1970)
.max(),
let minX = dates
.map(\.timeIntervalSince1970)
.min() {
let spanX = maxX - minX
let padding = spanX * 0.1
let axisMinimum = minX - padding
// set the left padding
chart.xAxis.axisMinimum = axisMinimum
}

Manually write world file (jgw) from Leaflet.js map

I have the need to export georeferenced images from Leaflet.js on the client side. Exporting an image from Leaflet is not a problem as there are plenty of existing plugins for this, but I'd like to include a world file with the export so the resulting image can be read into GIS software. I have a working script fort his, but I can't seem to nail down the correct parameters for my world file such that the resulting georeferenced image is located exactly correctly.
Here's my current script
// map is a Leaflet map object
let bounds = map.getBounds(); // Leaflet LatLngBounds
let topLeft = bounds.getNorthWest();
let bottomRight = bounds.getSouthEast();
let width_deg = bottomRight.lng - topLeft.lng;
let height_deg = topLeft.lat - bottomRight.lat;
let width_px = $(map._container).width() // Width of the map in px
let height_px = $(map._container).height() // Height of the map in px
let scaleX = width_deg / width_px;
let scaleY = height_deg / height_px;
let jgwText = `${scaleX}
0
0
-${scaleY}
${topLeft.lng}
${topLeft.lat}`
This seems to work well at large scales (ie zoomed in to city-level or so), but at smaller scales there is some distortion along the y-axis. One thing I noticed is that all examples of world files I can find (and those produced from QGIS or ArcMap) all have the x-scale and y-scale parameters being exactly equal (oppositely signed). In my calculations, these terms are different unless you are sitting right on the equator.
Example world file produced from QGIS
0.08984380916303301 // x-scale (size of px in x direction)
0 // rotation parameter 1
0 // rotation parameter 2
-0.08984380916303301 // y-scale (size of px in y direction)
-130.8723208723141056 // x-coord of top left px
51.73651369984968085 // y-coord of top left px
Example world file produced from my calcs
0.021972656250000017
0
0
-0.015362443783773333
-130.91308593750003
51.781435604431195
Example of produced image using my calcs with correct state boundaries overlaid:
Does anyone have any idea what I'm doing wrong here?
Problem was solved by using EPSG:3857 for the worldfile, and ensuring the width and height of the map bounds was also measured in this coordinate system. I had tried using EPSG:3857 for the worldfile, but measured the width and height of the map bounds using Leaflet's L.map.distance() function. To solve the problem, I instead projected corner points of the map bounds to EPSG:3857 using L.CRS.EPSG3857.project(), the simply subtracted the X,Y values.
Corrected code is shown below, where map is a Leaflet map object (L.map)
// Get map bounds and corner points in 4326
let bounds = map.getBounds();
let topLeft = bounds.getNorthWest();
let bottomRight = bounds.getSouthEast();
let topRight = bounds.getNorthEast();
// get width and height in px of the map container
let width_px = $(map._container).width()
let height_px = $(map._container).height()
// project corner points to 3857
let topLeft_3857 = L.CRS.EPSG3857.project(topLeft)
let topRight_3857 = L.CRS.EPSG3857.project(topRight)
let bottomRight_3857 = L.CRS.EPSG3857.project(bottomRight)
// calculate width and height in meters using epsg:3857
let width_m = topRight_3857.x - topLeft_3857.x
let height_m = topRight_3857.y - bottomRight_3857.y
// calculate the scale in x and y directions in meters (this is the width and height of a single pixel in the output image)
let scaleX_m = width_m / width_px
let scaleY_m = height_m / height_px
// worldfiles need the CENTRE of the top left px, what we currently have is the TOPLEFT point of the px.
// Adjust by subtracting half a pixel width and height from the x,y
let topLeftCenterPxX = topLeft_3857.x - (scaleX / 2)
let topLeftCenterPxY = topLeft_3857.y - (scaleY / 2)
// format the text of the worldfile
let jgwText = `
${scaleX_m}
0
0
-${scaleY_m}
${topLeftCenterPxX}
${topLeftCenterPxY}
`
For anyone else with this problem, you'll know things are correct when your scale-x and scale-y values are exactly equal (but oppositely signed)!
Thanks #IvanSanchez for pointing me in the right direction :)

How to get the result from fraction without rounding up in Thymeleaf

I am trying to get the relation between the height and width from image and then multiply by a fixed width to resize a picture using Thymeleaf.
For it, I saved the height and width in a java object called g. Using a fixed width: 270px I want to scale the height using the relation between the sized saved doing that:
th:style="'height:' + ${(g.height / g.width) * 270} +';
The saved and original size is: int height = 286 and int width = 423.
So the fraction's result should be 286/423 = 0.67.
But the problem is that this fraction g.height / g.width is giving me 0 as result.
How can I obtain decimals from this fraction? I tried with {#numbers.formatDecimal()} but not results.
Since both width & height are integers, it's doing integer division. Either store them as float/double on the object itself, or convert them to doubles in the expression.
th:style="'height:' + ${((0.0 + g.height) / g.width) * 270} +'px;'"

Focal length to Field of view

I'm importing some 3D models from Rhino 3D to Unity. When doing that I need to import the camera views. In Rhino they have the property Focal length and in Unity we have Field of view.
I need to convert focal length to Field of View. I found a formula to convert the values here
http://paulbourke.net/miscellaneous/lens/
I'm planning to use this formula
vertical field of view = 2 atan(0.5 height / focal length)
My question is how can I find the value for the height. I'm not sure from where I can get that in Unity.
Thanks
Maths isn't my strong suit but I do recall the formula was used in a certain BFBC2 fov tool
hFov = 2 * atan(tan( vFov/2 ) * width/height)
Where width and height are your current screen resolution dimensions.
I hope this is correct for your purpose.
To answer my question, this is the formula I ended up using at the end. Hope that'll be useful for anyone having a similar issue.
Code in C# in Unity
// Standard film size
int filmHeight = 24;
int filmWidth = 36;
// Formula to convert focalLength to field of view - In Unity they use Vertical FOV.
// So we use the filmHeight to calculate Vertical FOV.
double fovdub = Mathf.Rad2Deg * 2.0 * Math.Atan(filmHeight / (2.0 * focalLen));
float fov = (float) fovdub;

Changing this to a set pixel width

This is probably super easy, but I can't get it to work right. I am trying to do a simple update to my iOS app by changing an image resize option to a set pixel size. the code below is what i'm working with and how it is currently functioning:
selectedWidth = (30 * selectedWidth)/100;
selectedHeight = (30 * selectedHeight)/100;
I assume this is 30% of 100%? I just need the selected width to be 200px, and height to be automatic. Can somebody please help me? I'm a newb with this type of coding, my developer is away and i thought this would be an easy change haha.
So if I understand you right, I think this might help
selectedHeight = (selectedHeight / selectedWidth) * 200;
selectedWidth = newWidth;
This should calculate the correct height to your 200px width.
If you want to change your fixed-width from time to time, you can define a constant variable in the m.file below the imports:
#define kWidth 200
and use it instead of the hard coded 200 in the code on top.
Example:
old width: 100px
old height: 50px
new width: 200px
new height: (50 / 100) * 200 = 100px