I am looking for a way to limit resized image file size.
Resized image size should not exceed given size i.e. 100KB.
This is my code to resize image:
using (var ms = new MemoryStream(Image_data))
{
var image = Image.FromStream(ms);
var ratioX = (double)1800 / image.Width;
var ratioY = (double)1500 / image.Height;
var ratio = Math.Min(ratioX, ratioY);
var width = (int)(image.Width * ratio);
var height = (int)(image.Height * ratio);
var newImage = new Bitmap(width, height);
Graphics.FromImage(newImage).DrawImage(image, 0, 0, width, height);
Graphics.FromImage(newImage).CompositingQuality = CompositingQuality.HighQuality;
Graphics.FromImage(newImage).SmoothingMode = SmoothingMode.HighQuality;
Graphics.FromImage(newImage).InterpolationMode = InterpolationMode.HighQualityBicubic;
Bitmap bmp = new Bitmap(newImage);
ImageConverter converter = new ImageConverter();
Image_data = (byte[])converter.ConvertTo(bmp, typeof(byte[]));
string SmallImageData = string.Format(Convert.ToBase64String(Image_data));
string subpath = ConfigurationManager.AppSettings["ResizedImagePath"];
bool pathexists = System.IO.Directory.Exists(HttpContext.Current.Server.MapPath(subpath));
if (!pathexists)
{
System.IO.Directory.CreateDirectory(HttpContext.Current.Server.MapPath(subpath));
}
string path = HttpContext.Current.Server.MapPath(subpath) + "/" + ImageName + ".jpeg";
bmp.Save(path, ImageFormat.Jpeg);
}
But above code generate image file of any size.
Magick.NET provides an Extent parameter to specify a maximum file size output, which informs the compression. Description:
Gets or sets the compression quality that does not exceed the
specified extent in kilobytes (jpeg:extent).
An example as a test case from the source repo:
var defines = new JpegWriteDefines
{
Extent = 10, // 10 KB target size
};
using (var image = new MagickImage(/* File */))
{
using (MemoryStream memStream = new MemoryStream())
{
image.Settings.SetDefines(defines);
image.Format = MagickFormat.Jpeg;
image.Write(memStream);
}
}
Related
I am using C#,MVC5 and I am uploading image from my web application but I realize that I have performance issues because I don't optimize them and I need to fix it and is important to keep the quality.
Below you can see the results of the report why is slow.
How can I do it?
I am saving the files into a path locally with the below code.
string imgpathvalue = ConfigurationManager.AppSettings["RestaurantPath"];
string path = System.IO.Path.Combine(Server.MapPath(imgpathvalue));
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string pic = System.IO.Path.GetFileName(restaurantImg.FileName.Replace(" ", "_").Replace("%", "_"));
path = System.IO.Path.Combine(Server.MapPath(imgpathvalue), pic);
// file is uploaded
restaurantImg.SaveAs(path);
I have try the code below but I am getting the error "A generic error occurred in GDI+."
System.Drawing.Bitmap bmpPostedImage = new System.Drawing.Bitmap(restaurantImg.InputStream);
System.Drawing.Image objImage = ResizeImages.ScaleImage(bmpPostedImage, 81);
using (var ms = new MemoryStream())
{
objImage.Save(ms, objImage.RawFormat);
//ResizeImages.getImage(ms.ToArray());
}
public static System.Drawing.Image ScaleImage(System.Drawing.Image image, int maxHeight)
{
var ratio = (double)maxHeight / image.Height;
var newWidth = (int)(image.Width * ratio);
var newHeight = (int)(image.Height * ratio);
var newImage = new Bitmap(newWidth, newHeight);
using (var g = Graphics.FromImage(newImage))
{
g.DrawImage(image, 0, 0, newWidth, newHeight);
}
return newImage;
}
You are missing some of the code to resize your image correctly. Appending is a function that correctly resizes images depending on the Width and Height Values you give to it (in this example the image gets resized to 120*120 if possible).
Function Call:
ResizeImage("Path to the Image you want to resize",
"Path you want to save resizes copy into", 120, 120);
To make a function call like that possible we need to write our function. Which takes the image from the sourceImagePath and creates a new Bitmap.
Then it calculates the factor to resize the image and depending on if either the width or height is bigger it gets adjusted accordingly.
After that is done we create a new BitMap fromt he sourceImagePath and resize it. At the end we also need to dispose the sourceImage, the destImage and we also need to dispose of the Graphics Element g that we used for different Quality Settings.
Resize Function:
private void ResizeImage(string sourceImagePath, string destImagePath,
int wishImageWidth, int wishImageHeight)
{
Bitmap sourceImage = new Bitmap(sourceImagePath);
Bitmap destImage = null;
Graphics g = null;
int destImageWidth = 0;
int destImageHeight = 0;
// Calculate factor of image
double faktor = (double) sourceImage.Width / (double) sourceImage.Height;
if (faktor >= 1.0) // Landscape
{
destImageWidth = wishImageWidth;
destImageHeight = (int) (destImageWidth / faktor);
}
else // Port
{
destImageHeight = wishImageHeight;
destImageWidth = (int) (destImageHeight * faktor);
}
try
{
destImage = new Bitmap(sourceImage, destImageWidth, destImageHeight);
g = Graphics.FromImage(destImage);
g.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
g.SmoothingMode =
System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.PixelOffsetMode =
System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.CompositingQuality =
System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.DrawImage(sourceImage, 0, 0, destImageWidth, destImageHeight);
// Making sure that the file doesn't already exists.
if (File.Exists(destImagePath)) {
// If it does delete the old version.
File.Delete(destImagePath);
}
destImage.Save(destImagePath);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("*** ERROR-Terror: " + ex.Message)
}
finally
{
if (g != null) { g.Dispose(); g = null; }
if (destImage != null) { destImage.Dispose(); destImage = null; }
}
sourceImage.Dispose();
sourceImage = null;
}
I'm working on a task that draw a string on an image.
but the result image is not same with source code that I wrote down.
following image shows the font size difference.
red text is written in NanumSquare font 18px in window paint.
and the black text date below red text is also NanumSquare font 18px. It is written with C# source code.
following is my source code. C#.
static void Main(string[] args)
{
DrawTextToImageSave("webPrint_back.png");
}
public static void DrawTextToImageSave(string path)
{
//png to bitmap
Image Dummy = Image.FromFile(path);
using (Bitmap bitmap = (Bitmap)Dummy)
{//load the image file
using (Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
var titleFont = new Font("NanumSquareOTF ExtraBold", 25);
var bodyFont = new Font("NanumSquareOTF Regular", 25);
graphics.DrawString("DATE", titleFont, System.Drawing.Brushes.Black, new PointF(401.5f, 863.5f)); //comment 1
graphics.DrawString(DateTime.Now.ToString("yyyy.MM.dd"), bodyFont, System.Drawing.Brushes.Black, new PointF(345, 885f));
graphics.DrawString("LOCATION", titleFont, System.Drawing.Brushes.Black, new PointF(344, 919.5f));
graphics.DrawString(System.DateTime.Now.ToString("yyyyMMddHHmmss") , bodyFont, System.Drawing.Brushes.Black, new PointF(267f, 946f));
WriteableBitmap bitmapimg = Generator128Code("STACKOVERFLOW", 110, 110);
bitmapimg = resize_image(bitmapimg, 1.4); //comment 2
var stream = new MemoryStream();
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapimg));
encoder.Save(stream);
byte[] buffer = stream.GetBuffer();
var qrBitmap = new System.Drawing.Bitmap(new MemoryStream(buffer));
graphics.DrawImage(qrBitmap, 485f, 855f);
}
bitmap.Save( "output_WebPrintBack.png", ImageFormat.Png);
}
}
see comment 1. I expect it draws exactly 18px font. but It does not.
I have also same problem on drawing qrcode with zxing.
without comment2 code I get a ~90 px qr code size.
public static WriteableBitmap Generator128Code(string contents, int width, int height)
{
if (string.IsNullOrEmpty(contents))
{
return null;
}
EncodingOptions options = null;
BarcodeWriter writer = null;
options = new QrCodeEncodingOptions
{
CharacterSet = "UTF-8",
Width = width,
Height = height,
ErrorCorrection = ErrorCorrectionLevel.H,
Margin = 0
};
writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = options
};
WriteableBitmap bitmap = writer.Write(contents);
return bitmap;
}
static WriteableBitmap resize_image(WriteableBitmap img, double scale)
{
BitmapSource source = img;
var s = new ScaleTransform(scale, scale);
var res = new TransformedBitmap(img, s);
return convert_BitmapSource_to_WriteableBitmap(res);
}
static WriteableBitmap convert_BitmapSource_to_WriteableBitmap(BitmapSource source)
{
// Calculate stride of source
int stride = source.PixelWidth * (source.Format.BitsPerPixel / 8);
// Create data array to hold source pixel data
byte[] data = new byte[stride * source.PixelHeight];
// Copy source image pixels to the data array
source.CopyPixels(data, stride, 0);
// Create WriteableBitmap to copy the pixel data to.
WriteableBitmap target = new WriteableBitmap(source.PixelWidth
, source.PixelHeight, source.DpiX, source.DpiY
, source.Format, null);
// Write the pixel data to the WriteableBitmap.
target.WritePixels(new Int32Rect(0, 0
, source.PixelWidth, source.PixelHeight)
, data, stride, 0);
return target;
}
with multiplying x 1.4 with its size, I can get similar result that I want.
why this difference has occured?
size of origin image is also 638px * 1010px. following image is origin image.
thank you for reading. and I apologize my poor English skill.
Edit
following source is executable with Console .net framework.
I retry with this source code but the result was same. :( ...
following source code is full source code.
you need png file that named "webPrint_back.png". and size 638x1010 . https://dummyimage.com/
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using ZXing;
using ZXing.Common;
using ZXing.QrCode;
using ZXing.QrCode.Internal;
using BarcodeWriter = ZXing.Presentation.BarcodeWriter;
namespace bitmapTest
{
class Program
{
static void Main(string[] args)
{
DrawTextToImageSave("webPrint_back.png");
}
public static void DrawTextToImageSave(string path)
{
//png to bitmap
Image Dummy = Image.FromFile(path);
using (Bitmap bitmap = (Bitmap)Dummy)
{//load the image file
using (Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
var titleFont = new Font("NanumSquareOTF ExtraBold", 18);
var bodyFont = new Font("NanumSquareOTF Regular", 18);
graphics.DrawString("DATE", titleFont, System.Drawing.Brushes.Black, new PointF(401.5f, 863.5f)); //comment 1
graphics.DrawString(DateTime.Now.ToString("yyyy.MM.dd"), bodyFont, System.Drawing.Brushes.Black, new PointF(345, 885f));
graphics.DrawString("LOCATION", titleFont, System.Drawing.Brushes.Black, new PointF(344, 919.5f));
graphics.DrawString(System.DateTime.Now.ToString("yyyyMMddHHmmss") , bodyFont, System.Drawing.Brushes.Black, new PointF(267f, 946f));
WriteableBitmap bitmapimg = Generator128Code("STACKOVERFLOW", 110, 110);
bitmapimg = resize_image(bitmapimg, 1.4); //comment 2
var stream = new MemoryStream();
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapimg));
encoder.Save(stream);
byte[] buffer = stream.GetBuffer();
var qrBitmap = new System.Drawing.Bitmap(new MemoryStream(buffer));
graphics.DrawImage(qrBitmap, 485f, 855f);
}
bitmap.Save( "output_WebPrintBack.png", ImageFormat.Png);
}
}
public static WriteableBitmap Generator128Code(string contents, int width, int height)
{
if (string.IsNullOrEmpty(contents))
{
return null;
}
EncodingOptions options = null;
BarcodeWriter writer = null;
options = new QrCodeEncodingOptions
{
CharacterSet = "UTF-8",
Width = width,
Height = height,
ErrorCorrection = ErrorCorrectionLevel.H,
Margin = 0
};
writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = options
};
WriteableBitmap bitmap = writer.Write(contents);
return bitmap;
}
static WriteableBitmap resize_image(WriteableBitmap img, double scale)
{
BitmapSource source = img;
var s = new ScaleTransform(scale, scale);
var res = new TransformedBitmap(img, s);
return convert_BitmapSource_to_WriteableBitmap(res);
}
static WriteableBitmap convert_BitmapSource_to_WriteableBitmap(BitmapSource source)
{
// Calculate stride of source
int stride = source.PixelWidth * (source.Format.BitsPerPixel / 8);
// Create data array to hold source pixel data
byte[] data = new byte[stride * source.PixelHeight];
// Copy source image pixels to the data array
source.CopyPixels(data, stride, 0);
// Create WriteableBitmap to copy the pixel data to.
WriteableBitmap target = new WriteableBitmap(source.PixelWidth
, source.PixelHeight, source.DpiX, source.DpiY
, source.Format, null);
// Write the pixel data to the WriteableBitmap.
target.WritePixels(new Int32Rect(0, 0
, source.PixelWidth, source.PixelHeight)
, data, stride, 0);
return target;
}
}
}
I found the factor that makes font size is smaller than I expected.
First, source code that I posted works bad with PNG File with "24 bit depth"(without transparent background).
but PNG file with "32 bit depth"(with transparent background), Fontsize works well.
I don't know why It happened.
Second, the barcode made with zxing.net nuget. internally has padding with its border. the problem is that padding size depends on string length. longer string length makes more smaller barcode size and more bigger padding.
following source is my solution for barcode zxing.net nuget
WriteableBitmap bitmapimg = Generator128Code(StaticCommon.localConfigModel.cardBack_QRText, 110, 110);
var stream = new MemoryStream();
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapimg));
encoder.Save(stream);
byte[] buffer = stream.GetBuffer();
var qrBitmap = new System.Drawing.Bitmap(new MemoryStream(buffer));
RectangleF recF = new RectangleF(new PointF(477f, 852f), new SizeF(130, 130));
//ZXING PADDING value, padding size depends on QR encoded string length, so I divide with integer 30 and use remainder
int len = StaticCommon.localConfigModel.cardBack_QRText.Length;
int pad = (int)len / 30;
if (len % 30 > 0) pad++;
RectangleF srecF = new RectangleF(pad * 6f, pad * 6f, 110f - pad * 12f, 110 - pad * 12f);
graphics.DrawImage(qrBitmap, recF, srecF, GraphicsUnit.Pixel);
I solved my problem with engineering way, but I hope someone solve this problem with theoretical way. so I remain this question unsolved.
how to resize an image without loosing its quality in c#.net?
Stream myBlob;
var encoder = new JpegEncoder();using (var output = new MemoryStream())
using (SixLabors.ImageSharp.Image<Rgba32> image = Image.Load(myBlob))
{ var divisor = image.Width / 100;
var height = Convert.ToInt32(Math.Round((decimal)(image.Height/divisor)));
image.Mutate(x => x.Resize(320, 640));
image.Save(output, encoder);
output.Position = 0;
await blockBlob.UploadFromStreamAsync(output);
}
You can use the overloaded Bitmap constructor to create the new re-sized image, as can be seen bellow:
public static Image Resize(Image image, Size size)
{
return (Image)(new Bitmap(image, size));
}
And you call it using:
var result = Resize(image, new Size(320,640));
Here is my code below which i am using to redraw and save the image.
Bitmap bitmap = new Bitmap(HttpContext.Current.Server.MapPath(
filePath + Path.GetFileName(fileName)));
int newWidth = 100;
int newHeight = 100;
int iwidth = bitmap.Width;
int iheight = bitmap.Height;
if (iwidth <= 100)
newWidth = iwidth;
if (iheight <= 100)
newHeight = iheight;
bitmap.Dispose();
// ONCE WE GOT ALL THE INFORMATION, WE'll NOW PROCESS IT.
// CREATE AN IMAGE OBJECT USING ORIGINAL WIDTH AND HEIGHT.
// ALSO DEFINE A PIXEL FORMAT (FOR RICH RGB COLOR).
System.Drawing.Image objOptImage = new System.Drawing.Bitmap(newWidth, newHeight,
System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
// GET THE ORIGINAL IMAGE.
using (System.Drawing.Image objImg =
System.Drawing.Image.FromFile(HttpContext.Current.Server.MapPath(filePath + fileName)))
{
// RE-DRAW THE IMAGE USING THE NEWLY OBTAINED PIXEL FORMAT.
using (System.Drawing.Graphics oGraphic = System.Drawing.Graphics.FromImage(objOptImage))
{
var _1 = oGraphic;
System.Drawing.Rectangle oRectangle = new System.Drawing.Rectangle(0, 0, newWidth, newHeight);
_1.DrawImage(objImg, oRectangle);
}
// On the below lines of code i am getting error while i try to execute
// this code after uploading image. If image size is around 10 kb it will
// not throw any error but if it exceeds then 10 kb then it will.
//SAVE THE OPTIMIZED IMAGE
objOptImage.Save(HttpContext.Current.Server.MapPath(filePath + "TempSubImages/" + fileName),
System.Drawing.Imaging.ImageFormat.Png);**
objImg.Dispose();
}
objOptImage.Dispose();
// FINALLY SHOW THE OPTIMIZED IMAGE DETAILS WITH SIZE.
Bitmap bitmap_Opt = new Bitmap(HttpContext.Current.Server.MapPath(filePath + "TempSubImages/" + Path.GetFileName(fileName)));
byte[] bytes = System.IO.File.ReadAllBytes(HttpContext.Current.Server.MapPath(filePath + "TempSubImages/" + Path.GetFileName(fileName)));
UI.BasePage.TemporaryFile = bytes;
String[] ArrContentType = new String[] { postedFile.ContentType, fileName };
UI.BasePage.TemporaryStrings = ArrContentType;
int iwidth_Opt = bitmap_Opt.Width;
int iheight_Opt = bitmap_Opt.Height;
bitmap_Opt.Dispose();
I want to display thumbnail image in a gridview from file location. How to generate that of .jpeg file?
I am using C# language with asp.net.
You have to use GetThumbnailImage method in the Image class:
https://msdn.microsoft.com/en-us/library/8t23aykb%28v=vs.110%29.aspx
Here's a rough example that takes an image file and makes a thumbnail image from it, then saves it back to disk.
Image image = Image.FromFile(fileName);
Image thumb = image.GetThumbnailImage(120, 120, ()=>false, IntPtr.Zero);
thumb.Save(Path.ChangeExtension(fileName, "thumb"));
It is in the System.Drawing namespace (in System.Drawing.dll).
Behavior:
If the Image contains an embedded thumbnail image, this method
retrieves the embedded thumbnail and scales it to the requested size.
If the Image does not contain an embedded thumbnail image, this method
creates a thumbnail image by scaling the main image.
Important: the remarks section of the Microsoft link above warns of certain potential problems:
The GetThumbnailImage method works well when the requested thumbnail
image has a size of about 120 x 120 pixels. If you request a large
thumbnail image (for example, 300 x 300) from an Image that has an
embedded thumbnail, there could be a noticeable loss of quality in the
thumbnail image.
It might be better to scale the main image (instead
of scaling the embedded thumbnail) by calling the DrawImage method.
The following code will write an image in proportional to the response, you can modify the code for your purpose:
public void WriteImage(string path, int width, int height)
{
Bitmap srcBmp = new Bitmap(path);
float ratio = srcBmp.Width / srcBmp.Height;
SizeF newSize = new SizeF(width, height * ratio);
Bitmap target = new Bitmap((int) newSize.Width,(int) newSize.Height);
HttpContext.Response.Clear();
HttpContext.Response.ContentType = "image/jpeg";
using (Graphics graphics = Graphics.FromImage(target))
{
graphics.CompositingQuality = CompositingQuality.HighSpeed;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.DrawImage(srcBmp, 0, 0, newSize.Width, newSize.Height);
using (MemoryStream memoryStream = new MemoryStream())
{
target.Save(memoryStream, ImageFormat.Jpeg);
memoryStream.WriteTo(HttpContext.Response.OutputStream);
}
}
Response.End();
}
Here is a complete example of how to create a smaller image (thumbnail). This snippet resizes the Image, rotates it when needed (if a phone was held vertically) and pads the image if you want to create square thumbs. This snippet creates a JPEG, but it can easily be modified for other file types. Even if the image would be smaller than the max allowed size the image will still be compressed and it's resolution altered to create images of the same dpi and compression level.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
//set the resolution, 72 is usually good enough for displaying images on monitors
float imageResolution = 72;
//set the compression level. higher compression = better quality = bigger images
long compressionLevel = 80L;
public Image resizeImage(Image image, int maxWidth, int maxHeight, bool padImage)
{
int newWidth;
int newHeight;
//first we check if the image needs rotating (eg phone held vertical when taking a picture for example)
foreach (var prop in image.PropertyItems)
{
if (prop.Id == 0x0112)
{
int orientationValue = image.GetPropertyItem(prop.Id).Value[0];
RotateFlipType rotateFlipType = getRotateFlipType(orientationValue);
image.RotateFlip(rotateFlipType);
break;
}
}
//apply the padding to make a square image
if (padImage == true)
{
image = applyPaddingToImage(image, Color.Red);
}
//check if the with or height of the image exceeds the maximum specified, if so calculate the new dimensions
if (image.Width > maxWidth || image.Height > maxHeight)
{
double ratioX = (double)maxWidth / image.Width;
double ratioY = (double)maxHeight / image.Height;
double ratio = Math.Min(ratioX, ratioY);
newWidth = (int)(image.Width * ratio);
newHeight = (int)(image.Height * ratio);
}
else
{
newWidth = image.Width;
newHeight = image.Height;
}
//start the resize with a new image
Bitmap newImage = new Bitmap(newWidth, newHeight);
//set the new resolution
newImage.SetResolution(imageResolution, imageResolution);
//start the resizing
using (var graphics = Graphics.FromImage(newImage))
{
//set some encoding specs
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.DrawImage(image, 0, 0, newWidth, newHeight);
}
//save the image to a memorystream to apply the compression level
using (MemoryStream ms = new MemoryStream())
{
EncoderParameters encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, compressionLevel);
newImage.Save(ms, getEncoderInfo("image/jpeg"), encoderParameters);
//save the image as byte array here if you want the return type to be a Byte Array instead of Image
//byte[] imageAsByteArray = ms.ToArray();
}
//return the image
return newImage;
}
//=== image padding
public Image applyPaddingToImage(Image image, Color backColor)
{
//get the maximum size of the image dimensions
int maxSize = Math.Max(image.Height, image.Width);
Size squareSize = new Size(maxSize, maxSize);
//create a new square image
Bitmap squareImage = new Bitmap(squareSize.Width, squareSize.Height);
using (Graphics graphics = Graphics.FromImage(squareImage))
{
//fill the new square with a color
graphics.FillRectangle(new SolidBrush(backColor), 0, 0, squareSize.Width, squareSize.Height);
//put the original image on top of the new square
graphics.DrawImage(image, (squareSize.Width / 2) - (image.Width / 2), (squareSize.Height / 2) - (image.Height / 2), image.Width, image.Height);
}
//return the image
return squareImage;
}
//=== get encoder info
private ImageCodecInfo getEncoderInfo(string mimeType)
{
ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
for (int j = 0; j < encoders.Length; ++j)
{
if (encoders[j].MimeType.ToLower() == mimeType.ToLower())
{
return encoders[j];
}
}
return null;
}
//=== determine image rotation
private RotateFlipType getRotateFlipType(int rotateValue)
{
RotateFlipType flipType = RotateFlipType.RotateNoneFlipNone;
switch (rotateValue)
{
case 1:
flipType = RotateFlipType.RotateNoneFlipNone;
break;
case 2:
flipType = RotateFlipType.RotateNoneFlipX;
break;
case 3:
flipType = RotateFlipType.Rotate180FlipNone;
break;
case 4:
flipType = RotateFlipType.Rotate180FlipX;
break;
case 5:
flipType = RotateFlipType.Rotate90FlipX;
break;
case 6:
flipType = RotateFlipType.Rotate90FlipNone;
break;
case 7:
flipType = RotateFlipType.Rotate270FlipX;
break;
case 8:
flipType = RotateFlipType.Rotate270FlipNone;
break;
default:
flipType = RotateFlipType.RotateNoneFlipNone;
break;
}
return flipType;
}
//== convert image to base64
public string convertImageToBase64(Image image)
{
using (MemoryStream ms = new MemoryStream())
{
//convert the image to byte array
image.Save(ms, ImageFormat.Jpeg);
byte[] bin = ms.ToArray();
//convert byte array to base64 string
return Convert.ToBase64String(bin);
}
}
For the asp.net users a little example of how to upload a file, resize it and display the result on the page.
//== the button click method
protected void Button1_Click(object sender, EventArgs e)
{
//check if there is an actual file being uploaded
if (FileUpload1.HasFile == false)
{
return;
}
using (Bitmap bitmap = new Bitmap(FileUpload1.PostedFile.InputStream))
{
try
{
//start the resize
Image image = resizeImage(bitmap, 256, 256, true);
//to visualize the result, display as base64 image
Label1.Text = "<img src=\"data:image/jpg;base64," + convertImageToBase64(image) + "\">";
//save your image to file sytem, database etc here
}
catch (Exception ex)
{
Label1.Text = "Oops! There was an error when resizing the Image.<br>Error: " + ex.Message;
}
}
}
Here is a version based on the accepted answer. It fixes two problems...
Improper disposing of the images.
Maintaining the aspect ratio of the image.
I found this tool to be fast and effective for both JPG and PNG files.
private static FileInfo CreateThumbnailImage(string imageFileName, string thumbnailFileName)
{
const int thumbnailSize = 150;
using (var image = Image.FromFile(imageFileName))
{
var imageHeight = image.Height;
var imageWidth = image.Width;
if (imageHeight > imageWidth)
{
imageWidth = (int) (((float) imageWidth / (float) imageHeight) * thumbnailSize);
imageHeight = thumbnailSize;
}
else
{
imageHeight = (int) (((float) imageHeight / (float) imageWidth) * thumbnailSize);
imageWidth = thumbnailSize;
}
using (var thumb = image.GetThumbnailImage(imageWidth, imageHeight, () => false, IntPtr.Zero))
//Save off the new thumbnail
thumb.Save(thumbnailFileName);
}
return new FileInfo(thumbnailFileName);
}
Here is an example to convert high res image into thumbnail size-
protected void Button1_Click(object sender, EventArgs e)
{
//---------- Getting the Image File
System.Drawing.Image img = System.Drawing.Image.FromFile(Server.MapPath("~/profile/Avatar.jpg"));
//---------- Getting Size of Original Image
double imgHeight = img.Size.Height;
double imgWidth = img.Size.Width;
//---------- Getting Decreased Size
double x = imgWidth / 200;
int newWidth = Convert.ToInt32(imgWidth / x);
int newHeight = Convert.ToInt32(imgHeight / x);
//---------- Creating Small Image
System.Drawing.Image.GetThumbnailImageAbort myCallback = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
System.Drawing.Image myThumbnail = img.GetThumbnailImage(newWidth, newHeight, myCallback, IntPtr.Zero);
//---------- Saving Image
myThumbnail.Save(Server.MapPath("~/profile/NewImage.jpg"));
}
public bool ThumbnailCallback()
{
return false;
}
Source-
http://iknowledgeboy.blogspot.in/2014/03/c-creating-thumbnail-of-large-image-by.html
This is the code I'm using. Also works for .NET Core > 2.0 using System.Drawing.Common NuGet.
https://www.nuget.org/packages/System.Drawing.Common/
using System;
using System.Drawing;
class Program
{
static void Main()
{
const string input = "C:\\background1.png";
const string output = "C:\\thumbnail.png";
// Load image.
Image image = Image.FromFile(input);
// Compute thumbnail size.
Size thumbnailSize = GetThumbnailSize(image);
// Get thumbnail.
Image thumbnail = image.GetThumbnailImage(thumbnailSize.Width,
thumbnailSize.Height, null, IntPtr.Zero);
// Save thumbnail.
thumbnail.Save(output);
}
static Size GetThumbnailSize(Image original)
{
// Maximum size of any dimension.
const int maxPixels = 40;
// Width and height.
int originalWidth = original.Width;
int originalHeight = original.Height;
// Return original size if image is smaller than maxPixels
if (originalWidth <= maxPixels || originalHeight <= maxPixels)
{
return new Size(originalWidth, originalHeight);
}
// Compute best factor to scale entire image based on larger dimension.
double factor;
if (originalWidth > originalHeight)
{
factor = (double)maxPixels / originalWidth;
}
else
{
factor = (double)maxPixels / originalHeight;
}
// Return thumbnail size.
return new Size((int)(originalWidth * factor), (int)(originalHeight * factor));
}
}
Source:
https://www.dotnetperls.com/getthumbnailimage