How do I resize an image without stretching it? - c#

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

Related

Cyotek ImageBox get zoomed part of image

I am using Cyotek ImageBox to zoom a image, now if I zoom to a part of image and that part is visible in the ImageBox how can I save that part of image which is visible in ImageBox.
The GetSourceImageRegion method allows you to get a RectangleF that describes the part of the image that is visible in the current state of an ImageBox.
The example code below will create a new Bitmap based on the visible part of the image. This example is not zoomed.
Rectangle visibleImageRegion;
Bitmap result;
visibleImageRegion = Rectangle.Round(imageBox.GetSourceImageRegion());
result = new Bitmap(visibleImageRegion.Width, visibleImageRegion.Height);
using (Graphics g = Graphics.FromImage(result))
{
g.DrawImage(imageBox.Image, new Rectangle(Point.Empty, visibleImageRegion.Size), visibleImageRegion, GraphicsUnit.Pixel);
}
This next example does the same as above, but also scales the new image to match the ImageBox
RectangleF visibleImageRegion;
Bitmap result;
double zoomFactor;
int w;
int h;
visibleImageRegion = imageBox.GetSourceImageRegion();
zoomFactor = imageBox.ZoomFactor;
w = Convert.ToInt32(visibleImageRegion.Width * zoomFactor);
h = Convert.ToInt32(visibleImageRegion.Height * zoomFactor);
result = new Bitmap(w, h);
using (Graphics g = Graphics.FromImage(result))
{
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imageBox.Image, new Rectangle(0, 0, w, h), visibleImageRegion, GraphicsUnit.Pixel);
}
You could hook into the Scroll or Zoomed events of the control to detect when you need to update the image based on user activity.

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

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 merge multiple images into a single image ?

I have an array of Images all of the same size . I should add them to a new image like i have shown in the picture.
Different colors represent different images.
Identify the size of final image
Create a bitmap with final height and width var bitmap = new Bitmap(width, height);
Draw each image on canvas
using (var canvas = Graphics.FromImage(bitmap))
{
canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
//Draw each image (maybe use a loop to loop over images to draw)
canvas.DrawImage(someImage, new Rectangle(0, 0, width, height), new Rectangle(0, 0, Frame.Width, Frame.Height), GraphicsUnit.Pixel);
canvas.Save();
}
Save the final image bitmap.Save("image path", ImageFormat.Jpeg);

Bitmap Resize, only crops the image and no resizing

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

Categories