c# rotate embedded image - c#

I have an image that load a .PNG file and then combines it with other graphics I create. The thing is that I need to rotate only the .PNG file, not the whole thing. Picture a speedometer, you have a background image that goes from 0 to 200. That image remains static all the time. Now, on top of it, you have an arrow pointing to your current speed. That's the one I want to rotate.
This is what I have so far. It does display the graphics, but doesn't rotate the .PNG (the arrow)
Bitmap bitmap = new Bitmap(500, 280, PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(bitmap);
g.Clear(Color.White);
//this.Arrow = path to the .PNG
Image i = Image.FromFile(this.Arrow);
Bitmap a = new Bitmap(i.Width, i.Height);
Graphics ga = Graphics.FromImage(a);
a.SetResolution(ga.DpiX, ga.DpiY);
//It shouldn't rotate having the pivot at the (centre, centre)
//coordinates, but at the bottom of the image.
//The (21, 110) coordinates are right relative to the .PNG file
ga.TranslateTransform(21, 110);
ga.RotateTransform(45); //<--- Not rotating
ga.DrawImage(i, 0, 0);
g.DrawImage(i, new Rectangle(new Point(229, 120), new Size(i.Width, i.Height)));
g.DrawLine(new Pen(new SolidBrush(Color.Aquamarine), 1), 250, 0, 250, 280);
g.DrawLine(new Pen(new SolidBrush(Color.Aquamarine), 1), 0, 230, 500, 230);
Any ideas?

Without a good, minimal, complete code example that reliably reproduces the problem, it is impossible to know for sure what the problem is. There are several possible problems in the code you posted; the most obvious being that you are drawing the image i into the Graphics object g, rather than the image a into which you've drawn i at a 45-degree rotation.
You will likely get results closer to that desired if you change that program statement to this:
g.DrawImage(a, new Rectangle(new Point(229, 120), new Size(a.Width, a.Height)));
Other issues include:
Failing to dispose ga and g when done with them
Failing to translate ga back to the desired location after the rotation (i.e. you translate to get the rotation of the image to happen around the point (21, 110) of the image, but have left the image translated by that amount after the rotation, which may not be what you want
Using positive offsets for the previously-mentioned translation
Because of these issues (and possibly others), I don't think the above change will result in exactly the desired output, but at least you will see some evidence of rotation.
While your error does not seem to be that which I've addressed in my answer to the question commenter Keith M mentioned, I do think you would benefit from reading the code example there, as it does basically the same thing you are trying to do here.

Related

How to detect object by color with openCV

I have to make a macros, it should detect object by color on the certain area on the picture of the screen. Further, I need to continue execute code if object has been detected.
Image<Bgr, Byte> imgWindowScreen;
Image<Gray, Byte> imgWindowScreenProcessed;
Bitmap bmpScreenshot;
System.Drawing.Graphics gfxScreenshot;
Size size = new Size(400, 120);
bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height,
PixelFormat.Format32bppArgb);
gfxScreenshot = Graphics.FromImage(bmpScreenshot);
gfxScreenshot.CopyFromScreen(700, 347, 0, 0, size);
imgWindowScreen = new Image<Bgr, Byte>(bmpScreenshot);
imgWindowScreenProcessed = imgWindowScreen.InRange(new Bgr(3, 25, 82),
new Bgr(50, 98, 200));
Is it right I have choosen the area? I have a upper left point and I need to get something like that:
How to define that imgWindowScreenProcessed has a pixels of searched color? I need to build a following structure:
if (picture has pixels of searched color) {...}
else {...}
Here you may find the Python implementation of HSV thresholding. I understand that you need it on another language, however you might get some insights on logic of the implementation as it shows a simple case. Here you can find a deeper C++ implementation
After you have obtained the binary image, where pixels of desired color are 1 and other pixels are 0, you may play with morphology to enhance the image here, and get proper regions of interest.
Then, when you have an in image you may want to see the location of the object. You may use findContours() function to get the location of the object.
I usually do work with OpenCV in Python, but hope that this may also be helpful! :)

