I'm taking a screenshot of my form and then sending it to the printer. The image is too large, it goes off the sides of the page. I've been looking around for the past few hours to no avail. Can someone assist?
When I open the file itself it looks good in a print preview. If I then print from the preview its fine. But I wanted to do this with no user intervention.
public void SetupPrintHandler()
{
PrintDocument printDoc = new PrintDocument();
printDoc.PrintPage += new PrintPageEventHandler(OnPrintPage);
printDoc.DefaultPageSettings.Landscape = true;
printDoc.Print();
}
private void OnPrintPage(object sender, PrintPageEventArgs args)
{
using (Image image = Image.FromFile(#"C:/temp2.bmp"))
{
Graphics g = args.Graphics;
g.DrawImage(image, 0, 0);
}
}
private void printscreen()
{
ScreenCapture sc = new ScreenCapture();
Image img = sc.CaptureScreen();
sc.CaptureWindowToFile(this.Handle, "C:/temp2.bmp", ImageFormat.Bmp);
SetupPrintHandler();
}
So what I did just now as instead of the screen shot, for testing, I save what was in panel3 which is 2 pictureboxes. So i'm taking the size of panel3.
Bitmap bmp = new Bitmap(panel3.ClientSize.Width, panel3.ClientSize.Height);
panel3.DrawToBitmap(bmp, panel3.ClientRectangle);
bmp.Save(subPath + file + ".bmp");
Which again, looks great on a print preview and if I click print from the print preview it prints fine. But if I just send it straight to the printer it doesn't fit. So maybe its not a size issue but a setting I have to send to the printer when not using print preview?
Update
So I may have found the issue. When you un-check "Fit to frame" when printing a picture it fits perfectly. However there doesn't seem to be an option when sending directly to the printer the way I am where I can disable "Fit to frame"
If you want to resize and keep the aspect of the image I do the following
public Stream ResizeImage(Stream stream, ImageFormat imageFormat, int width, int height)
{
var originalImage = Image.FromStream(stream);
var sourceWidth = originalImage.Width;
var sourceHeight = originalImage.Height;
const int sourceX = 0;
const int sourceY = 0;
var destX = 0;
var destY = 0;
float nPercent;
var nPercentW = ((float)width / sourceWidth);
var nPercentH = ((float)height / sourceHeight);
if (nPercentH < nPercentW)
{
nPercent = nPercentH;
destX = Convert.ToInt16((width - (sourceWidth * nPercent)) / 2);
}
else
{
nPercent = nPercentW;
destY = Convert.ToInt16((height - (sourceHeight * nPercent)) / 2);
}
var destWidth = (int)(sourceWidth * nPercent);
var destHeight = (int)(sourceHeight * nPercent);
// specify different formats based off type ( GIF and PNG need alpha channel - 32aRGB 8bit Red 8bit Green 8bit B 8bit Alpha)
Bitmap newImage;
if (imageFormat.Equals(ImageFormat.Png) || imageFormat.Equals(ImageFormat.Gif))
{
newImage = new Bitmap(width, height, PixelFormat.Format32bppArgb);
}
else
{
newImage = new Bitmap(width, height, PixelFormat.Format24bppRgb);
}
newImage.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution);
var newGraphics = Graphics.FromImage(newImage);
// don't clear the buffer with white if we have transparency
if (!imageFormat.Equals(ImageFormat.Png) && !imageFormat.Equals(ImageFormat.Gif))
{
newGraphics.Clear(Color.White);
}
newGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
newGraphics.DrawImage(originalImage,
new Rectangle(destX, destY, destWidth, destHeight),
new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
GraphicsUnit.Pixel);
newGraphics.Dispose();
originalImage.Dispose();
var memoryStream = new MemoryStream();
newImage.Save(memoryStream, imageFormat);
memoryStream.Position = 0;
return memoryStream;
}
Using this you can resize the image. You need to pick up a scaling size before print.
As example - rescale 'image' to 227x171 pixels.
image = new Bitmap(image, new Size(227, 171));
Related
Link to Project: https://github.com/FFladenmuller/resize-bmp
Code works for a resize with a factor of 1. However, if trying a larger factor and I open the image, Photos says: "It looks like we don't support this file format".
I have not added in padding yet but I have only worked with images whose width is divisible by 4.
For loop to add BGR bytes to new Image:
for (int i = 54; i < oldBMP.Info.Count - 2; i += 3)
{
for(int j = 0; j < sizeMultiplier; j++)
{
newBMP.Info.Add(oldBMP.Info[i]);
newBMP.Info.Add(oldBMP.Info[i + 1]);
newBMP.Info.Add(oldBMP.Info[i + 2]);
}
}
First for loop to increment through BGR triples, second for loop to add each pixel sizeMultiplier amount of times.
Define the following method:
public static Bitmap ResizeImage(Bitmap image, Size size)
{
try
{
Bitmap result = new Bitmap(size.Width, size.Height);
using (Graphics g = Graphics.FromImage((Image)result))
{
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.DrawImage(image, 0, 0, size.Width, size.Height);
}
return result;
}
catch
{
return image;
}
}
Then, within your code, whenever a resize is needed:
Bitmap image = new Bitmap(#"C:\Path\MyImage.bmp");
Single scaleWidth = 1.2f;
Int32 targetWidth = (Int32)((Single)image.Width * scaleWidth);
Single scaleHeight = 1.0f;
Int32 targetHeight = (Int32)((Single)image.Height * scaleHeight);
Size size = new Size(targetWidth, targetHeight);
Bitmap imageResized = ResizeImage(image, size);
An alternative (that has the drawback of reducing the output quality) is the following:
Bitmap image = new Bitmap(#"C:\Path\MyImage.bmp");
Single scaleWidth = 1.2f;
Int32 targetWidth = (Int32)((Single)image.Width * scaleWidth);
Single scaleHeight = 1.0f;
Int32 targetHeight = (Int32)((Single)image.Height * scaleHeight);
Bitmap imageResized = new Bitmap(image, targetWidth, targetHeight);
I am facing an interesting issue when re-sizing images of average dimension 1200x700. I am using following method to do the same. I see original image size is 210KB and output image size is 255KB.
public static Image ResizeImage(Image image, Size size, bool preserveAspectRatio = true)
{
int newWidth;
int newHeight;
if (preserveAspectRatio)
{
int originalWidth = imageFile.Width;
int originalHeight = imageFile.Height;
float percentWidth = (float)size.Width / (float)originalWidth;
float percentHeight = (float)size.Height / (float)originalHeight;
float percent = percentHeight < percentWidth ? percentHeight : percentWidth;
newWidth = (int)(originalWidth * percent);
newHeight = (int)(originalHeight * percent);
}
else
{
newWidth = size.Width;
newHeight = size.Height;
}
Image newImage = new Bitmap(newWidth, newHeight);
using (Graphics graphicsHandle = Graphics.FromImage(newImage))
{
graphicsHandle.CompositingQuality = CompositingQuality.HighQuality;
graphicsHandle.SmoothingMode = SmoothingMode.HighQuality;
graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphicsHandle.DrawImage(imageFile, 0, 0, newWidth, newHeight);
}
return newImage;
}
To call above method I'm using following code:
WebClient wc = new WebClient();
try
{
using (var image = Image.FromStream(new MemoryStream(wc.DownloadData(remoteFileLocation))))
{
Image resized = ResizeImage(image, new Size(660, 660));
resized.Save(saveFileLocation);
}
}
catch(Exception)
{
//todo
}
I tried different InterpolationMode and CompositingQuality but result is always same. Is there anything I'm missing to reduce image dimension and size? I mean, I'm expecting if dimension is decreased image size should also decrease.
I want to resize the image coming through file uploader. For that I was referred to the following:
How to set Bitmap.Width and Bitmap.height
(Javed Akram's Answer)
Made following code:
Dim imgSmall As Bitmap = New Bitmap(FUpload.PostedFile.InputStream, False)
imgSmall.Size = New Size(250, 300)
But giving me error:
Size is read-only property.
How can I resize the image in this case?
It is read-only; you'll have to create a new bitmap from it. Try this: -
internal static Image ScaleByPercent(Image image, Size size, float percent)
{
int sourceWidth = image.Width,
sourceHeight = image.Height;
int destWidth = (int)(sourceWidth * percent),
destHeight = (int)(sourceHeight * percent);
if (destWidth <= 0)
{
destWidth = 1;
}
if (destHeight <= 0)
{
destHeight = 1;
}
var resizedImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
resizedImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
// get handle to new bitmap
using (var graphics = Graphics.FromImage(resizedImage))
{
InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// create a rect covering the destination area
var destRect = new Rectangle(0, 0, destWidth, destHeight);
var brush = new SolidBrush(drawing.Color.White);
graphics.FillRectangle(brush, destRect);
// draw the source image to the destination rect
graphics.DrawImage(image,
destRect,
new Rectangle(0, 0, sourceWidth, sourceHeight),
GraphicsUnit.Pixel);
}
return resizedImage;
}
This is from a site I have in production; if you want I can send you the code that works out how to keep the correct aspect ratio when resizing (i.e. what gets passed in the 'size' parameter)
Hope that helps
I have to display image in photo gallery # width=200 height=180, but while uploading images I have to resize it , but the problem is every image have different resolution. How can I resize the images with different resolution so that images remain intact.
Here is my code :
private void ResizeImage()
{
System.Drawing.Image ImageToUpload = System.Drawing.Image.FromStream(FileUpload1.PostedFile.InputStream);
byte[] image = null;
int h = ImageToUpload.Height;
int w = ImageToUpload.Width;
int r = int.Parse(ImageToUpload.VerticalResolution.ToString());
int NewWidth = 200;//constant
int NewHeight = 180;//constant
byte[] imagesize = FileUpload1.FileBytes;
System.Drawing.Bitmap BitMapImage = new System.Drawing.Bitmap(ImageToUpload, NewWidth, NewHeight);//this line gives horrible output
MemoryStream Memory = new MemoryStream();
BitMapImage.Save(Memory, System.Drawing.Imaging.ImageFormat.Jpeg);
Memory.Position = 0;
image = new byte[Memory.Length + 1];
Memory.Read(image, 0, image.Length);
}
if resolution is 96 and if I set maxwidth=200 then its height would be 150 then only the image looks small and accurate. Can't we resize image in desired way so that it looks exact?
The function will resize the image maintaining aspect ratio.
public static Image Resize(Image originalImage, int w, int h)
{
//Original Image attributes
int originalWidth = originalImage.Width;
int originalHeight = originalImage.Height;
// Figure out the ratio
double ratioX = (double)w / (double)originalWidth;
double ratioY = (double)h / (double)originalHeight;
// use whichever multiplier is smaller
double ratio = ratioX < ratioY ? ratioX : ratioY;
// now we can get the new height and width
int newHeight = Convert.ToInt32(originalHeight * ratio);
int newWidth = Convert.ToInt32(originalWidth * ratio);
Image thumbnail = new Bitmap(newWidth, newHeight);
Graphics graphic = Graphics.FromImage(thumbnail);
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = SmoothingMode.HighQuality;
graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphic.CompositingQuality = CompositingQuality.HighQuality;
graphic.Clear(Color.Transparent);
graphic.DrawImage(originalImage, 0, 0, newWidth, newHeight);
return thumbnail;
}
Usage
Image BitMapImage = Resize(ImageToUpload, NewWidth, NewHeight);
Here i keep height fixed to 180 to maintain aspect ratio. It will resize the image and save to disk. The return value is the percentage value which i use in 'background-size' css.
public float ResizePhoto(string filepath, string filename)
{
var path = Path.Combine(filepath, filename);
var newPath = Path.Combine(filepath, "sml_" + filename);
Image orgImage = Image.FromFile(path);
float fixedHt = 180f;
int destHeight, destWidth;
float reqScale;
if(orgImage.Height > fixedHt)
{
destHeight = (int)fixedHt;
destWidth = (int)(fixedHt / orgImage.Height * orgImage.Width);
reqScale = destWidth / destHeight * 100;
}
else
{
destHeight = orgImage.Height;
destWidth = orgImage.Width;
reqScale = fixedHt / destHeight * 100;
}
Bitmap bmp = new Bitmap(destWidth, destHeight);
bmp.SetResolution(orgImage.HorizontalResolution,orgImage.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmp);
grPhoto.DrawImage(orgImage,
new Rectangle(0, 0, destWidth, destHeight),
new Rectangle(0, 0, orgImage.Width, orgImage.Height),
GraphicsUnit.Pixel);
bmp.Save(newPath);
return reqScale;
}
How would you resize a JPEG image, to a fixed width whilst keeping aspect ratio? In a simple way, whilst preserving quality.
This will scale in the vertical axis only:
public static Image ResizeImageFixedWidth(Image imgToResize, int width)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = ((float)width / (float)sourceWidth);
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap b = new Bitmap(destWidth, destHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return (Image)b;
}
If you are reducing the width by 25 percent to a fixed value, you must reduce the height by 25 percent.
If you are increasing the width by 25 percent to a fixed value, you must increasing the height by 25 percent.
It's really straight forward.
Assuming there is a (double width) variable:
Image imgOriginal = Bitmap.FromFile(path);
double height = (imgOriginal.Height * width) / imgOriginal.Width;
Image imgnew = new Bitmap((int)width, (int)height, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(imgnew);
g.DrawImage(imgOriginal, new Point[]{new Point(0,0), new Point(width, 0), new Point(0, height)}, new Rectangle(0,0,imgOriginal.Width, imgOriginal.Height), GraphicsUnit.Pixel);
In the end you´ll have a new image with widthxheight, then, you´ll need to flush the graphics e save the imgnew.
I think there are plenty of samples of this if you search for them. Here's the one I commonly use...
public static Stream ResizeGdi(Stream stream, System.Drawing.Size size)
{
Image image = Image.FromStream(stream);
int width = image.Width;
int height = image.Height;
int sourceX = 0, sourceY = 0, destX = 0, destY = 0;
float percent = 0, percentWidth = 0, percentHeight = 0;
percentWidth = ((float)size.Width / (float)width);
percentHeight = ((float)size.Height / (float)height);
int destW = 0;
int destH = 0;
if (percentHeight < percentWidth)
{
percent = percentHeight;
}
else
{
percent = percentWidth;
}
destW = (int)(width * percent);
destH = (int)(height * percent);
MemoryStream mStream = new MemoryStream();
if (destW == 0
&& destH == 0)
{
image.Save(mStream, System.Drawing.Imaging.ImageFormat.Jpeg);
return mStream;
}
using (Bitmap bitmap = new Bitmap(destW, destH, System.Drawing.Imaging.PixelFormat.Format48bppRgb))
{
using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap))
{
//graphics.Clear(Color.Red);
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.DrawImage(image,
new Rectangle(destX, destY, destW, destH),
new Rectangle(sourceX, sourceY, width, height),
GraphicsUnit.Pixel);
}
bitmap.Save(mStream, System.Drawing.Imaging.ImageFormat.Jpeg);
}
mStream.Position = 0;
return mStream as Stream;
}
Example of the calling code...
Stream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.None);
resizedStream = ImageUtility.ResizeGdi(stream, new System.Drawing.Size(resizeWidth, resizeHeight));
A quick search on code project has found the following article. It allows for resizing of images which accepts a boolean to restrain the new image to keep the originals aspect ratio. I'm unsure of what the quality is like as no screenshots were provided. See the article here