C#, Preventing erasing strokes from erasing portions of overlapped background image - c#

I am using a C# console application project to generate raster frames and then uses
ffmpeg tool to generate the video from those frames. I am using a graphical object g to draw a bmp object and save it to
generate
the frame(s) [The rate of saving is 25 frame per second]. I implemented drawing[writing] on the graphical object fine, erasing
"ON WHITE BACKGROUND", clearing the graphical object very well,
undoing drawn shapes perfectly. 4) I attempted to set background and
import images and that worked so very well as you can write on the
graphical object [whether white paper, background image, imported
image...etc]
The problem that when I attempt to erase portion of the image which has a background [background image, for example lines,
graphical, coordinates..etc]. the graphical object erases the
portion of the image where the stroke of the erase [white color
overlaps]. Sure This [white colors for erasing strokes ] was working
fine with white page background.
I am kind of thinking out loud, logically an it makes perfect sense that the white stroke erasers will mark on the non-white
backgrounds [so it looks as the eraser erased the background].
Is there (a) way(s), mechanism, overlay algorithm, coloring mechanism :) to make show the background image parts under the erasing-strokes' points as it is, non distorted. For example,:
1) Placing the background image on the first layer
2) Perform the drawing on the top layer
3) When erasing [on the top layer], use a transparent color, or stroke mechanism to show the background image-portions' that was/were overlapped before with the background......Is that possible??
Thanks for your help and input in advance.
Note that you may not have the perfect solution. But your thoughts are appreciated.

