Draw 2 pictureboxes in one bitmap - c#

I'm a c# beginner and I'm wondering if there is a way that I could draw 2 images from 2 different pictureboxes and save it as a one image using the method DrawToBitmap.
I can preview everything nice in the program itself (it looks good), but the main problem is when I save the picture, It's just showing the picturebox1 with a blank-alike icon of the picturebox2 in the middle :/
Here's the part of my code and it's not working as it should
pictureBox2.ImageLocation = potDoSlike;
Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
pictureBox1.DrawToBitmap(bmp, pictureBox1.Bounds);
pictureBox2.DrawToBitmap(bmp, pictureBox2.Bounds);
bmp.Save(#"D:\asd.jpg");

I figured it out! The problem was that I didn't save anything to the pictureBox.Image and it couldn't draw nothing out... well here's the code!
pictureBox2.Parent = pictureBox1;
pictureBox2.ImageLocation = potDoSlike;
pictureBox2.Image = Image.FromFile(potDoSlike);
Bitmap bmp = new Bitmap(pictureBox1.Image);
pictureBox1.DrawToBitmap(bmp, pictureBox1.Bounds);
pictureBox2.DrawToBitmap(bmp, pictureBox2.Bounds);
bmp.Save(#"D:\asd.jpg");

Related

C# GDI+ ScaleTransform ok on picturebox but image saved is original

Hi I have the issue that when I use ScaleTransform(zoomFactor,zoomFactor) the image saved on disk is the original version always, while on screen in the picturebox the image is distorted in proportion to the zoomFactor.
Why this could be happening ? Shouldn't I have the final result as applied from e.Graphics on disk written image ?
My code is the following which is a version with matrix. but the instead of matrix I have used the ScaleTransform as well. Result is always the same:
g=e.Graphics;//inside picturebox_paint()
g.ScaleTransform(ratio * zoomFac, ratio * zoomFac);
e.Graphics.DrawImage((Bitmap)bmp, 0, 0);
int seed = Convert.ToInt32(Regex.Match(Guid.NewGuid().ToString(), #"\d+").Value);
String destinationFile = #"C:\tmp\photoid\" + new Random(seed).Next() + "_conv.jpg";
//Here I get always the original image back!!!!
bmp.Save(destinationFile);
I have used as well the following idiom but with same results:
//Matrix matrix = new Matrix();
//matrix.Scale(zoomFac, zoomFac);
//e.Graphics.Transform = matrix;
You need to make the PictureBox draw the things it shows on screen into a new Bitmap, which you then can save!
As it is the Image will be saved in the original form and nothing you did in the Paint event, which actually painst onto the surface of the PictureBox will be saved.
So to save everything, i.e. The Image, possibly a BackgroundImage and all you draw in the Paint event you would call DrawToBitmap somehwere.
Somewhere means somewhere else, not in the Paint event, as it will call the Paint event to create the new Bitmap, causing an endless loop..
To call it you would do something like this:
Bitmap bmpSave = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
pictureBox1.DrawToBitmap(bmpSave, pictureBox1.ClientRectangle);
But maybe this is not really what you want? Maybe you actually want to modify the Image? In that case do not use the Paint event at all!
Instead do something like this:
Bitmap bmpSave = new Bitmap(yourNewWidth, yourNewHeight);
using (Graphics g = Graphics.FromImage(bmpSave))
{
g.ScaleTransform(ratio * zoomFac, ratio * zoomFac);
g.DrawImage((Bitmap)pictureBox1.Image, 0, 0); //
pictureBox1.Image = bmpSave;
bmpSave.Save(...);
}
You could call this from somewhere where the scaling is being triggered from.
Note that doing the scaling repeatedly and each time from the previoulsy scaled version will degrade the quality rather fast. For this always scale from a saved version of the original!!
Btw: Using a Matrix for scaling doesn't really make a difference over ScaleTransform.
But if you want to do a direct scaling why not use the DrawImage overload which takes two Rectangles? This is the most common solution if all you want to to scale and maybe draw other stuff additionally..:
int newWidth = 100; int newHeight = 100; string yourFileName = "D:\\xyz123.jpg";
Bitmap bmpSave = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
Rectangle newRectangle = new Rectangle(0, 0, newWidth, newHeight);
Rectangle oldRectangle = new Rectangle(Point.Empty, pictureBox1.Image.Size);
using (Graphics g = Graphics.FromImage(bmpSave))
{
g.DrawImage((Bitmap)pictureBox1.Image, newRectangle, oldRectangle, GraphicsUnit.Pixel);
bmpSave.Save(yourFileName, ImageFormat.Jpeg);
}
And there there is the scaling Bitmap constructor:
Bitmap bmp = new Bitmap(pictureBox1.Image, newWidth, newHeight);
Which I would recommend if all you want is to scale the Image. As the other solutions it will not change the Image displayed until you assign it back into the PictureBox..:
pictureBox1.Image = bmp ;
Don't forget to dispose of the old Image..
Been a while since I messed with GDI but I think you need to copy back to the Bitmap here.
g.DrawImage(bmp, scaledwidth, scaledheight);
Try something like that before bmp.Save
Edit
Apologies for not seeing that you were copying back to the bitmap. Perhaps the overload which specifies the output rectangle is what you need. Try a DrawImage overload which has the destination Rect. https://msdn.microsoft.com/en-us/library/ms142040(v=vs.110).aspx

Rotate Image using RotateFlip in C#

I have this code to rotate an image in an if loop in C# Windows Form application, but the Form does not show anything in the form output.
Can anyone help?
this.splitContainer1.Panel2.Controls.Add(PictureBox1);
PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
PictureBox1.Image = bitmap; //Image.FromFile(#"C:\image.jpg");
PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
PictureBox1.Image = (Image)(RotateImg(bitmap, 30.0f, Color.Transparent));
if you need to rotate an image on common angles you can use RotateFlip method with ease.
Please see my sample code:
string fileName = "somefile.png";
System.Drawing.Imaging.ImageFormat imageFormat = System.Drawing.Imaging.ImageFormat.Png;
Bitmap bitmap =(Bitmap)Bitmap.FromFile(fileName );
//this will rotate image to the left...
bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
//lets save result back to file...
bitmap.Save(fileName, imageFormat);
bitmap.Dispose();
That's all, hope it helps.
Try this:
PictureBox1.Images.RotateFlip(RotateFlipType.Rotate180FlipX);
PictureBox1.Refresh();

CopyFromScreen not working

This one is slightly confusing...
I am using Adobe's PDF Viewer control to view PDFs but I want the user to be able to drag an image onto the PDF and then when they click save it adds the image to the PDF at that location.
Implementing the PDF viewer proved quite difficult but I decided in the end to use Adobe's control, take a picture and then allow the user to draw the image ontop of the picture of the PDF. When they click save I am going to use PDFSharp to put the image onto the PDF once I've worked out where it goes but the problem I have at the moment is that I can't get a picture of the PDF.
The following code is used to get the picture but the Panel that it is attached to just appears with a white background with a red 'X' and border...
using (Bitmap bitmap = new Bitmap(adobePDFViewer1.Width, adobePDFViewer1.Height))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(new Point(adobePDFViewer1.Left, adobePDFViewer1.Top), Point.Empty, adobePDFViewer1.Size);
}
panelOverPdfViewer.BackgroundImage = bitmap;
}
I don't think this is the best way of doing it but I couldn't work out any others. Any help would be appreciated!
EDIT:
Following a very helpful answer below this is working code:
Here is the code I used:
Bitmap printscreen = new Bitmap(adobePDFViewer1.Width, adobePDFViewer1.Height);
Graphics graphics = Graphics.FromImage(printscreen as Image);
int left = this.Left + 396;
int top = this.Top + 30;
graphics.CopyFromScreen(left, top, 0, 0, printscreen.Size);
pictureBoxOverPDFView.Image = printscreen;
Look at this this Print-Screen
and try this for test work of CopyFromScreen
private void PrintScreen()
{
Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics graphics = Graphics.FromImage(printscreen as Image);
graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size);
printscreen.Save(#"C:\Temp\printscreen.jpg", ImageFormat.Jpeg);
}

Don't scale image when creating new bitmap from existing image

Does anyone know how to create a new bitmap from an existing image with a taller height, but don't scale the image and just have transparent, black or white below the original image in the new bitmap?
I basically have one picture that is taller than the second and I need the second one to be as tall as the first, without stretching it.
img2 = new Bitmap(lImages[2],new Size(pictureBox.Image.Width,pictureBox.Image.Height));
img2 = ((Bitmap)img2).Clone(new Rectangle(0, 0, pictureBox.Image.Width, pictureBox.Image.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
C# .NET 4.0.
By using a Graphics object, you can achieve this easily:
Bitmap temp = new Bitmap(new Size(pictureBox.Image.Width,pictureBox.Image.Height));
using(Graphics g = Graphics.FromImage(temp))
{
g.DrawImage(img2, 0, 0);
}
img2 = temp;
Now img2 references a new Bitmap object of the required size which has the original (unstretched) image painted on it.
Note: To control the color of the extra space, add a call to g.FillRect before drawing the image.
Create your "standart" size bitmap and fill it with, let's say, white color and call Bitmap.MakeTransparent(Color.White) and draw your final image over it.

List view control displaying distorted images

I have a problem with the ListView control in a windows forms application.
Even if I create a thumbnail image or resize the real one I get distorted images in the list view.
The image looks like when you zoom in an image very much.
I first thought that the GetThumbnailImage is couseing this but I used a resize code I found here and I have the same result.
I also did not found any bug related to list view control so I gues I'm doing something wrong but I just can't figure out what.
Here is the code I use:
lsvPictures.LargeImageList = m_imagesList;
lsvPictures.LargeImageList.ImageSize = new Size(100, 100);
lsvPictures.View = View.LargeIcon;
lsvPictures.CheckBoxes = true;
for (int i = 0; i < ofd.FileNames.Length; i++)
{
filename = ofd.FileNames[i].ToString();
ListViewItem lvi = new ListViewItem(filename);
m_imagesList.Images.Add(ResizeImage(Image.FromFile(filename), 100, 100));
lvi.ImageIndex = i;
lsvPictures.Items.Add(lvi);
}
And this is the function that resizes images:
public static System.Drawing.Bitmap ResizeImage(System.Drawing.Image image,
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 image into the target bitmap
graphics.DrawImage(image, 0, 0, result.Width, result.Height);
}
//return the resulting bitmap
return result;
}
Thank you!
Mosu'
I just found the source of the problems:
m_imagesList.ColorDepth = ColorDepth.Depth16Bit;
It seams that, as default, the ColorDepth of the ImageList is 8 bit (or 4 bit, but my guess is 8). If I change this to at least 16 bit everything looks very nice.
To those with similar problems: I changed my Thumbnail method a lot before I realised that the ListView control is not using the color depth the images were having. I put the result of my method on a PictureBox control and saw that the function was working corectly. Atfer this I googled a lot ... and found that silly ColorDepth property.
How did you set the resolution for your image. Also, did what did you set the PixelFormat value to when you created the bitmap? I have a list of images loading into my list view that I am resizing similar to how you are and it is working fine without any distortion in the resulting thumbnail images that are created.
Here is a snippet from my resize method.
Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
bitmap.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.Clear(Color.Red);
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.DrawImage(image,
new Rectangle(destinationX, destinationY, destinationWidth, destinationHeight),
new Rectangle(sourceX, sourceY, originalWidth, originalHeight),
GraphicsUnit.Pixel);
}
return bitmap;
I was also using a ListView in WinForms to display directories, and had the same problem. I suggest that you check the image file type: icon files (.ico) tend to end up distorted, so try to use an image file with the .png extension. This works for me:
ListView listView = new ListView();
ImageList imageList = new ImageList();
// add image to list:
imageList.Images.Add("image_key", image_path);
// give the listview the imagelist:
listView.SmallImageList = imageList;
// add item to listview:
listView.Items.Add("item_text", "image_key");

Categories