Overlay bitmap on another bitmap - c#

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

Related

Add border to images 1 bpp indexed

I want to add a border to an Image.
To achieve that, I want to crate a new empty image with size equal to old size + border size, copy old image on center and draw border :
There is the method I wrote :
private Bitmap addBorderToImage(Image image, int borderSize)
{
Bitmap bmpTmp = new Bitmap(image);
Bitmap bmp = new Bitmap(bmpTmp.Width + 2 * borderSize,
bmpTmp.Height + 2 * borderSize,
bmpTmp.PixelFormat);
BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);
BitmapData dataTmp = bmpTmp.LockBits(new Rectangle(0, 0, bmpTmp.Width, bmpTmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed);
// Copy the bytes from the image into a byte array
for (int y = 0; y < bmpTmp.Height; y++)
{
System.Runtime.InteropServices.Marshal.Copy(dataTmp.Scan0, y * data.Stride, (IntPtr)((long)data.Scan0 + data.Stride * y + borderSize), y * data.Stride);
}
bmp.UnlockBits(data);
bmpTmp.UnlockBits(data);
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawRectangle(new Pen(Brushes.Green, borderSize * 2), new Rectangle(0, 0, bmp.Width, bmp.Height));
}
return bmp;
}
But I'm unable to do a correct copy. I have error :
Argument 1: cannot convert from 'System.IntPtr' to 'byte[]'
How should I do the Marshal.Copy ?
Edit: I use Marshall.copy instead of graphics cause I can't create graphics element from Format1bppIndexed.
First Marshal.Copy is expecting a byte [] array that's why it doesn't compile.
Second, you don't need to have low byte manipulation as Graphics handles all operation you need for this job (this is an authentic XY problem).
Last, there are many undisposed object in your original code which will leads you to memory leaks.
What about the following :
private static Bitmap AddBorderToImage(Image image, int borderSize)
{
using (Bitmap bmp = new Bitmap(image.Width + 2 * borderSize,
image.Height + 2 * borderSize))
{
using (Graphics destGraph = Graphics.FromImage(bmp))
{
destGraph.FillRectangle(Brushes.Green, new Rectangle(new Point(0, 0), bmp.Size));
destGraph.DrawImage(image, new Point(borderSize, borderSize));
}
return bmp.Clone(new Rectangle(0, 0, bmp.Width, bmp.Height), image.PixelFormat);
}
}
The idea is as simple as this:
Create a new result bitmap with the background of border's color
Draw the inner original image at the correct place (borderSize, borderSize).
Clone the final result with original PixelFormat
I used System.Drawing and got the results. Hope this is what you were looking for.
private Bitmap AddBorder(Image original_image, int border_size, Color border_color)
{
Size originalSize = new Size(original_image.Width + border_size, original_image.Height + border_size);
Bitmap bmp = new Bitmap(originalSize.Width, originalSize.Height);
Rectangle rec = new Rectangle(new Point(0, 0), originalSize);
Pen pen = new Pen(border_color, border_size);
Graphics g = Graphics.FromImage(bmp);
g.DrawRectangle(pen, rec);
rec.Inflate(-border_size /2, -border_size /2);
g.DrawImage(original_image, rec);
return bmp;
}

C# - picturebox, graphics.DrawImage and picturebox.Image = null, why?

I'm trying to crop and resize an image in PictureBox1. My code:
//original image for eventually undo
undoImage = pictureBox1.BackgroundImage.Clone() as Image;
Bitmap sourceBitmap = new Bitmap(pictureBox1.BackgroundImage, pictureBox1.Width, pictureBox1.Height);
Graphics g = pictureBox2.CreateGraphics();
g.DrawImage(sourceBitmap, new Rectangle(0, 0, pictureBox2.Width, pictureBox2.Height), rectCropArea, GraphicsUnit.Pixel);
sourceBitmap.Dispose();
And it working properly on two PictureBoxes.
But PictureBox2.Image,PictureBox2.BackgroundImage (and any other including ErrorImage...) = null.
I tried PictureBox.DrawToBitmap, and other, like g.GetHdc() found on google, but unsuccessful.
My question:
How do I properly copy the edited image from PictureBox2 to PictureBox1?
Trivial solution:
undoImage = pictureBox1.BackgroundImage.Clone() as Image;
Bitmap sourceBitmap = new Bitmap(pictureBox1.BackgroundImage, pictureBox1.Width, pictureBox1.Height);
using (Graphics g = Graphics.FromImage(sourceBitmap))
{
g.DrawImage(sourceBitmap, new Rectangle(0, 0, pictureBox2.Width,pictureBox2.Height), rectCropArea, GraphicsUnit.Pixel);
}
pictureBox1.BackgroundImage = sourceBitmap;

