Bitmap Resize, only crops the image and no resizing - c#

I have this code to resize a bitmap, but all it does is to crop it instead of resizing, what I am doing wrong?
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);
// set the resolutions the same to avoid cropping due to resolution differences
result.SetResolution(image.HorizontalResolution, image.VerticalResolution);
//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;
}
and I call the function like this
bmPhoto = Imaging.ImageProcessing.ResizeImage(bmPhoto, scaledSize.Width, scaledSize.Height);

// Keeping Aspect Ratio
Image resizeImg(Image img, int width)
{
double targetHeight = Convert.ToDouble(width) / (img.Width / img.Height);
Bitmap bmp = new Bitmap(width, (int)targetHeight);
Graphics grp = Graphics.FromImage(bmp);
grp.DrawImage(img, new Rectangle(0, 0, bmp.Width, bmp.Height), new Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel);
return (Image)bmp;
}
// Without Keeping Aspect Ratio
Image resizeImg(Image img, int width, int height)
{
Bitmap bmp = new Bitmap(width, height);
Graphics grp = Graphics.FromImage(bmp);
grp.DrawImage(img, new Rectangle(0, 0, bmp.Width, bmp.Height), new Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel);
return (Image)bmp;
}

Try using a Rectangle object to specify the portion of the new image that you want to fill, like so:
graphics.DrawImage(image, new Rectangle(0, 0, result.Width, result.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, null);
As noted the Rectangle specifies that the image should be drawn between the top left and bottom right corner, and then you provide the coordinates of the original image that you want to scale into that area (0,0,image.Width,image.Height).

Related

How to set a 200x200 background of an image?

I am currently creating an app which will let you upload some images and then resize them (100x180) and put a 200x200 white background on them.
I've figured on how to resize the images + create the white background but I cannot figure out how to put them together.
Here is the code for resizing and the white background:
public static Bitmap ResizeImage(Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
private Bitmap DrawFilledRectangle(int x, int y)
{
Bitmap bmp = new Bitmap(x, y);
using (Graphics graph = Graphics.FromImage(bmp))
{
Rectangle ImageSize = new Rectangle(0, 0, x, y);
graph.FillRectangle(Brushes.White, ImageSize);
}
return bmp;
}
Expected result:
Thank you all in advance!

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

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

C#: how to take a screenshot of a portion of screen

like
TakeScreenshot(new Rectangle(0,0,100,100), "output.jpg");
Use the following:
Rectangle rect = new Rectangle(0, 0, 100, 100);
Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(bmp);
g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);
bmp.Save(fileName, ImageFormat.Jpeg);
Here is the code to capture the screen. Change the values to the size you need.
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:\printscreen.jpg", ImageFormat.Jpeg);
Or make method which will return you captured image like this :
Image CaptureScreen(int sourceX, int sourceY, int destX, int destY,
Size regionSize)
{
Bitmap bmp = new Bitmap(regionSize.Width, regionSize.Height);
Graphics g = Graphics.FromImage(bmp);
g.CopyFromScreen(sourceX, sourceY, destX, destY, regionSize);
return bmp;
}
......
// call
Image image = CaptureScreen(sourceX, sourceY, destX, destY, regionSize);
image.Save(#"C:\Somewhere\screen.jpg);
Use the Graphics.CopyFromScreen method. Google turns up this tutorial.
Have you checked the Graphics.CopyFromScreen method?

Categories