I want to merge two pictures in my C# program.
the first one is any picture in grayscale mode, and the second one is like in this picture:
Both of the pictures/images have the same size, and this is my code:
Bitmap first = new Bitmap (picturebox1.image);
Bitmap second = new Bitmap (picturebox2.image);
Bitmap result = new Bitmap (first.width, first.height);
Graphics g = Graphics.FromImage(result);
g.DrawImageUnscaled(first, 0, 0);
g.Flush();
g.DrawImageUnscaled(second, 0, 0);
g.Flush();
picturebox3.image = result;
I can join those picture, but the result has smaller size than the two originals (both pictures have same size). Could anyone give me some suggestions?
Additionally, I want the result picture has condition like this :
if the edge pixel in 2nd picture dropped to the bright side at the 1st one, it will be dark, otherwise when the edge dropped to the dark side, it will be bright (seem glow).
so the text will be semi transparent.
Here's an example of the results I want.
Could anyone give some suggestions please?
It was for joining
Bitmap first = new Bitmap (picturebox1.Image);
Bitmap second = new Bitmap (picturebox2.Image);
Bitmap result = new Bitmap (first.Width+first.Width, first.Height);
Graphics g = Graphics.FromImage(result);
g.DrawImageUnscaled(first, 0, 0);
g.DrawImageUnscaled(second,first.Width, 0);
Try this for merging one on top another . set alpha by yourself ( red: U can use BitMap.MakeTransParent if u not want alpha)
public Bitmap SetImageOpacity(Image image, float opacity)
{
try
{
//create a Bitmap the size of the image provided
Bitmap bmp = new Bitmap(image.Width, image.Height);
//create a graphics object from the image
using (Graphics gfx = Graphics.FromImage(bmp))
{
//create a color matrix object
ColorMatrix matrix = new ColorMatrix();
//set the opacity
matrix.Matrix33 = opacity;
//create image attributes
ImageAttributes attributes = new ImageAttributes();
//set the color(opacity) of the image
attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
//now draw the image
gfx.DrawImage(image, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
}
return bmp;
}
catch (Exception ex)
{
return null;
}
}
private void button1_Click(object sender, EventArgs e)
{
Bitmap first = new Bitmap(pictureBox1.Image);
Bitmap second = SetImageOpacity(pictureBox2.Image, 0.5f);
//Bitmap result = new Bitmap(first.Width, first.Height);
//fix :
Bitmap result = new Bitmap(Math.Max(first.Width,second.Width), Math.Max(first.Height,second.Height));
Console.WriteLine(first.Width);
Graphics g = Graphics.FromImage(result);
g.DrawImageUnscaled(first, 0, 0);
g.DrawImageUnscaled(second, 0, 0);
pictureBox3.Image = result;
result.Save("result.jpg" );
}
}
}
And Coming For watermark why not you want to use Drawstring with alpha
here is article for all these http://www.codeproject.com/Articles/5034/How-to-implement-Alpha-blending
You need to include the System.Drawing.Imaging namespace to make this code work.
Go through following code:
private void CombineImages(FileInfo[] files)
{
//change the location to store the final image.
string finalImage = #"C:\\MyImages\\FinalImage.jpg";
List imageHeights = new List();
int nIndex = 0;
int width = 0;
foreach (FileInfo file in files)
{
Image img = Image.FromFile(file.FullName);
imageHeights.Add(img.Height);
width += img.Width;
img.Dispose();
}
imageHeights.Sort();
int height = imageHeights[imageHeights.Count - 1];
Bitmap img3 = new Bitmap(width, height);
Graphics g = Graphics.FromImage(img3);
g.Clear(SystemColors.AppWorkspace);
foreach (FileInfo file in files)
{
Image img = Image.FromFile(file.FullName);
if (nIndex == 0)
{
g.DrawImage(img, new Point(0, 0));
nIndex++;
width = img.Width;
}
else
{
g.DrawImage(img, new Point(width, 0));
width += img.Width;
}
img.Dispose();
}
g.Dispose();
img3.Save(finalImage, System.Drawing.Imaging.ImageFormat.Jpeg);
img3.Dispose();
imageLocation.Image = Image.FromFile(finalImage);
}
Follow Link:
http://www.niteshluharuka.com/2012/08/combine-several-images-to-form-a-single-image-using-c/
This codeproject article shows how to watermark an image with text as well as another image.
In summary, what you have to do is draw your watermark image over the image with the desired transparency.
Related
I have a Windows Forms application that takes a screenshot of a specific portion of the screen, then displays it in a picture box (pictureBox1). It works when I don't try to convert it, but I want to convert the image to grayscale or black and white. The problem is when I convert it to grayscale, it still shows the original picture in the picture box.
Here is the code when it works, without the conversion:
private void button1_Click(object sender, EventArgs e)
{
Rectangle rectangle = new Rectangle(660, 200, 600, 100);
pictureBox1.Height = rectangle.Height;
pictureBox1.Width = rectangle.Width;
imageUploader(rectangle);
}
public void imageUploader(Rectangle rectangle)
{
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
bitmap.Save("proba.jpeg", ImageFormat.Jpeg);
pictureBox1.Image = bitmap;
}
Here is the conversion method, which I tried out:
public void toGrayscale(Bitmap bitmap)
{
Color c;
for (int y = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
c = bitmap.GetPixel(x,y);
Color newColor = Color.FromArgb(c.R,0,0);
bitmap.SetPixel(x,y,newColor);
}
}
}
After I used this conversion (see below) the image showed up in the picture box, but it wasn't grayscale.
Here is the modified imageUploader void with the conversion:
public void imageUploader(Rectangle rectangle)
{
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
toGrayscale(bitmap);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
bitmap.Save("proba.jpeg", ImageFormat.Jpeg);
pictureBox1.Image = bitmap;
}
It appears that your issue is here:
public void imageUploader(Rectangle rectangle)
{
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
toGrayscale(bitmap);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
bitmap.Save("proba.jpeg", ImageFormat.Jpeg);
pictureBox1.Image = bitmap;
}
You're converting each pixel of the bitmap to greyscale (oddly it looks like you're only grabbing the red channel) then copying from the screen, which overwrites your conversion. To fix it, all you should need to do is move the toGreyscale after you copy from the screen, like this:
public void imageUploader(Rectangle rectangle)
{
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
toGrayscale(bitmap); # Moved after the copy from screen
bitmap.Save("proba.jpeg", ImageFormat.Jpeg);
pictureBox1.Image = bitmap;
}
This should fix the issue.
You are converting an empty Bitmap to greyscale, then copying over the (nominally) greyscaled Bitmap with an image from the screen. Here is your code, annotated to describe what it is doing:
// This line creates an empty Bitmap.
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
// This line converts the empty Bitmap to grayscale.
toGrayscale(bitmap);
// This line creates a Graphics drawing surface from your bitmap.
Graphics graphics = Graphics.FromImage(bitmap);
// This line overwrites the image data from your bitmap with an image from the screen.
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
You need to find some way to take the data you got from the screen and make it greyscale. You have not done this. You have made a greyscale image, but then you have thrown it away by writing other data on top of it. It happens that that replacement data is not greyscale.
I have worked on image capture window application. When I have captured image by application in window tablet then image quality low and show darkness in captured image background. When I have captured image by tablet then image is good quality.
What is missing/problem in my code?
I have used code share by you...
private void cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Bitmap bitmap = (Bitmap)eventArgs.Frame.Clone();
ImgContainer.Image = b;
}
private void btnKeep_Click(object sender, EventArgs e)
{
int width = 457;
int height = 350;
Image tmpimg = ImgContainer.Image;
System.Drawing.Bitmap b = new System.Drawing.Bitmap(ImgContainer.Image, width, height);
System.Drawing.Graphics gr = System.Drawing.Graphics.FromImage(b);
gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
System.Drawing.Rectangle rectDestination = new System.Drawing.Rectangle(0, 0, width, height);
System.Drawing.Imaging.ImageCodecInfo codec = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()[1];
System.Drawing.Imaging.EncoderParameters eParams = new System.Drawing.Imaging.EncoderParameters(1);
eParams.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
string ImagePath = Guid.NewGuid().ToString();
string imagefullpath = System.AppDomain.CurrentDomain.BaseDirectory + "imageFolder\\" + ImagePath + ".jpg";
b.Save(imagefullpath);
}
Show you captured by application image ............
Show you captured by tablet ............
Please give me any idea and solution remove darkness captured by application (above image).
You can use a DrawImage with an ImageAttributes instance to change the gamma. I found 0.5f to work:
Here is a function that applies a gamma value to a bitmap and returns a modified bitmap. It is up to you to ..:
make sure you don't leak resources
make sure to apply the gamma always to the original and not repeatedly to the same bitmap when giving the user a trackbar to find a good value..
The function:
public static Bitmap ApplyGamma(Bitmap bmp0, float gamma)
{
Bitmap bmp1 = new Bitmap(bmp0.Width, bmp0.Height);
using (Graphics g = Graphics.FromImage(bmp1))
{
ImageAttributes attributes = new ImageAttributes();
attributes.SetGamma(gamma, ColorAdjustType.Bitmap);
g.DrawImage(bmp0, new Rectangle(0, 0, bmp0.Width, bmp0.Height),
0, 0, bmp0.Width, bmp0.Height, GraphicsUnit.Pixel, attributes);
}
return bmp1;
}
The calling code I used:
Image img = Image.FromFile(yourImage); // some image to use
float gamma = (float)(trackBar1.Value / 10f); // a trackbar to test
Text = "Gamma = " + gamma; // a control display
pictureBox1.Image = ApplyGamma((Bitmap)img, gamma);
If you also want to change contrast and/or brightness you can use a ColorMatrix. See here for an example!
I keep getting this error of 'System.Runtime.InteropServices.ExternalException' on line 70 "img3.Save(finalImage, System.Drawing.Imaging.ImageFormat.Jpeg);". Originally I had a program that stitched two photos together that worked fine, but I wanted the two images to be the same size (300 pixles by 300 pixles) so I inserted a method:
public static Image resizeImage(Image imgToResize, Size size)
{
return (Image)(new Bitmap(imgToResize, size));
}
and in my CombineImages method put:
img = resizeImage(img, new Size(300, 300));
but now I am getting an error. Here is my code:
private void cmdCombine_Click(object sender, EventArgs e)
{
//Change the path to location where your images are stored.
DirectoryInfo directory = new DirectoryInfo(#"C:\Users\Elder Zollinger\Desktop\Images");
if (directory != null)
{
FileInfo[] files = directory.GetFiles();
CombineImages(files);
}
}
private void CombineImages(FileInfo[] files)
{
//change the location to store the final image.
string finalImage = #"C:\Users\Elder Zollinger\Desktop\Images\Final.jpg";
List<int> imageHeights = new List<int>();
int nIndex = 0;
int width = 0;
foreach (FileInfo file in files)
{
Image img = Image.FromFile(file.FullName);
img = resizeImage(img, new Size(300, 300));
imageHeights.Add(img.Height);
width += img.Width;
img.Dispose();
}
imageHeights.Sort();
int height = imageHeights[imageHeights.Count - 1];
Bitmap img3 = new Bitmap(width, height);
Graphics g = Graphics.FromImage(img3);
g.Clear(SystemColors.AppWorkspace);
foreach (FileInfo file in files)
{
Image img = Image.FromFile(file.FullName);
if (nIndex == 0)
{
g.DrawImage(img, new Point(0, 0));
nIndex++;
width = img.Width;
}
else
{
g.DrawImage(img, new Point(width, 0));
width += img.Width;
}
img.Dispose();
}
g.Dispose();
img3.Save(finalImage, System.Drawing.Imaging.ImageFormat.Jpeg);
img3.Dispose();
imageLocation.Image = Image.FromFile(finalImage);
}
public static Image resizeImage(Image imgToResize, Size size)
{
return (Image)(new Bitmap(imgToResize, size));
}
}
}
It is likely that the image format of the uploaded image cannot be converted directly to Jpeg. One thing we do when resizing is actually draw the image to a new Graphics instance as follows. Note that the first 2 lines attempt to get the pixel and image formats directly from the original image instance - you may have issues with CMYK and images with a transparency layer (GIF/PNG).
var pixelFormat = imgToResize.PixelFormat;
var imageFormat = imgToResize.RawFormat;
Bitmap b = new Bitmap(newWidth.Value, newHeight.Value, pixelFormat);
Graphics g = Graphics.FromImage(b);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawImage(imgToResize, (float)-0.5, (float)-0.5, newWidth.Value + 1, newHeight.Value + 1);
g.Dispose();
b.Save(stream, imageFormat);
When i used following code to convert a bitmap from 8bpp to 24bpp, the resulted image is shifted but i can't figure out the reason of that, can anyone help?
private static Bitmap ConvertTo24(Bitmap bmpIn)
{
bmpIn.Save(#"F:\sara1.bmp");
Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(converted))
{
// Prevent DPI conversion
g.PageUnit = GraphicsUnit.Pixel;
// Draw the image
g.DrawImageUnscaled(bmpIn, 0, 0);
// g.DrawImage(bmpIn, 0, 0);
}
converted.Save(#"F:\sara2.bmp");
}
The following code worked for me:
private static Bitmap ConvertTo24(Bitmap bmpIn)
{
bmpIn.Save(#"F:\sara1.bmp");
Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(converted))
{
// Prevent DPI conversion
g.PageUnit = GraphicsUnit.Pixel;
// Draw the image
// g.DrawImageUnscaled(bmpIn, 0, 0);
g.DrawImage(bmpIn, 0, 0, converted.Width, converted.Height);
}
converted.Save(#"F:\sara2.bmp");
}
Providing the width and height rescales the image.
You could have problem in bmpIn before receiving it in your function.
You can test following (better) code after putting your 8bpp image in f:\sara1.bmp (just to ensure that you have 8bpp image not shifted before conversion).
private static Bitmap ConvertTo24(Bitmap bmpIn)
{
//Bitmap bmpIn;
bmpIn = new Bitmap(#"f:\sara1.bmp");
Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(converted))
{
g.PageUnit = GraphicsUnit.Pixel;
Rectangle rng = new Rectangle(new Point(0, 0), bmpIn.Size);
g.DrawImage(bmpIn, rng); // use this instead of following
}
converted.Save(#"F:\sara2.bmp");
}
Hope it works fine 4 u. I used DrawImage(Image img, Rectangle rng) as you are already told in comments
Answer is complete. Following is explanation. Your code (edited. Use it as it is and follow the comment)
private static Bitmap ConvertTo24(Bitmap bmpIn)
{
bmpIn.Save(#"F:\sara1.bmp");
return;
// After you have called this function. Go open your image f:\sara1.bmp from
//hrad disk-- I doubt you would find it shifted here even before conversion
Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(converted))
{
// Prevent DPI conversion
g.PageUnit = GraphicsUnit.Pixel;
// Draw the image
g.DrawImageUnscaled(bmpIn, 0, 0);
// g.DrawImage(bmpIn, 0, 0);
}
converted.Save(#"F:\sara2.bmp");
}
Again Your code ( I just ignored your received 8bpp Bitmap and fetched it directly from f drive, supposing that you would put it before running the application or at least before calling this function)
Following code also worked fine for me.
private static Bitmap ConvertTo24(Bitmap bmpIn)
{
Bitmap bmpIn = new Bitmap(#"f:\sara1.bmp");
Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(converted))
{
// Prevent DPI conversion
g.PageUnit = GraphicsUnit.Pixel;
// Draw the image
g.DrawImageUnscaled(bmpIn, 0, 0);
// g.DrawImage(bmpIn, 0, 0);
}
converted.Save(#"F:\sara2.bmp");
}
I am trying to do a simple crop of an image, but for some reason it is not respecting my starting x,y location. It is always starting the crop at 0,0. The following is what I am doing:
Bitmap original = new Bitmap(pictureBox1.Image);
int x = Convert.ToInt32(txtX.Text);
int y = Convert.ToInt32(txtY.Text);
int dX = Convert.ToInt32(txtDeltaX.Text);
int dY = Convert.ToInt32(txtDeltaY.Text);
Point loc = new Point(x, y);
Size cropSize = new Size(dX, dY);
Rectangle cropArea = new Rectangle(loc, cropSize);
Bitmap bmpCrop = CropImage(original, cropArea);
pictureBox1.Image = bmpCrop;
The cropping method:
public Bitmap CropImage(Bitmap source, Rectangle section)
{
// An empty bitmap which will hold the cropped image
Bitmap bmp = new Bitmap(section.Width, section.Height);
Graphics g = Graphics.FromImage(bmp);
// Draw the given area (section) of the source image
// at location 0,0 on the empty bitmap (bmp)
g.DrawImage(source, 0, 0, section, GraphicsUnit.Pixel);
return bmp;
}
This should be very simple, but for some reason its not working. Its cropping it, just at 0,0.
Thanks!
You should try to use
g.DrawImage(source, section);
Anyway this function works:
public Bitmap CropBitmap(Bitmap bitmap,
int cropX, int cropY,
int cropWidth, int cropHeight)
{
Rectangle rect = new Rectangle(cropX, cropY, cropWidth, cropHeight);
Bitmap cropped = bitmap.Clone(rect, bitmap.PixelFormat);
return cropped;
}
You might want to use Graphics.DrawImageUnscaledAndClipped
Try to use, something like this :
g.DrawImage(source, x, y, section, GraphicsUnit.Pixel);