Custom Cursor - Colour Issues - c#

I'm having a problem where a the colours in a custom cursor are sometimes not displaying correctly.
I have a Windows Forms application and on one of the forms there is a PictureBox control. When an image is loaded into that PictureBox and the mouse is moved over that control I want to display a custom cursor. This cursor is a little unusual in that for each image that's loaded into the PictureBox there's another associated image, and as the user moves the mouse pointer over the PictureBox control I want the cursor to be a square and within that square I want it to display the corresponding pixels from the associated image. Within certain limits, the size of the cursor may be changed by the user.
In principle I've nearly got it to work. Certainly at any given point the cursor is showing the right part of the associated image and it updates properly as I move the pointer around.
The problem is that the colours being displayed in the cursor are not always correct. They're in the right ballpark: a shade of red will always display as a shade of red for instance, just not necessarily the right shade. Sometimes the cursor colours look slightly darker, other times slightly lighter. I've noticed that for any colours where all three of the R, G and B components are a combination of 0 or 255, the colours always look correct.
In addition, this only happens if the cursor is a 64x64 pixel square or smaller. If the user increases the size of the cursor beyond that point the problem disappears, though it will reappear if the cursor size is later reduced back to 64x64 or smaller.
This is the code which does the work. X and Y come from the MouseMove event. CursorSize is a form-wide int variable which holds the size of the cursor in pixels (always an even number) and imgAssoc is a form-wide Image variable into which the associated image was loaded. picMain is the PictureBox control.
private void LoadCursorFromBitmap(int X, int Y)
{
int halfSize = CursorSize / 2;
// The new cursor image is a [CursorSize] x [CursorSize] pixel square.
using (Bitmap bmp = new Bitmap(CursorSize, CursorSize))
{
using (Graphics g = Graphics.FromImage(bmp))
{
// Create a [CursorSize] x [CursorSize] pixel square, centered on the X and Y co-ordinates.
Rectangle square = new Rectangle(X - halfSize, Y - halfSize, CursorSize, CursorSize);
// Copy the square section of the image to the bitmap.
g.DrawImage(imgAssoc, 0, 0, square, GraphicsUnit.Pixel);
// Draw a line around the edge of the bitmap.
using (Pen pen = new Pen(Color.FromArgb(64, Color.Black), 1F))
{
g.DrawRectangle(pen, 0, 0, CursorSize - 1, CursorSize - 1);
}
}
picMain.Cursor = new Cursor(bmp.GetHicon());
}
}
Any ideas how to solve this?

Related

C# WinForms | Picturebox white bleeding right & bottom edges

