1

I am developing an application in which user can select an image in a picture box.

After that he can right click on the image and add a user control which will again display an Image along with some text. This user control can be added any number of times.

User can also re-position the user controls as per need.

All this functionality has been implemented and is working fine.

Now, the requirement is to save the Image along with the user control.

enter image description here

Above you can see the complete image which needs to be saved. Back image is the picture box image and the user control (small images with text).

When user will click on save button the image should get saved on his disk as a single image.

This is a windows application developed in C#.

I want to know that whether this functionality can be achieved or not. If yes, then please guide me in the right direction.

Lokesh
  • 301
  • 3
  • 19
  • For future reference, below answer is correct but you can also refer : [here](http://stackoverflow.com/questions/465172/merging-two-images-in-c-net) – Lokesh Sep 11 '13 at 12:41

2 Answers2

2

If you create a copy of the bitmap then with the Graphics.DrawImage() you can draw those images onto it. You need to calculate the position of those controls.

Look here for DrawImage: http://msdn.microsoft.com/en-us/library/42807xh1.aspx

example:

Bitmap copy = new Bitmap(OriginalBitmap);

Graphics g = Graphics.FromImage(copy);

g.DrawImage(arrowBitmap, new Point(..));

copy.Save(...);
Jeroen van Langen
  • 21,446
  • 3
  • 42
  • 57
  • I have another situation regarding images. I have posted a question [here](http://stackoverflow.com/questions/19268410/set-child-image-background-when-parent-image-is-zoomed). See if you could help again. Thanks. – Lokesh Oct 09 '13 at 09:59
1

A very simple and straight forward solution exists, has been thought of by Microsoft and includes these steps:

  • Instead of PictureBox use a Panel and instead of using the Image property of the PictureBox use the BackgroundImage property of the Panel

note: By using also the BackgroundImageLayout property you can quite easily instruct the Panel to stretch, center or zoom the image (I'm presuming the default value which is tile is not a good option in your case)

  • Instead of placing the other user controls at higher Z order but alongside the previous PictureBox place them inside the Panel
  • Use the Control.DrawToBitmap method like so:

    private void button1_Click(object sender, EventArgs e) {
        var bmp = new Bitmap(this.panel1.Width, this.panel1.Height);
        this.panel1.DrawToBitmap(bmp, new Rectangle(Point.Empty, bmp.Size));
        bmp.Save(@"D:\test.png", ImageFormat.Png);
    }
    

That will result in your controls begin rendered along with the picture:

enter image description here

Furthermore, and if your scenario allows it, you could simply use the DrawToBitmap method with any control which contains all of the actors you wish to render, for instance the actual Form.

Eduard Dumitru
  • 3,242
  • 17
  • 31
  • Hey, it worked like charm. Thanks for this simple answer. Just one thing .png was giving me an error with GDI+ but when i changed to .Jpeg, it saved successfuly. Thanks again. – Lokesh Sep 11 '13 at 11:57
  • Glad to hear that. The ImageFormat is your choice.. you can go with Bmp, Jpeg, Gif.. whatever suits you. – Eduard Dumitru Sep 11 '13 at 12:00
  • Although that answer is perfect, but i have one more problem. Actually i did not mention that the user can zoom back image also. After realizing the zoom, the image saved is not complete complete. Any solution for this? – Lokesh Sep 11 '13 at 12:01
  • I think I understand... You're saying that an hour ago, no matter what the zoom level, you always got a complete picture but without the user controls. Now, you get the user controls also, but the picture is cropped because of the viewport.. ? Please confirm this is what you mean. I will think of an elegant solution. – Eduard Dumitru Sep 11 '13 at 12:29
  • I got the solution by Jeroen, drawing imges again and again will do the need full. Thanks, for your support. – Lokesh Sep 11 '13 at 12:39
  • One idea would be to replicate the entire control creation process which produces the visible viewport onto an invisible and potentially giant panel (some.. 3000x3000 pixels if necessary). The general idea would be to size that giant invisible panel accordingly: the Size of the image multiplied by the zoom level. It is easier to create `WinForms` controls and place them onto other controls than drawing everything using lines and circles and a bit of trigonometry maybe (it does not require great "gamedev" or "graphics" skills) – Eduard Dumitru Sep 11 '13 at 12:39
  • @Eduard Dumitru, I think you should use controls for gui. I like the DrawToBitmap function, but i think it useful for creating screenshot with your application. – Jeroen van Langen Sep 11 '13 at 13:12
  • @JeroenvanLangen, I totally agree with that idea of clean code which uses the tools it was designed to use to begin with. I mean: not using a hammer to solder metals together. In the beginning I thought that the asking user is looking for just that: instant screenshots nice and fast... Later on, I just became wacky and started finding ways in which to continue using the same technique for a more _vectorial_ requirement. Vectorial graphics is vectorial graphics and should be treated as such. You are correct. Besides, whatever the requirement, your solution is more extensible in the future – Eduard Dumitru Sep 11 '13 at 13:25
  • @Eduard Dumitru: I'll remember the trick for a nice and fast screenshot, didn't know that. Thanks for sharing that. – Jeroen van Langen Sep 11 '13 at 13:37
  • I'm sorry for the chatty commenting on the site. Promise to make this one my last one on the subject. It is screenshotty in nature, but if I recall correctly, it goes a bit deeper than that. It is undisturbed by floating windows above that area of the screen or if a portion or the entire area is hidden due to parent child layout or visibility. Basically you can use the Win32 API wrapped by that method and ask any HWND to render itself onto another HDC whether the 2 handles are from the same process or not (except for Service owned HDCs).It's probably the exact way the OS renders stuff. – Eduard Dumitru Sep 11 '13 at 13:46