How to merge two images in one? - c#

how can I merge canvas in one image ? I need do this because I want to save merge image.
Here is my code:
WriteableBitmap wb = new WriteableBitmap(50, 50);
wb.LoadJpeg(stream);
Image t = new Image();
t.Source = wb;
Canvas.SetLeft(t, 130);
Canvas.SetTop(t, 130);
canvas1.Children.Add(t);
So now I want to merge these two images into one and use my save function.

You can use Graphics.FromImage() and Graphics.DrawImage()
http://msdn.microsoft.com/en-us/library/system.drawing.graphics.fromimage%28v=vs.110%29.aspx
http://msdn.microsoft.com/en-us/library/42807xh1%28v=vs.110%29.aspx
// Pseudo ...
using (Graphics gfx = Graphics.FromImage(image1))
{
gfx.DrawImage(image2, new Point(0, 0));
}
// image1 is now merged with image 2

You have not specified in details what do you mean by "merge". Do you mean, overlay the images on top of each other (if that's the case, what overlay mode? add? multiply? normal?) or merge the images side by side into a larger image (like taking 3 shots with a camera and then combining them into one long photo)? Either way, you will want to look at the System.Drawing namespace.
Assuming the latter one is the case. Here's what you'll do:
Image a = ...;
Image b = ...;
//assuming equal height, and I forget whether the ctor is width first or height first
Image c = new Image(a.Width + b.Width, a.Height);
Graphics g = Graphics.FromImage(c);
g.DrawImage(...); //a lot of overloads, better check out the documentation
SaveImage(c); //depending on how you want to save it
g.Dispose();

You need a third-party library, like WriteableBitmapEx. Look at the Blit method.

Related

How to make a listBox semi-transparent?

I tried looking through a few questions on here already but none seemed to fit.
This is what i've tried:
listBox1.BackColor = Color.FromArgb(85, 200, 200, 200);
But at runtime, there's an error. It states that the component doesn't support transparency. I'm asking on here because there could be a workaround. If anyone could help, that'd be great. Thanks in advance!
I suggest going for a ListView in Details View instead.
This is a more modern control, much more powerful and also more supportive when it comes to adding some extra styling..
ListView has a BackgroundImage which alone may be good enough. It doesn't support transparency, though.
But with a few tricks you can make it fake it by copying the background that would shine through..:
void setLVBack(ListView lv)
{
int alpha = 64;
Point p1 = lv.Parent.PointToScreen(lv.Location);
Point p2 = lv.PointToScreen(Point.Empty);
p2.Offset(-p1.X, -p1.Y );
if (lv.BackgroundImage != null) lv.BackgroundImage.Dispose();
lv.Hide();
Bitmap bmp = new Bitmap(lv.Parent.Width, lv.Parent.Height);
lv.Parent.DrawToBitmap(bmp, lv.Parent.ClientRectangle);
Rectangle r = lv.Bounds;
r.Offset(p2.X, p2.Y);
bmp = bmp.Clone(r, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(bmp))
using (SolidBrush br = new SolidBrush(Color.FromArgb(alpha, lv.BackColor)))
{
g.FillRectangle(br, lv.ClientRectangle);
}
lv.BackgroundImage = bmp;
lv.Show();
}
A few notes:
I hide the listview for a short moment while getting the background pixels
I calculate an offset to allow borders; one could (and maybe should?) also use SystemInformation.Border3DSize.Height etc..
I crop the right area using a bitmap.Clone overload
finally I paint over the image with the background color of the LV, green in my case
you can set the alpha to control how much I paint over the image
Also note that I dispose of any previous image, so you can repeat the call when necessary, e.g. when sizes or positions change or the background etc..
The ListView overlaps a PictureBox (left) but sits on a TabPage with an image of its own.
Result:

how to remove a section of image and move below part up in C#

I have a image in which i have the rectangle dimension of its which is needed to be removed from the image, how i can do that using the image processing library available in C#, or you have any kind of reference for this requirement please let me know and help me
i am attaching the image for the problem statement.
i have A image and i want B image after processing, how can i do that please help me.
thanks in advance
I would suggest to use the Graphics Object and The Bitmap class.
Load your source Bitmap into Memory.
Create a new Bitmap with the right height
Create Graphics instances from both of your Bitmaps https://msdn.microsoft.com/de-de/library/system.drawing.graphics.fromimage(v=vs.110).aspx
Draw the source Bitmap to the destination Bitmap https://msdn.microsoft.com/de-de/library/558kfzex(v=vs.110).aspx
Draw a filled Rectangle with Color.Transparent to the source Bitmap. It must be located at 0/0 and must have the size x4/y4. https://msdn.microsoft.com/de-de/library/c6ksfcek(v=vs.110).aspx
Draw the source bitmap to the destination picture again, but this time you locate it at 0/-(y3-y1)
Finally save the Bitmap to a file again or do whatever you want to do with it.
An important setting for this approch is the Graphics.ComposingMode. For the first draw to the destination and the source bitmap it must be set to SourceCopy. For the second draw to the destination it must be set to SourceOver. https://msdn.microsoft.com/de-de/library/system.drawing.drawing2d.compositingmode(v=vs.110).aspx
Additionally both bitmaps must have a pixelFormat with Alpha channel e.g. Format32bppArgb https://msdn.microsoft.com/de-de/library/system.drawing.imaging.pixelformat(v=vs.110).aspx
So what am I doing:
Im drawing the big picture into the small one. The bottom part is cropped.
I make the upper part transparent and draw the picture with a negative y coordinate to the destination. By this the bottom part of the picture is pasted over the remaining visible part from the first draw.
If you have any problem with this introduction, feel free to ask.
EDIT: I felt like trying myself... Here's the working code:
int cropFromY = 240;
int cropToY = 334;
// Change location if required...
using (FileStream fs = new FileStream(#"D:\Test\pic.png", FileMode.Open, FileAccess.Read))
{
// Step 1
// load Bitmap from File
var loadedBitmap = new Bitmap(fs);
// Step 1 (extended)
// As the loadedBitmap might have a wrong PixelFormat, we convert it to have an Alpha channel
var source = new Bitmap(loadedBitmap.Width, loadedBitmap.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (Graphics gSource = Graphics.FromImage(source))
{
gSource.DrawImageUnscaled(loadedBitmap, 0, 0);
}
// Step 2
// Create destination Picture
var destination = new Bitmap(source.Width, source.Height - (cropToY - cropFromY), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
// Step 3
// Create the two graphics objects
using (Graphics gSource = Graphics.FromImage(source))
{
using (Graphics gDestination = Graphics.FromImage(destination))
{
// Step 4
// Copy picture source to destination => Crop Bottom
gDestination.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
gDestination.DrawImageUnscaled(source, 0, 0);
// Step 5
// Make the top part (which is already drawn to the destination) transparent
gSource.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
gSource.FillRectangle(Brushes.Transparent, new Rectangle(0, 0, source.Width, cropToY));
// Step 6
// Draw the source bitmap to the destination picture again, but this time you locate it at 0/-(y3-y1)
gDestination.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
gDestination.DrawImageUnscaled(source, 0, -(cropToY - cropFromY));
// Step 7
// Save new picture. Change location if required...
destination.Save(#"D:\Test\pic2.png");
}
}
}
Original:
Resulting picture:
Cheers Thomas

How can you copy part of a writeablebitmap to another writeablebitmap?

How would you copy a part from one WriteableBitmap to another WriteableBitmap? I've written and used dozens of 'copypixel' and transparent copies in the past, but I can't seem to find the equivalent for WPF C#.
This is either the most difficult question in the world or the easiest because absolutely nobody is touching it with a ten foot pole.
Use WriteableBitmapEx from http://writeablebitmapex.codeplex.com/
Then use the Blit method as below.
private WriteableBitmap bSave;
private WriteableBitmap bBase;
private void test()
{
bSave = BitmapFactory.New(200, 200); //your destination
bBase = BitmapFactory.New(200, 200); //your source
//here paint something on either bitmap.
Rect rec = new Rect(0, 0, 199, 199);
using (bSave.GetBitmapContext())
{
using (bBase.GetBitmapContext())
{
bSave.Blit(rec, bBase, rec, WriteableBitmapExtensions.BlendMode.Additive);
}
}
}
you can use BlendMode.None for higher performance if you don't need to preserve any information in your destination. When using Additive you get alpha compositing between source and destination.
There does not appear to be a way to copy directly from one to another but you can do it in two steps using an array and CopyPixels to get them out of one and then WritePixels to get them into another.
I agree with Guy above that the easiest method is to simply use the WriteableBitmapEx library; however, the Blit function is for compositing a foreground and background image. The most efficient method to copy a part of one WriteableBitmap to another WriteableBitmap would be to use the Crop function:
var DstImg = SrcImg.Crop(new Rect(...));
Note that your SrcImg WriteableBitmap must be in the Pbgra32 format to be operated on by the WriteableBitmapEx library. If your bitmap isn't in this form, then you can easily convert it before cropping:
var tmp = BitmapFactory.ConvertToPbgra32Format(SrcImg);
var DstImg = tmp.Crop(new Rect(...));
public static void CopyPixelsTo(this BitmapSource sourceImage, Int32Rect sourceRoi, WriteableBitmap destinationImage, Int32Rect destinationRoi)
{
var croppedBitmap = new CroppedBitmap(sourceImage, sourceRoi);
int stride = croppedBitmap.PixelWidth * (croppedBitmap.Format.BitsPerPixel / 8);
var data = new byte[stride * croppedBitmap.PixelHeight];
// Is it possible to Copy directly from the sourceImage into the destinationImage?
croppedBitmap.CopyPixels(data, stride, 0);
destinationImage.WritePixels(destinationRoi,data,stride,0);
}

C# graphics displays the image larger than normal?

I am trying to merge two images using C Sharp's System.Drawing.Graphics.
Here is my code:
Point p = new Point(Convert.ToInt32(OffsetX), Convert.ToInt32(OffsetY));
Image i = Image.FromFile("1.jpg");
Image toDraw = Image.FromFile("2.jpg");
using (Graphics g = Graphics.FromImage(i))
{
g.DrawImage(toDraw, p);
g.Save();
Directory.CreateDirectory(Path.Combine(Directory.GetCurrentDirectory(), "saved"));
i.Save(Path.Combine("saved", "saved1.jpg"));
}
The code works fine, but the second image is enlarged in the output from the program.
Made with Paint:
Made with code above:
Use the Graphics.DrawImage(Image, Rectangle) overload to control the size of the image. The overload you are using takes note of the Image.HorizontalResolution and VerticalResolution properties to ensure that the drawn image is (roughly) as large in inches as it was when it was created. Fix:
g.DrawImage(toDraw, new Rectangle(p, new Size(i.Width, i.Height)));

How can I replace an existing image on a winforms ImageList?

How can I replace an existing image on a winforms ImageList?
I tried this:
this.CoolPics.Images [ 2 ] = // new image
this.ListViewControl.SmallImageList = this.CoolPics;
However the new image is not rescaled the way the others are, when I used the this.CoolPics.Images.Add method.
What am I doing wrong?
I know this is old but here is how I solved the problem. It looks like the image list will not resize the image upon assignment (even though it does when using the Add() function). So basically, you need to resize the image manually before assigning.
Image img; //used to load new image from disk
Bitmap bmp = new Bitmap(160, 120); //canvas where the new image will be drawn/resized
Graphics graph = Graphics.FromImage(bmp); //used to draw/resize the new image
img = new Bitmap(fileDialog.FileNames[0]); //load new image from disk
graph.DrawImage(img, new Rectangle(0, 0, 160, 120)); //resize new image to proper size
imgList.Images[index] = bmp; //assign the new resized image to the list (overwrites the old image)
after your code try
listView1.Refresh();
I have run into this before and if I remember right the assignment operator had this behavior but the Imagelist.Images.Add(myImage) did the right thing.
Try changing your code to do the .Add(myImage) and see if that doesn't look better.

Categories

Resources