Remove a round transparent section of an Image c#

I am creating an Circle on a bitmap but want to have a hole in it. After serching for half an hour I only found ways to crop an image to a circle. The hard thing is, that the hole in the middle should be transparent as the rest of the Image.
This is the base image and the yellow circle represents the transparent area that should be added.
Thanks for any kind of help.
The start is simple: Create a transparent bitmap by doing a g.Clear(Color.Transparent) and then draw/fill a circle in a color.
The next step is a bit trickier: You next want to paint the hole with transparency.
To do so you need to switch the Graphics object to the right CompositingMode; default is SourceOver but you want SourceCopy. The former overlays the alpha values creating mixed colors. The latter will do what we want: Draw the hole by copying the drawn colors including alpha right over the old ones..
Here is an example:
Bitmap bmp = new Bitmap(500, 500);
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.Transparent);
//g.SmoothingMode = SmoothingMode.AntiAlias;
g.CompositingMode = CompositingMode.SourceCopy;
g.FillEllipse(Brushes.DarkGreen, 100, 100, 300, 300);
g.FillEllipse(Brushes.Transparent, 200, 200, 100, 100);
}
pictureBox1.Image = bmp;
This is what is looks like in a PictureBox with a BackgroundImage:
A few notes:
You can also use a semi-transparent brush to create a 'tinted' hole; do not use anti-aliasing for this though, as it would introduce colored fringes.
We used simple circles here but with a GraphicsPath you can create and fill shapes of almost any shape and complexity..
And using a GraphicsPath would also have been an alternative to filling with transparency: By first adding the large and then the smaller, inner ellipse the path would have been created with a hole and filling it would have had the very same result! But I found the solution above more instructive..
Final note: As clarkitect noted, to save, do use a format that supports transparency. Png is always recommended..

PDFsharp - Image drawn with transparency

I am currently working on a PDF generator. I need to first draw the background image and then draw a dark layer with 85 percent of transparency. I can draw it nicely, but when I want to draw two images after that, those images also get the transparency and that is not what I want.
XBrush brush = new XSolidBrush(XColor.FromArgb((int)(.85 * 255), 255, 255, 255));
DrawPageBackground(gfx,backgroundImage,page.Width.Value,page.Height.Value);
gfx.DrawRectangle(b,0,0,gfx.PageSize.Width,gfx.PageSize.Height );
gfx.DrawImage(otherImage,25,25);
Is there any reason why I can't just draw the images without the transparency? Is it just something simple that I am not doing right now?
Thanks.
I did successfully fix this issue by saving the XGraphicsState before the drawing of the background with darkened layer. After the drawing I used the XGraphicsState to restore and draw the images without any transparency. See the following piece of code.
XGraphicsState state = gfx.Save();
XBrush brush = new XSolidBrush(XColor.FromArgb((int)(.85 * 255), 255, 255, 255));
DrawPageBackground(gfx,backgroundImage,page.Width.Value,page.Height.Value);
gfx.DrawRectangle(b,0,0,gfx.PageSize.Width,gfx.PageSize.Height );
gfx.DrawImage(otherImage,25,25);
gfx.Restore(state);
The method DrawPageBackground:
private static void DrawPageBackground(XGraphics gfx, XImage image, double pageWidth, double pageHeight)
{
if (image.Size.Width > pageWidth)
gfx.DrawImage(image, CalculateDiffImageCenterToPageCenter(image,pageWidth), 0, CalculateBackgroundImageWidth(image,pageHeight), pageHeight);
else
gfx.DrawImage(image, 0, 0, CalculateBackgroundImageWidth(image, pageHeight),pageHeight);
}
This is just an helper method to draw the background image to the right scale and center it.
I confirm what I wrote in a comment: it is a bug that the transparency set for a brush was also applied to the images.
With version 1.50.3915-beta2 published earlier this week, this bug was fixed.
Using Save() and Restore() is a suitable workaround for earlier versions, but with the latest version this workaround is no longer needed.

Why is Graphics.DrawImage cropping part of my image?