how to draw a part of a png image 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");

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);

c# write text on bitmap

I have following problem. I want to make some graphics in c# windows form.
I want to read bitmap to my program and after it write some text on this bitmap. In the end I want this picture load to pictureBox. And it's my question. How can I do it?
example, how must it work:
Bitmap a = new Bitmap(#"path\picture.bmp");
a.makeTransparent();
// ? a.writeText("some text", positionX, positionY);
pictuteBox1.Image = a;
Is it possible do to?
Bitmap bmp = new Bitmap("filename.bmp");
RectangleF rectf = new RectangleF(70, 90, 90, 50);
Graphics g = Graphics.FromImage(bmp);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawString("yourText", new Font("Tahoma",8), Brushes.Black, rectf);
g.Flush();
image.Image=bmp;
Very old question, but just had to build this for an app today and found the settings shown in other answers do not result in a clean image (possibly as new options were added in later .Net versions).
Assuming you want the text in the centre of the bitmap, you can do this:
// Load the original image
Bitmap bmp = new Bitmap("filename.bmp");
// Create a rectangle for the entire bitmap
RectangleF rectf = new RectangleF(0, 0, bmp.Width, bmp.Height);
// Create graphic object that will draw onto the bitmap
Graphics g = Graphics.FromImage(bmp);
// ------------------------------------------
// Ensure the best possible quality rendering
// ------------------------------------------
// The smoothing mode specifies whether lines, curves, and the edges of filled areas use smoothing (also called antialiasing).
// One exception is that path gradient brushes do not obey the smoothing mode.
// Areas filled using a PathGradientBrush are rendered the same way (aliased) regardless of the SmoothingMode property.
g.SmoothingMode = SmoothingMode.AntiAlias;
// The interpolation mode determines how intermediate values between two endpoints are calculated.
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Use this property to specify either higher quality, slower rendering, or lower quality, faster rendering of the contents of this Graphics object.
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
// This one is important
g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
// Create string formatting options (used for alignment)
StringFormat format = new StringFormat()
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
// Draw the text onto the image
g.DrawString("yourText", new Font("Tahoma",8), Brushes.Black, rectf, format);
// Flush all graphics changes to the bitmap
g.Flush();
// Now save or use the bitmap
image.Image = bmp;
References
https://msdn.microsoft.com/en-us/library/system.drawing.graphics.smoothingmode(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.drawing.drawing2d.interpolationmode(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.drawing.graphics.pixeloffsetmode(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.drawing.graphics.textrenderinghint(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.drawing.stringformat(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/21kdfbzs(v=vs.110).aspx
You need to use the Graphics class in order to write on the bitmap.
Specifically, one of the DrawString methods.
Bitmap a = new Bitmap(#"path\picture.bmp");
using(Graphics g = Graphics.FromImage(a))
{
g.DrawString(....); // requires font, brush etc
}
pictuteBox1.Image = a;
var bmp = new Bitmap(#"path\picture.bmp");
using( Graphics g = Graphics.FromImage( bmp ) )
{
g.DrawString( ... );
}
picturebox1.Image = bmp;
If you want wrap your text, then you should draw your text in a rectangle:
RectangleF rectF1 = new RectangleF(30, 10, 100, 122);
e.Graphics.DrawString(text1, font1, Brushes.Blue, rectF1);
See: https://msdn.microsoft.com/en-us/library/baw6k39s(v=vs.110).aspx

Categories