Resolution:
Masking the original image (source image with all my shapes' drawing) and drawing it on a different destination bmp:
public static Image CropToPath(Image srcImage, List<Point> Points, Pen p, Bitmap bmp)
{
Bitmap mask = bmp;//new Bitmap(Bitmap.FromFile( (new DirectoryInfo(outPutPath)).GetFiles()?.OrderByDescending( f => f.CreationTimeUtc).First()?.FullName));
DrawPoints(Graphics.FromImage(mask), p, Points);
using (var imgattr = new ImageAttributes())
{
// set color key to Line
imgattr.SetColorKey(Color.Gainsboro, Color.Gainsboro);
// Draw non-line portions of mask onto original
using (var g3 = Graphics.FromImage(srcImage))
{
SmoothGraphic(g3).DrawImage(
mask,
new Rectangle(0, 0, srcImage.Width, srcImage.Height),
0, 0, srcImage.Width, srcImage.Height,
GraphicsUnit.Pixel, imgattr
);
return srcImage;
}
}
}

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

Application C# image quality [duplicate]

This question already exists:
Application about C# image quality [closed]
Closed 2 years ago.
I am developing an application with C#. In the application I developed, I take the picture file with the user selection and transfer the picture onto the form.
After this step, I want to make changes to the bitmap of the picture. For example resizing the image in small sizes and converting to 1bpp color format.
I can do these now, I can resize the image and convert it to 1bpp color format, but at this point I think I have quality problems.
For example, when I take a screenshot of a text and send it to the program, I see that the letters in the text are unclearly bad when I view it in the resized 1bpp color format.
I show the algorithms I used and the screenshot of the application:
Bitmap bmp = new Bitmap(ResizeImage.filePath);
Bitmap bmpOriginalRGB = Helper.ImageResize(bmp, 512, 384);
pcbox1.Image = bmpOriginalRGB;
Bitmap bmpResizeRGB = Helper.ImageResize(bmp, ResizeWidth, ResizeHeight);
pcbox2.Image = bmpResizeRGB;
Bitmap bmpResize1BPP_1 = Helper.ConvertTo1BppImage(Helper.ImageResize(bmp, ResizeWidth, ResizeHeight));
pcbox3.Image = bmpResize1BPP_1;
Bitmap bmpResize1BPP_2 = bmpResizeRGB.Clone(new Rectangle(0, 0, ResizeWidth, ResizeHeight), PixelFormat.Format1bppIndexed);
pcbox4.Image = bmpResize1BPP_2;
Bitmap oledBitmap = bmpResize1BPP_2;
and
public static Bitmap ImageResize(Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
Here's a first screenshoot
Here's a second screenshoot
Here's a third screenshoot
For example, as in the second screen image, the shadow of the woman appears as black. And I don't want that. I want to see a clearer black and white image.
Do you think it is possible to further improve this picture quality?
Edit: Sorry for translate..
I don't believe your problem is the quality on resizing, it's rather the conversion from greyscale to black and white.
When resizing, the color of the adjacent pixels are averaged together to get a new color approximating the set of pixels. So going from a 200x200 pixel image to a 100x100 pixel image, a set of 4 pixels becomes a single pixel. It will still look fairly good, but the solid black text will become a series of gray pixels. The exact formula will vary by the interpolation method used. But when resizing a nice piece of black and white text, the text will end up lighter or more grey (which will be important later)
However, when going from greyscale (or full color) to black and white each pixel ends up being either black and white, there are no other options, but there are different algorithms used to decide which pixels end up black or white, often called dithering. (https://en.wikipedia.org/wiki/Dither)
Your first b/w image appears to use some form of error diffusion, quite possibly Floyd-Steinberg. It tends to work fairly well on real wold images and turns grey areas into spaced out black pixels visually approximating the greyness of the area they fall in.
Your second b/w image appears to be a simple threshold algorithm. Basically pixels darker than a certain color end up black, and all the rest end up white. You can adjust the image by simply setting which color is used as the threshold. Often this works well with text, but you will need to adjust the value used as the threshold, but I don't know if the libraries you are using allow for this or not. I have found what works well for programmatically selecting the threshold is to total up how many pixels there are of each color, and then assume some percent will be black (text tends to be mostly white space), then choose the threshold that gives you that number of black pixels.
And there are many other dithering algorithms that you can try, as well as edge detection algorithms. You can also try adjusting the contrast of the image before converting to b/w.
However, at the end of the day, when resolution is low (pixels per character), it may not be possible to easily convert them to b/w and have them still be readable (just try to fax small text on a fax machine in standard mode). Remember your resize removed a lot of information and the conversion from 8 bit to 1 bit removed another 87% of the information in the resized picture.

Form with graphics distorts

In C# i have created a function to draw a triangle between a rich-textbox and a RectangleShape object.
below is what i wrote.
Graphics Pointer = this.CreateGraphics();
Pointer.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
Pointer.FillPolygon(new SolidBrush(Color.White), GetTriangle(this.FetchRectangle));
Pointer.Dispose();
The gettriangle() function returns an array of points(3 vertices of the triangle.) But when i try running the pgm, the form's background (which is set to black color) now takes a blurred and distorted background image of wat is shown in the computer screen.
How can i get the triangle image without distorting the form background?
this problem is cause due to http://en.wikipedia.org/wiki/Vertical_blanking_interval
The solution is double buffering. and waiting Vertical retrace. I couldn't find example how to do htis but this is the way to go
see:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/9f07dec1-1b04-419c-b604-44fd74027161/windows-forms-double-buffering-?forum=csharpgeneral

Make overlapping picturebox transparent in C#.net

I have two overlapping pictureboxes.The images of both picture boxes have some transparent pixels.I want to see the bottom picture box through the transparent pixels of the overlapping picture box.
I tried setting the background color of both picture boxes as transparent.But it just sets the back color of the picture box to the background color of the form.
Clearly you are using Winforms. Yes, transparency is simulated by drawing the pixels of the Parent. Which is the form, you only see the form pixels, stacking effects don't work. There's a KB article that shows a workaround for this. It is painful. Another approach is to not use PictureBox controls but just draw the images in the form's Paint event.
Consider WPF, it has a very different rendering model that easily supports transparency.
Solutions to that problem might be various, and it mainly depends on your skills and amount of work will depend on kind of images you're dealing with. For example if images are always same resolution, size and overlapping image supports transparency you could try to do manipulation of two Image objects and draw one over another, then display it in PictureBox. Or if you will need to do it multiple times in various places of your app you could even consider creating your own UserContriol.
Code in answer of this question, method ResizeImagein particular, show how to create resized, good quality image, all you need it is to change it a little. Make it to get two Images as input parameters, and change it to draw one image over another.
Changes might look like this
public static Bitmap CombineAndResizeTwoImages(Image image1, Image image2, int width, int height)
{
//a holder for the result
Bitmap result = new Bitmap(width, height);
//use a graphics object to draw the resized image into the bitmap
using (Graphics graphics = Graphics.FromImage(result))
{
//set the resize quality modes to high quality
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//draw the images into the target bitmap
graphics.DrawImage(image1, 0, 0, result.Width, result.Height);
graphics.DrawImage(image2, 0, 0, result.Width, result.Height);
}
//return the resulting bitmap
return result;
}
And use it, for example, like this:
pictureBox1.Image = CombineAndResizeTwoImages(Image.FromFile("c:\\a.png"), Image.FromFile("c:\\b.png"), 100,100);
But that its only example, and you must tune it up to your needs.
Good luck.
If it's one PictureBox inside another, you can use:
innerPictureBox.SendToBack();
innerPictureBox.Parent = outerPictureBox;

Display filter C#

It's a little hard to explain what I need but i'll try:
I need to write application (winform) which will be some kind of filter to image/other forms behind it. With one exception - all behind form should looks as is except of red (for example) color, which have to be replaced to any other specified color, white for example.
So let's imagine I have opened windows Word with few lines of text. With red and black letters.
So when i place my application above this text - it should "filter" red symbols and fill them to white.
So as i understand this task: i have to snap area behind the form, then process it (replace colors) and after draw this image on my form body.
Any links or keywords for solution?
UPD:
so - this is my final solution:
do form transparent (using TransparencyKey and BackColor properties)
place picturebox over the form
when we need to update image in picturebox - we replace current image with pictureBox1.Image = null;, then refreshing form with (this.Refresh()) and do new snapshot
thanks for all ;-)
UPD 2:
sample http://dl.dropbox.com/u/4486681/result.png
UPD 3:
here are sources
you can create a snapshot of the desktop using the following code:
public Bitmap CaptureScreen()
{
Bitmap b = new Bitmap(SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height);
Graphics g = Graphics.FromImage(b);
g.CopyFromScreen(0, 0, 0, 0, b.Size);
g.Dispose();
return b;
}
Replace the dimensions and position with the coordinates of your form. This way you get a bitmap of what's behind your form. Then you can do the color replacement on that bitmap.
Please note that due to settings like ClearType and other anti-aliasing mechanisms, you have to also take into account "intermediate pixels" when doing the color replacement. Otherwise things will look funny :-)
I don't know if this can be done at all (let's see what others answer :-).
You can get a handle to the screen device context, which gives you a bitmap of the screen.
HDC dc = GetDC(NULL);
(This is C++, you'll have to use P/Invoke, or create a mixed-mode library in C++)
Then you can redraw a region of the screen with your filtering process.
Now the problems start:
how do you know that the pixels in your interesting region has changed ?
if the region changes, are the changes visible or are they hidden by your own drawing.
You could have a button somewhere that hides your own app momentarily and shows it back when re-pressed, and filters the new content.
Good luck. Any possibility of sharing the user scenario ?

Categories