If you consider the following image, it's a fairly basic icon, sized at 32x32. Around the icon is a transparent rectangle, although I filled in the four corners with a solid colour while testing.
Now consider this code, which simply draws the image, but at a larger scale:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
e.Graphics.DrawImage(Properties.Resources.icon_32a, new RectangleF(0, 0, 512, 512), new RectangleF(0, 0, 32, 32), GraphicsUnit.Pixel);
}
Note that I'm drawing the full image and I'm not attempting to crop it in any way, just enlarge it.
Finally, this is the output the test gives me:
Notice the problem? Half of the pixels in the top row and left column have vanished. If I then try and overlay a grid on top of this, it looks pretty awful as the grid is correctly aligned, but the image is not. Even just doubling the size to 64, 64 introduces this first row/column crop.
Note, I also tried offset the destination rectangle just in case it was drawing before 0,0, but this was not the case.
I also tried using different interpolation modes, but as far as I could tell through the headache inducing blur, the pixels were still cropped, so I don't believe it's due to the interpolation mode.
I also attempted using different graphics modes, but aside from the fact that it didn't seem to help, I need to stick with pixels anyway.
I tried again with a new copy of the image at 96dpi out of curiosity and got the same effect so I don't think it's the resolution of the source images.
Clutching at straws and using Rectangle instead of RectangleF also had no effect.
Can anyone offer any clues as to why this apparent crop is occurring?
Thanks;
The PixelOffsetMode is set by default to PixelOffsetMode.Half:
Specifies that pixels are offset by -.5 units, both horizontally and
vertically, for high speed antialiasing.
In your case half a pixel in the original image is 8 pixels in the resulting image, which is exactly what you are missing.
Try setting it to PixelOffsetMode.None PixelOffsetMode.HighQuality:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
e.Graphics.DrawImage(Properties.Resources.icon_32a, new RectangleF(0, 0, 512, 512), new RectangleF(0, 0, 32, 32), GraphicsUnit.Pixel);
}
Just covering reply comfirmed by users, I tried it myself and the problem was solved with PixelOffsetMode.HighQuality instead none.
c#
e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
my case c++ managed:
e->graphics->PixelOffsetMode = System::Drawing::Drawing2D::PixelOffsetMode::HighQuality;

Efficient Zoom At C#

To zoom images in and out, there is a possible way to resize the pictureBox and showing image in strechmode. Although I can not use it efficiently becauce in general over 8x it gives storage error [think that a pictureBox has the Size(32k, 32k) it needs over 1GB memory !
Is there a special method, or should I zoom only the seen part of the image by using ImageClone ?
Update:
Here is the project at first try to zoom at the project [impossible, storage error] than delete the 41. line in form.cs :
pictureBox1.Image = youPicture;
After deleting this line, the program will work, please move the zoomed image.
Here is the link: http://rapidshare.com/files/265835370/zoomMatrix.rar.html
By using the matrix object and the transform property of your graphics object:
using(Graphics g = this.CreateGraphics())
{
using(Bitmap youPicture = new Bitmap(yourPictureFile))
{
g.DrawImage(youPicture, 0, 0, 300, 100); //set the desired size
//Now you need to create a matrix object to apply transformation on your graphic
Matrix mat = new Matrix();
mat.Scale(1.5f, 1.5f, MatrixOrder.Append); //zoom to 150%
g.Transform = mat;
g.DrawImage(youPicture, new Rectangle(...), 0, 0, youPicture.Width,
youPicture.Height, GraphicsUnit.Pixel) ;
}
}
I personally would just zoom the visible part as the rest is hidden anyway (and thus no use)
See this answer to an earlier question. You definitely don't want to zoom by making the image huge and showing only part of it - you'll run into the memory problem that you've already encountered. Also, the stretch mode of a picture box doesn't use high-quality interpolation, so the result will look pretty crappy.
In the answer I linked here, I included a link to a C# project that shows you how to do this kind of zooming.
Update: here is a direct link to the downloadable project.

Categories

Resources