I want to highlight overlapped text from PDF. Got all words coordinates using "PDFExchangeviewer.exe" and then converted to dot.net rectangle. In dotnet rectangle found intersection of rectangle and highlighted the intersected words using itextsharp. But it highlighting unwanted words in PDF rather than overlapped text. Please post solution to this. Below shown is my part of the code in c#
foreach (var pdfrect in WordpageCoordinates)
{
float X = (float)pdfrect.Item1;
float Y = reader.GetPageSize(pdfPg).Top - (float)pdfrect.Item4;
float Width = (float)pdfrect.Item3 - X;
float Height = (float)(pdfrect.Item4) - (float)(pdfrect.Item2);
DotNetRect.Add(new System.Drawing.RectangleF(X, Y, Width, Height));
}
for(int j = 0; j < DotNetRect.Count; j++)
{
System.Drawing.RectangleF MasterRect = DotNetRect[j];
System.Drawing.RectangleF ChildRect = new System.Drawing.RectangleF();
if (j == DotNetRect.Count - 1)
{
break;
}
for (int k = j + 1; k < DotNetRect.Count; k++)
{
ChildRect = DotNetRect[k];
System.Drawing.RectangleF NewRect = new System.Drawing.RectangleF(ChildRect.X, ChildRect.Y , ChildRect.Width, ChildRect.Height);
if (MasterRect.IntersectsWith(NewRect))
{
{
iTextSharp.text.Rectangle Annotrect = new iTextSharp.text.Rectangle((float)WordpageCoordinates[k].Item1, (float)WordpageCoordinates[k].Item2, (float)WordpageCoordinates[k].Item3, (float)WordpageCoordinates[k].Item4);
//iTextSharp.text.Rectangle Annotrect = new iTextSharp.text.Rectangle((float)ClsGlobal.TextCoordinatesList[k].Item1, (float)ClsGlobal.TextCoordinatesList[k].Item2, (float)ClsGlobal.TextCoordinatesList[k].Item3, (float)ClsGlobal.TextCoordinatesList[k].Item4);
//float[] quad = { Annotrect.Left, Annotrect.Bottom, Annotrect.Right, Annotrect.Bottom, Annotrect.Left, Annotrect.Top, Annotrect.Right, Annotrect.Top };
float[] quad = { Annotrect.Left, Annotrect.Top, Annotrect.Right, Annotrect.Top, Annotrect.Left, Annotrect.Bottom, Annotrect.Right, Annotrect.Bottom };
PdfAnnotation HighlightAnnotation = PdfAnnotation.CreateMarkup(pdfstamper.Writer, Annotrect, "Text Overlap", PdfAnnotation.MARKUP_HIGHLIGHT, quad);
HighlightAnnotation.Title = "Overlap Text Highlighter\n" + System.DateTime.Now.ToString();
HighlightAnnotation.Color = iTextSharp.text.BaseColor.GREEN;
pdfstamper.AddAnnotation(HighlightAnnotation, pdfPg);
}
}
}
}
You are testing whether 2 Rectangles intersect, but you are not working with the intersection. Take the intersection for the annotation. The intersection is the overlapping part.
RectangleF intersection = RectangleF.Intersect(MasterRect, NewRect);
With this static method RectangleF.Intersect Method (RectangleF, RectangleF):
public static RectangleF Intersect(
RectangleF a,
RectangleF b
)
There is no need to create a copy of ChildRect. IntersectsWith only tests for an intersection but does not create one and does not change the rectangle. Since RectangleF is a struct and therefore a value type, a copy of it is passed to the method anyway. If it was a class, i.e. a reference type, the method could theoretically change its fields and properties.
Intersect returns an empty rectangle if there is no intersection. Therefore, you could also first create the intersection and then test if it is not empty instead of using IntersectsWith.
RectangleF intersection = RectangleF.Intersect(MasterRect, ChildRect);
if (!intersection.IsEmpty)
{
// create the annotation with `intersection`
}
Instead of writing
if (j == DotNetRect.Count - 1)
{
break;
}
change the loop condition to (added - 1):
for(int j = 0; j < DotNetRect.Count - 1; j++)
Related
I have an image (attached) which I'm using as a test. I'm trying to get and store all the colours of each pixel in an array.
I use the below code to do this;
Texture2D tex = mapImage.mainTexture as Texture2D;
int w = tex.width;
int h = tex.height;
Vector4[,] vals = new Vector4[w, h];
Color[] cols = tex.GetPixels();
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
if(cols[y+x] != Color.black)
{
Debug.Break();
}
vals[x, y] = cols[(y + x)];
}
}
Where mapImage is a public Material variable which I drag in into the scene on the prefab. As you can see, I've added a debug test there to pause the editor if a non-black colour is reached. This NEVER gets hit ever.
Interestingly, I've got another script which runs and tells me the colour values (GetPixel()) at the click position using the same image. It works fine (different methods, but both ultimately use the same material)
I'm at a loss as to why GetPixels() is always coming out black?
I've also been considering just loading the image data into a byte array, then parsing the values into a Vector4, but hoping this will work eventually.
You aren't indexing into the Color array properly. With the indices you are using, y+x, you keep checking the same values on the lowest rows of the texture, never getting past a certain point.
Instead, when calculating the index, you need to multiply the row that you are on by the row length and add that to the column you are on:
Texture2D tex = mapImage.mainTexture as Texture2D;
int w = tex.width;
int h = tex.height;
Vector4[,] vals = new Vector4[w, h];
Color[] cols = tex.GetPixels();
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
int index = y * w + x;
vals[x, y] = cols[index];
}
}
From the documentation on GetPixels:
The returned array is a flattened 2D array, where pixels are laid out left to right, bottom to top (i.e. row after row). Array size is width by height of the mip level used. The default mip level is zero (the base texture) in which case the size is just the size of the texture. In general case, mip level size is mipWidth=max(1,width>>miplevel) and similarly for height.
My goal is to have a robot use this grid to create a map base off the information it collects from its surroundings. When the robot detects an object the square in front of it turns red. Currently I am stuck on how I can give each square an x and Y value for location purposes. Also when I scroll the screen the block sizes change, can someone provide help with that as well?
Rectangle rect = new Rectangle(700, 350, 50, 50);
g.DrawRectangle(myPen, rect); // Draws the Rectangle to the screen
e.Graphics.FillEllipse(myBrush, 700,350,50,50);`
for (int i = 0; i < 9900; i = i + 50)
{
rect = new Rectangle(0 + i, 0, 50, 50);
g.DrawRectangle(myPen, rect);
for (int j = 0; j < 9900; j = j + 50)
{
rect = new Rectangle(0 + i, 0 + j, 50, 50);
g.DrawRectangle(myPen, rect);
}
}
Here is a very quick example of how to do this using a 2d array. It was written in LINQPad, so it may look a little odd, but it should give you some leads. It allows you to store a map and look up values using x and y coordinates. You can use the CellInfo class to add any extra information about the cell that you need, beyond if it is blocking or not.
Ideally, you would want to wrap the entire array up in your own Map class, that abstracts away the details, and gives you a lot of helpful utility functions. For instance, if your map is extremely large, you may run out of memory. You could have the Map class only load smaller blocks of the map from files on disk as needed, or even make the map wrap around its self easily.
void Main()
{
var map = new CellInfo[10, 10];
for (int x = 0; x < 10; x++)
{
for (int y = 0; y < 10; y++)
{
map[x, y] = new CellInfo();
}
}
var rnd = new Random();
for (int i = 0; i < 20; i++)
{
map[rnd.Next(0, 10), rnd.Next(0, 10)].IsBlocked = true;
}
DrawMap(map).Dump();
}
public Bitmap DrawMap(CellInfo[,] map)
{
var img = new Bitmap(320, 320, PixelFormat.Format32bppArgb);
using (var g = Graphics.FromImage(img))
{
for (int x = 0; x < 10; x++)
{
for (int y = 0; y < 10; y++)
{
var cell = map[x, y];
Brush brush = cell.IsBlocked ? Brushes.Red : Brushes.White;
g.FillRectangle(brush, x * 32, y * 32, 31, 31);
g.DrawRectangle(Pens.Black, x * 32, y * 32, 31, 31);
}
}
}
return img;
}
public class CellInfo
{
public bool IsBlocked { get; set; } = false;
}
It produces the following output (varies each time it is run):
I'm using Visual Studio 2010, including reference Dynamic Data Display map.
I'm drawing on the map polygon by drawing DragglePoints and Segments between the points.
I found a code that find if point(x,y) is in polygon, but on a map it doesnt work.
pt = e.GetPosition(this.plotter.CentralGrid); // Get the mouse position
ps = this.plotter.Viewport.Transform.ScreenToViewport(pt); // Transform the mouse positon to Screen on chartplotter
// Now ps is the point converting to the map point - it works perfect
// I'm using it for another things.(like Painting a dragglepoint or something else.
for (int k = 0; k <= listPolygons.Count - 1; k++)
{
bool ifInside = PointInPolygon(new Point(ps.X, double.Parse(this.plotter.Viewport.Transform.DataTransform.ViewportToData(ps).Y.ToString())), listPolygons[k]); // Sending to the functing pointInPolygon the point and list of polygons we have
if (ifInside)
{
listPolygons[k].removePolygon(listPolygons[k], plotter);
listPolygons.RemoveAt(k);
break;
}
}
and the function PointInPolygon:
private bool PointInPolygon(Point point, Polygon polygon)
{
List<DraggablePoint> points = polygon.getListPoints();
DraggablePoint pointClicked = new DraggablePoint(new Point(point.X, point.Y));
int i, j, nvert = polygon.getNumberOfVertx();
bool c = false;
for(i = 0, j = nvert - 1; i < nvert; j = i++)
{
if (((points[i].Position.Y) >= pointClicked.Position.Y) != (points[j].Position.Y >= pointClicked.Position.Y) &&
(pointClicked.Position.X <= (points[j].Position.X - points[i].Position.X) * (pointClicked.Position.Y - points[i].Position.Y) / (points[j].Position.Y - points[i].Position.Y) + points[i].Position.X))
c = !c;
}
return c;
}
Here c always returns as false, whether I click inside a polygon or outside.
points[i].Position.Y and points[i].Position.X and pointClicked.Position.Y and pointClicked.Position.X is given a perfect variables - on the map values.
Converting a bitmap to grayscale is pretty easy with AForge:
public static Bitmap ConvertToGrayScale(this Bitmap me)
{
if (me == null)
return null;
// first convert to a grey scale image
var filterGreyScale = new Grayscale(0.2125, 0.7154, 0.0721);
me = filterGreyScale.Apply(me);
return me;
}
But I need something more tricky:
Imagine you want to convert everything to grayscale except for a circle in the middle of the bitmap. In other words: a circle in the middle of the given bitmap should keep its original colours.
Let's assume the radius of the circle is 20px, how should I approach this?
This can be accomplished using MaskedFilter with a mask that defines the circled area you describe. As the documentation states
Mask can be specified as .NET's managed Bitmap, as UnmanagedImage or
as byte array. In the case if mask is specified as image, it must be 8
bpp grayscale image. In all case mask size must be the same as size of
the image to process.
So the mask image has to be generated based on the source image's width and height.
I haven't compiled the following code but it should get you on your way. If the circle is always in the same spot, you could generate the image mask outside the method so that it doesn't have to be regenerated each time you apply the filter. Actually you could have the whole MaskedFilter generated outside the method that applies it if nothing changes but the source image.
public static Bitmap ConvertToGrayScale(this Bitmap me)
{
if (me == null)
return null;
var radius = 20, x = me.Width / 2, y = me.Height / 2;
using (Bitmap maskImage = new Bitmap(me.Width, me.Height, PixelFormat.Format8bppIndexed))
{
using (Graphics g = Graphics.FromImage(maskImage))
using (Brush b = new SolidBrush(ColorTranslator.FromHtml("#00000000")))
g.FillEllipse(b, x, y, radius, radius);
var maskedFilter = new MaskedFilter(new Grayscale(0.2125, 0.7154, 0.0721), maskImage);
return maskedFilter.Apply(me);
}
}
EDIT
The solution for this turned out to be a lot more trickier than I expected. The main problem was that the MaskedFilter doesn't allow the usage of filters that change the images format, which the Grayscale filter does (it changes the source to an 8bpp or 16 bpp image).
The following is the resulting code, which I have tested, with comments added to each part of the ConvertToGrayScale method explaining the logic behind it. The gray-scaled portion of the image has to be converted back to RGB since the Merge filter doesn't support merging two images with different formats.
static class MaskedImage
{
public static void DrawCircle(byte[,] img, int x, int y, int radius, byte val)
{
int west = Math.Max(0, x - radius),
east = Math.Min(x + radius, img.GetLength(1)),
north = Math.Max(0, y - radius),
south = Math.Min(y + radius, img.GetLength(0));
for (int i = north; i < south; i++)
for (int j = west; j < east; j++)
{
int dx = i - y;
int dy = j - x;
if (Math.Sqrt(dx * dx + dy * dy) < radius)
img[i, j] = val;
}
}
public static void Initialize(byte[,] arr, byte val)
{
for (int i = 0; i < arr.GetLength(0); i++)
for (int j = 0; j < arr.GetLength(1); j++)
arr[i, j] = val;
}
public static void Invert(byte[,] arr)
{
for (int i = 0; i < arr.GetLength(0); i++)
for (int j = 0; j < arr.GetLength(1); j++)
arr[i, j] = (byte)~arr[i, j];
}
public static Bitmap ConvertToGrayScale(this Bitmap me)
{
if (me == null)
return null;
int radius = 20, x = me.Width / 2, y = me.Height / 2;
// Generate a two-dimensional `byte` array that has the same size as the source image, which will be used as the mask.
byte[,] mask = new byte[me.Height, me.Width];
// Initialize all its elements to the value 0xFF (255 in decimal).
Initialize(mask, 0xFF);
// "Draw" a circle in the `byte` array setting the positions inside the circle with the value 0.
DrawCircle(mask, x, y, radius, 0);
var grayFilter = new Grayscale(0.2125, 0.7154, 0.0721);
var rgbFilter = new GrayscaleToRGB();
var maskFilter = new ApplyMask(mask);
// Apply the `Grayscale` filter to everything outside the circle, convert the resulting image back to RGB
Bitmap img = rgbFilter.Apply(grayFilter.Apply(maskFilter.Apply(me)));
// Invert the mask
Invert(mask);
// Get only the cirle in color from the original image
Bitmap circleImg = new ApplyMask(mask).Apply(me);
// Merge both the grayscaled part of the image and the circle in color in a single one.
return new Merge(img).Apply(circleImg);
}
}
Right now, I'm working on a little Jump'n'Run game in XNA. I decided to load textures from a tileset,
and designed a method for getting the source rectangles of a bigger rectangle. Within the method, the calculated rectangles are being added to a list, and the list is returned at the end of the method. However, the method doesn't seem to work properly. When trying to get a rectangle from a given index out of the list, I'm getting a index out of range exception. I tried this with several numbers, it still wont work. here is my method for getting the rectangles:
public static List<Rectangle> getSourceRectangles(Rectangle original, int partWidth, int partHeight)
{
List<Rectangle> rlist = new List<Rectangle>();
int ix, iy;
ix = original.Width / partWidth;
iy = original.Height / partHeight;
for (int x = 0; x < ix; x++)
{
for (int y = 0; y < iy; y++)
{
Rectangle r = new Rectangle(x * partWidth, y * partHeight, partWidth, partHeight);
rlist.Add(r);
}
}
return rlist;
}
I save the return value in a global Container class.
this is were I get the error: (ist just the constructor of the NormalTile class!)
public NormalTile(int _TextureIndex,Rectangle _rect)
{
this.rect = _rect;
this.TileTextureIndex = _TextureIndex - 1;
this.tex_rect = Global.TileTextures[TileTextureIndex];//HERE
}
Why is this even Happening?