how to draw a part of a png image c# - c#

I'm trying to draw a part of a .png image but the code i found is not working. this is my code
//define canvas
canvas = pb.CreateGraphics();
sPicture = new Bitmap(pb.Width, pb.Height);
sCanvas = Graphics.FromImage(sPicture);
// Create a Bitmap object from a file.
Image image = Image.FromFile(#"");
// Clone a portion of the Bitmap object.
Rectangle cloneRect = new Rectangle(0, 0, 11, 6);
System.Drawing.Imaging.PixelFormat format =
image.PixelFormat;
Image cloneBitmap = image.Clone(cloneRect, format); //Error: No overload for method 'Clone' takes2 arguments
// Draw the cloned portion of the Bitmap object.
canvas.DrawImage(cloneBitmap, 0, 0);
This is for a sprite sheet and thanks.

You don't need to use Clone(), you can do this directly with Graphics.DrawImage(). It looks like you are trying to do this in WinForms. If, so handle OnPaint for the control you want to draw on. In the example below I'm drawing directly on the form.
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics graphics = e.Graphics;
int width = 60;
int height = 60;
// Create a Bitmap object from a file.
Image sourceImage = Image.FromFile(#"C:\Users\Mike\Downloads\logo.png");
// Draw a portion of the source image.
Rectangle sourceRect = new Rectangle(0, 0, width, height);
graphics.DrawImage(sourceImage, 0, 0, sourceRect, GraphicsUnit.Pixel);
}
If you want to do this without WinForms, there is the extra step of creating the target Graphics instance.
int width = 60;
int height = 60;
// Create a Bitmap object from a file.
Image sourceImage = Image.FromFile(#"C:\Users\Mike\Downloads\logo.png");
// Create a drawing target
Bitmap bitmap = new Bitmap(width, height, sourceImage.PixelFormat);
Graphics graphics = Graphics.FromImage(bitmap);
// Draw a portion of the source image.
Rectangle sourceRect = new Rectangle(0, 0, width, height);
graphics.DrawImage(sourceImage, 0, 0, sourceRect, GraphicsUnit.Pixel);
// Save
bitmap.Save(#"C:\Users\Mike\Downloads\out.png");

Related

Screenshot conversion into grayscale doesn't work. What causes this?

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.

Overlay bitmap on another bitmap

On a single bitmap I need to display graphs and text values. So what I did is create a bitmap with points and creating a another bitmap with the text and place on the large bitmap.
I tried using the brush to write the text, but I am not able to see the underlying graphics even though trasparency is set.
Instead I thought to set the transparency for the text bitmap, but the bitmap which I have created are 24 bit rgb. So can we set the transparency for the 24 bit map.
Bitmap textBitmap = null;
textBitmap = new Bitmap(10, 10, PixelFormat.Format24bppRgb);
using (Graphics memoryGrahics =
Graphics.FromImage(textBitmap))
{
memoryGrahics.FillRectangle(Brushes.Black, new Rectangle(0, 0, 100, 100));
memoryGrahics.DrawString(result, f, Brushes.White, x, y);
}
//placing the text bitmap on the graphbitmap
using (Graphics g = Graphics.FromImage(GraphBitmap))
{
g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
textBitmap.MakeTransparent();
g.DrawImage(textBitmap, 0, 0);
return GraphBitmap;
}
well.. it seems like you are using 2 different Graphical objects... although 1 Graphics objects with 1 bitmap can handle multiple layouts of custom drawings, like so:
int width = 800, height = 600;
var bit = new Bitmap(width, height);
var g = Graphics.FromImage(bit);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
var area = new Rectangle(0, 0, width, height);
g.FillRectangle(new LinearGradientBrush(area, Color.PaleGoldenrod, Color.OrangeRed, 45), area);
g.DrawImage(Image.FromFile(#"your image"), new Point(10, 10));
g.DrawString("sample", new System.Drawing.Font("Tahoma", 56), new SolidBrush(Color.Black), new PointF(50, 50));
pictureBox1.Image = bit;
note that g.DrawImage method can be used to load other bitmaps as well

How do I resize an image without stretching it?

I am trying to resize an image (bitmap) in C# without stretching the image.
Say the image is 100x100 pixels.
I am looking to make it 100x110 pixels, and leave a white gap at the bottom of the image where it added the extra pixels.
I have done this, but cannot find a way to specify the pixel format. I need it to be 8bppindexed. I've attached an example to show the before and after image.
Here is the code I have so far.
string visit2 = "C:\\users\\moorez\\desktop\\visit2.bmp";
Bitmap orig = new Bitmap(visit2);
int width = orig.Width;
int height = orig.Height;
int newHeight = height + 2;
Bitmap newImage = orig.Clone(new Rectangle(0, 0, width, height), System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
newImage.Save("C:\\users\\moorez\\desktop\\visit3.bmp");
Bitmap test = new Bitmap(width, newHeight);
Graphics g = Graphics.FromImage(test);
g.DrawImage(newImage, new Point(0, 0));
test.Save("C:\\users\\moorez\\desktop\\visit4.bmp");
You can try this
Bitmap bmp = new Bitmap(newImage.Width, newHeight);
Graphics g = Graphics.FromImage(bmp);
g.Clear(Color.White);
g.DrawImageUnscaled(newImage, 0, 0, newImage.Width, newHeight);
bmp.Save(#"C:\\users\\moorez\\desktop\\visit3.bmp", ImageFormat.Jpeg);

Merging 2 images using C#

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.

Composition from multiple images using C#.NET

I have a PictureBox on which images from files are painted, one on top of another (like a photoshop layering concept, if you're familiar). Being PNGs and with a opacity index, these images are perfect candidates for a image composition. But I can't figure out how to do that and save to a file.
In the following code sample, I've loaded two PNG images into bitmap objects and had them painted on the PictureBox.
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Rectangle DesRec = new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height);
Bitmap bmp;
Rectangle SrcRec;
bmp = (Bitmap)Image.FromFile(Application.StartupPath + "\\Res\\base.png");
SrcRec = new Rectangle(0, 0, bmp.Width, bmp.Height);
e.Graphics.DrawImage(bmp, DesRec, SrcRec, GraphicsUnit.Pixel);
bmp = (Bitmap)Image.FromFile(Application.StartupPath + "\\Res\\layer1.png");
SrcRec = new Rectangle(0, 0, bmp.Width, bmp.Height);
e.Graphics.DrawImage(bmp, DesRec, SrcRec, GraphicsUnit.Pixel);
}
How do I save the composition to a file, preferably to another PNG file?
I would start drawing to an intermediate in-memory bitmap, which I would then save (and eventually draw in your picture box, if really needed). Something like this:
var bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
using (var graphics = Graphics.FromImage(bmp))
{
// ...
graphics.DrawImage(...);
// ...
}
bmp.Save("c:\\test.png", ImageFormat.Png);
Thanks both of you. I've decided to do as Efran Cobisi suggested and changed the program so that it does the composing in memory first. Then I can use it where ever and however I want.
My new code to reflect the changes is as follows-
// Image objects to act as layers (which will hold the images to be composed)
Image Layer0 = new Bitmap(Application.StartupPath + "\\Res\\base.png");
Image Layer1 = new Bitmap(Application.StartupPath + "\\Res\\layer1.png");
//Creating the Canvas to draw on (I'll be saving/using this)
Image Canvas = new Bitmap(222, 225);
//Frame to define the dimentions
Rectangle Frame = new Rectangle(0, 0, 222, 225);
//To do drawing and stuffs
Graphics Artist = Graphics.FromImage(Canvas);
//Draw the layers on Canvas
Artist.DrawImage(Layer0, Frame, Frame, GraphicsUnit.Pixel);
Artist.DrawImage(Layer1, Frame, Frame, GraphicsUnit.Pixel);
//Free up resources when required
Artist.dispose();
//Show the Canvas in a PictureBox
pictureBox1.Image = Canvas;
//Save the Canvas image
Canvas.Save("MYIMG.PNG", ImageFormat.Png);
Apparently, the images (Canvas) are being saved with opacity index intact.

Categories