Good afternoon,
I was wondering whether there is a (built-in) way to identify all images in a Word Document that has one or more other image(s) ‘on top’ of it… / overlapping etc.
I.e. some users have placed one image on top of another one for annotation purposes and I was wondering whether there’s a convenient way to identify these?
Thanks,
-JB
Hi Joerg,
Thanks for your inquiry. The Aspose.Words.Layout namespace provides classes that allow to access information such as on what page and where on a page particular document elements are positioned, when the document is formatted into pages.
You can get the position of image using layout API. Please use LayoutCollector.GetEntity method to get an opaque position of the LayoutEnumerator which corresponds to the specified node. Please check the following code example. Hope this helps you.
Document doc = new Document(MyDir + "in.docx");
LayoutCollector layoutCollector = new LayoutCollector(doc);
LayoutEnumerator layoutEnumerator = new LayoutEnumerator(doc);
Shape shape1 = (Shape)doc.GetChild(NodeType.Shape, 0, true);
Shape shape2 = (Shape)doc.GetChild(NodeType.Shape, 1, true);
var renderObject = layoutCollector.GetEntity(shape1);
layoutEnumerator.Current = renderObject;
RectangleF location1 = layoutEnumerator.Rectangle;
renderObject = layoutCollector.GetEntity(shape2);
layoutEnumerator.Current = renderObject;
RectangleF location2 = layoutEnumerator.Rectangle;
if (location1.IntersectsWith(location2))
{
Console.WriteLine("Overlapped.");
}
Good afternoon,
thank you - I’ll give that a try!
One question - will that code (the .IntersectsWith(…) call) work across pages… i.e. if one image is on page 1 and the other on page 3… as in correctly know that they are not on the same page(s) and therefore return false in these cases or would I have to add any page-logic?
Thanks,
-J
One more question:
for some image shapes (.IsImage = true) the layoutCollector.GetEntity(shape) method returns null… why is that?
I have / use the following code:
///
/// Determines whether any of the are overlapping.
///
/// The image shapes.
/// The layout collector.
/// The layout enumerator.
///
/// true if one of the images overlapped with another one in the list, otherwise, false.
///
private static bool HasOverlappingImages(List imageShapes, LayoutCollector layoutCollector, LayoutEnumerator layoutEnumerator)
{
if (imageShapes == null) throw new ArgumentNullException(nameof(imageShapes));
if (layoutCollector == null) throw new ArgumentNullException(nameof(layoutCollector));
if (layoutEnumerator == null) throw new ArgumentNullException(nameof(layoutEnumerator));
// check for proper image types
if (imageShapes.Any(shape => shape.IsImage == false))
{
throw new ArgumentOutOfRangeException(nameof(imageShapes), $"All {nameof(imageShapes)} instances must be image ones (.{nameof(Shape.IsImage)} must be set to true)");
}
// (double-)check whether layoutCollector and layoutEnumerator have the same .Document instances
if (layoutCollector.Document != layoutEnumerator.Document)
throw new ArgumentException($"The .Document of both {nameof(layoutCollector)} and {nameof(layoutEnumerator)} must be the same instance.");
//… same for all image shapes
if (imageShapes.Any(shape => shape.Document != layoutCollector.Document))
{
throw new ArgumentException($"The .Document of all {nameof(imageShapes)} must be the same instance as the and {nameof(layoutCollector)}/{nameof(layoutEnumerator)} ones.");
}
// else collect locations per image shape
var allImageLocationsOfShapes = imageShapes.ToDictionary(
shape => shape,
shape =>
{
// layoutEnumerator.Reset();
// layoutCollector.Clear();
var renderObject = layoutCollector.GetEntity(shape); // this returns null sometimes… why!?
// here the ‘renderObject’ is null sometimes…
layoutEnumerator.Current = renderObject;
return layoutEnumerator.Rectangle;
});
// then go ahead and check the images one by one for overlap with other ones
foreach (var imageShape in imageShapes)
{
var locationForCurrentShape = allImageLocationsOfShapes[imageShape];
// iterate over all -other- shape’s locations and check whether they overlap
foreach (var imageLocationForOtherShape in allImageLocationsOfShapes.Where(kvp => kvp.Key != imageShape))
{
if (locationForCurrentShape.IntersectsWith(imageLocationForOtherShape.Value))
{
// if we find one image that overlaps with another one, we can return early / ‘true’
return true;
}
}
}
// else… if none overlapped at all, it’s all good / return false (= no overlapping images)
return false;
}
Hi Joerg,
Thanks for your inquiry.
jbattermann:
One question - will that code (the .IntersectsWith(…) call) work across pages… i.e. if one image is on page 1 and the other on page 3… as in correctly know that they are not on the same page(s) and therefore return false in these cases or would I have to add any page-logic?
Please use LayoutCollector.GetStartPageIndex method to get 1-based index of the page where node (image) begins. You can use this method to check either both images are on same page or not.
You may use LayoutEnumerator.Rectangle, Shape.Height and Shape.Width properties to check either images are overlapped or not. The LayoutEnumerator.Rectangle property returns the bounding rectangle of the current entity relative to the page top left corner (in points). The Shape.Height and Shape.Width returns the height and width of image.
jbattermann:
for some image shapes (.IsImage = true) the layoutCollector.GetEntity(shape) method returns null… why is that?
Could you please attach your input Word document here for testing? We will investigate the issue on our side and provide you more information.