Hello Stackoverflow Community.
I currently work on an application which has a cursor region magnifyer feature, for the user to pick a color.
However, i've the problem that the Picturebox has white edges on the right and bottom, even though the image captured is only one dark color.
The captured screen is 10x10 pixel and the Picturebox is 80x80 pixel and it's SizeMode set to StretchImage.
I checked if the raw captured image maybe contains this edges already by saving it and checking it in Photoshop. But the raw captured image is fine, so it must be something weird with the Picturebox.
Here you can see how it looks (The mousecursor and the capture-region[green rectangle] are just painted on the screenshot for demonstration, as i was not able to screen my cursor, and yes - the green region is painted way too large, it should be just 10x10 pixel ^^)
Has it maybe something to do with the way the Image get's stretched internally? If so, is there any, not too complicated way around it?
I appreciate any help in advance :)
//Edit: I think it's actually about the stretching
I found this topic Image after resize has white border but i don't know what the GetSize() Method is, or where it is (from)
Have a great day!
I found a solution for the edges here, as you can see in the first screen. However, in the second screen you can see a 2x2 pixel capture, stretched to 80x80 pixel with the found "solution", will mix colors as it's actually 80x80 pixel in the end, while i want to have it displaying the raw pixels, so, 3 black ones and one white one in this case. Now i am even more stuck ^^
I guess i should instead read the pixel colors of the single pixels from captured image and set the colors in the preview picturebox, or make 4 panels in the case of just 2x2 pixels
public new Image Resize(Image image, int targetWidth, int targetHeight)
{
var resizedImage = new Bitmap(targetWidth, targetHeight);
using (var graphics = Graphics.FromImage(resizedImage))
{
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
var attributes = new ImageAttributes();
attributes.SetWrapMode(WrapMode.TileFlipXY);
var destination = new Rectangle(0, 0, targetWidth, targetHeight);
graphics.DrawImage(image, destination, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
}
return resizedImage;
}
//Edit:
Okay i think i'm gonna use Get/SetPixel or Panels(for small captures), as i did here on the right, the left is still the 80x80 Picturebox

How can I make the picture smaller in the picture box without affecting the coordination?

I want to let the user define the area that they want to extract the text, but for the line item, the picture is too large and it make the rectangle cannot include the whole table.
I found a solution that able to smaller the picture but the coordinate also changed. For example, I draw the rectangle area at the "Malarvili" but the rectangle coordinate is not same as what I had drawn. Because of this, the extracted text is wrong.
So I want to know any solution to make the picture becomes smaller in the picturebox without affecting the original rectangle coordinate? Or using my original solution which is using the "autosize" without changing the picture size, but I have also facing a problem which is when i drawing the rectangle to the right, the scrollbar will not autoscroll and it makes me cannot draw the rectangle to the end of the right.
Any solution to solve these problems? Thanks a lot.
You can calculate the ratios (x and y axis) between the resize image (pictureBox with StretchImage mode) and the original image, and then calculate back the rectangle for original image from the rectangle you drawed in the pictureBox using these ratios.
pictureBox.SizeMode = PictureBoxSizeMode.StretchImage;
ratio_X = (double) pictureBox.Width/original_image;
ratio_Y = (double) pictureBox.Height/original_image;
//suppose you have the rect drawed in the pictureBox: pictureBox_rect
//now make a rect for original_image
Rectangle original_rect = new Rect((int)pictureBox_rect.X * ratio_X,
(int)pictureBox_rect.Y * ratio_Y,
(int)pictureBox_rect.Width * ratio_X,
(int)pictureBox_rect.Height * ratio_Y)

How to draw a lot of clickable rectangles in WPF?

I'm working on a basic mindmap program but I don't have a lot of experience with drawing with WPF. I want to be able to draw rectangles with text on them and i would like to be able to click on the rectangles to change the text for example.
As of now I have:
private void DrawSubject(int curve, double X, double Y, Brush clr)
{
Rectangle rect = new Rectangle();
rect.Width = 62;
rect.Height = 38;
rect.Fill = clr;
rect.Stroke = line;
rect.RadiusX = rect.RadiusY = curve;
Canvas.SetLeft(rect, X);
Canvas.SetTop(rect, Y);
mindmap.Children.Add(rect);
}
SolidColorBrush line = new SolidColorBrush(Color.FromArgb(255, 21, 26, 53));
minmap is the name of the canvas. I want to be able to draw a lot of these rectangles which present branches of the mindmap. However, when I drew 10,000 of these on random locations the process memory in the diagnostic tools went up by 100 MB, after it was done drawing all of them. I did this to sort of simulate a mindmap with 10,000 branches. So i was wondering if there might be a way to decrease the used memory for these rectangles?
Or is it better to use DrawingVisual and a grid.click event which checks if the clicked position matches the position of a rectangle by putting the coordinates of the rectangle in a List?
I would attempt the DrawingVisual method you described, if that proves costly in performance(I don't know how well DrawingVisual works) you could look into embedding OpenGL or DirectX into your application and rendering them via that.
But raytracing drawn visuals rather than making a Control for each is definitely the way to go for your scale.

gridding extraction in image

There is an image, and there are some grid lines which are vertical or horizontal in the image. I just want to extract the gridding from the image, but there are many unnecessary lines in the image, interfering my work. Do anyone have a more methods to extract the gridding via C#?
My idea is that for grid lines, there are some basic unit that compose the whole gridding, so if I know the size of the basic unit and I know the initial point of the gridding, maybe I can re-draw the gridding. Thus, I think it is the key to resolve the problem.
There are two direction you can take:
Either you take a look at the image and draw a grid just like the one there
Or you try to analyze the image to find out the parameters it takes to draw thw grid
I loaded the image into Photoshop and found that the gridlines start at (6,10) with a raster of 43 pixels and a line width of 1.5-2 pixels.
Using these values to draw those lines is trivial:
Image img = Image.FromFile(yourImage);
Bitmap bmp = new Bitmap(img.Width, img.Height);
using (Graphics G = Graphics.FromImage(bmp) )
using (Pen pen = new Pen(Color.DarkBlue, 2f) )
{
G.Clear(Color.Black);
for (int x = 6; x < img.Width; x += 43)
G.DrawLine(pen, x, 0, x, img.Height);
for (int y = 10; y < img.Height; y += 43)
G.DrawLine(pen, 0, y, img.Width, y);
}
bmp.Save(yourGrid);
bmp.Dispose();
img.Dispose();
The second option is not trivial. If the image is in fact typical, the good news is that the lines are straight and the raster regular. But pulling those values from the image automagically is still not so simple. One dificulty id the varying color of the grid.. I would scan a number of rows and test the pixels for being not black. Those would go into lists and then I would discard points that are only in a minority of those lists. This would then be repeated for a number of columns.
The effort to put into this will only pay if you need this analysis to be done for a considerable number of files with different grids. If the number is small a semi-automatic analysis may be easier and if it is only about one file go for the manual analysis!

Overlay of two images - Control which part is in the foreground with mouse coursor

I need to be able to compare two different Images in the following way:
The images are displayed on top of each other so first there is only one image visible. When hovering with the mouse coursor over the image this defines the X-position of a vertical line which is splitting the image, displaying part of the first image left to the line and the rest of the second image right to the line.
This basically should be used as a quality comparison for two images with identical contents.
Here is a picture that hopefully makes my intentions clear:
you can use splitter control. splitter one side you put one picture control another side put other picture control
I was able to resolve this by using a SplitContainer and custom drawing. As described in the comment of Vasanthakumar's answer purely using a picturebox is not enough as you will not be able to align the right image at the same starting point than the left image (top left of the form).
What I did was the following:
pictureBox 1 displays its image normally
the Image in pictureBox 2 is drawn on every move of the splitter (this.splitContainer1.SplitterMoved += new System.Windows.Forms.SplitterEventHandler(this.splitContainer1_SplitterMoved); with a custom subset of the Image to be displayed.
This effectively allows to generate the overlay I need.
Part of my implementation showing the drawing logic:
Bitmap bmp = new Bitmap(gImg2.Width, gImg2.Height);
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawImage(gImg2, 0, 0, new Rectangle(e.SplitX, 0, gImg2.Width - e.SplitX, gImg2.Height), GraphicsUnit.Pixel);
}
pictureBox2.Image = bmp;

Categories