To reduce the size of image when uploading - c#

In the below code i am uploading a document My aim is if it is a image document i have to reduce its size to 20 kb.Pls help me to do this.
string Uploadpath = ConfigurationManager.AppSettings["SearchFolder"];
string strUploadpath = Uploadpath.TrimEnd("\\".ToCharArray()) + "\\" + strClientName + "\\" + strDocumentFolder + "\\";
DirectoryInfo dInfo = new DirectoryInfo(strUploadpath);
if (!dInfo.Exists)
{
dInfo.Create();
}
if (DocumentsUpload.FileName != null && DocumentsUpload.FileName != string.Empty)
{
DocumentsUpload.SaveAs((strUploadpath) + DocumentsUpload.FileName);
}

An image size depends on few factors (size, resolution, format, compression, etc) and there is no guarantee that you could reduce it in exactly 20 kb without losing the quality. In order to change size of the file you can try to save new image adjusting its properties such as CompositingQuality, InterpolationMode, and quality and compression. For example, CompositingQuality could be set to "HighSpeed" value, InterpolationMode to "Low", etc. It all depends on what kind of images you have and it needs to be tested.
Example
//DocumentsUpload.SaveAs((strUploadpath) + DocumentsUpload.FileName);
Stream stream = DocumentsUpload.PostedFile.InputStream;
Bitmap source = new Bitmap(stream);
Bitmap target = new Bitmap(source.Width, source.Height);
Graphics g = Graphics.FromImage(target);
EncoderParameters e;
g.CompositingQuality = CompositingQuality.HighSpeed; <-- here
g.InterpolationMode = InterpolationMode.Low; <-- here
Rectangle recCompression = new Rectangle(0, 0, source.Width, source.Height);
g.DrawImage(source, recCompression);
e = new EncoderParameters(2);
e.Param[0] = new EncoderParameter(Encoder.Quality, 70); <-- here 70% quality
e.Param[1] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionLZW); <-- here
target.Save(newName, GetEncoderInfo("image/jpeg"), e);
g.Dispose();
target.Dispose();
public static ImageCodecInfo GetEncoderInfo(string sMime)
{
ImageCodecInfo[] objEncoders;
objEncoders = ImageCodecInfo.GetImageEncoders();
for (int iLoop = 0; iLoop <= (objEncoders.Length - 1); iLoop++)
{
if (objEncoders[iLoop].MimeType == sMime)
return objEncoders[iLoop];
}
return null;
}
Hope this helps.

this example works for .Net 4.5+ and upload several images at time. Also resizes the size of the image dynamically according to the value of the variable MaxWidthHeight. Excuse my bad english.
Example
private void UploadResizeImage()
{
string codigo = "";
string dano = "";
string nav = "";
string nombreArchivo = "";
string extension = "";
int cont = 0;
int MaxWidthHeight = 1024; // This is the maximum size that the width or height file should have
int factorConversion = 0;
int newWidth = 0;
int newHeight = 0;
int porcExcesoImg = 0;
Bitmap newImage = null;
string directory = "dano";
System.Drawing.Image image = null;
string targetPath = "";
try
{
if (!String.IsNullOrEmpty(Request.QueryString["codigo"]) && !String.IsNullOrEmpty(Request.QueryString["dano"]) && !String.IsNullOrEmpty(Request.QueryString["nav"]))
{
codigo = Request.QueryString["codigo"].ToString();
dano = Request.QueryString["dano"].ToString();
nav = Request.QueryString["nav"].ToString();
Directory.CreateDirectory(Server.MapPath(directory));
Directory.CreateDirectory(Server.MapPath(directory + "/" + nav));
string fechaHora = DateTime.Now.ToString("yyyyMMdd-HHmmss");
nombreArchivo = codigo + "-" + dano + "-" + fechaHora;
string html = "<h4>Se cargaron con éxito estos archivos al servidor:</h4>";
if (UploadImages.HasFiles)
{
html += "<ul>";
foreach (HttpPostedFile uploadedFile in UploadImages.PostedFiles)
{
cont++;
extension = System.IO.Path.GetExtension(UploadImages.FileName);
targetPath = Server.MapPath("~/" + directory + "/" + nav + "/").ToString() + nombreArchivo + "-" + cont.ToString() + extension;
if (extension.ToLower() == ".png" || extension.ToLower() == ".jpg")
{
Stream strm = null;
strm = uploadedFile.InputStream;
//strm = UploadImages.PostedFile.InputStream;
using (image = System.Drawing.Image.FromStream(strm))
{
string size = image.Size.ToString();
int width = image.Width;
int height = image.Height;
if (width > MaxWidthHeight || height > MaxWidthHeight)
{
porcExcesoImg = (width * 100) / MaxWidthHeight; // excessive size in percentage
factorConversion = porcExcesoImg / 100;
newWidth = width / factorConversion;
newHeight = height / factorConversion;
newImage = new Bitmap(newWidth, newHeight);
var graphImage = Graphics.FromImage(newImage);
graphImage.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphImage.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphImage.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
var imgRectangle = new Rectangle(0, 0, newWidth, newHeight);
graphImage.DrawImage(image, imgRectangle);
newImage.Save(targetPath, image.RawFormat);
}
else
{
uploadedFile.SaveAs(targetPath);
}
html += "<li>" + String.Format("{0}", uploadedFile.FileName) + "</li>";
}
}
}
html += "</ul>";
listofuploadedfiles.Text = html;
}
else
{
listofuploadedfiles.Text = "No se ha selecionado ninguna imagen!";
}
}
else
{
listofuploadedfiles.Text = "No se recibieron los parámetros para poder cargar las imágenes!";
}
}
catch (Exception ex)
{
listofuploadedfiles.Text = ex.Message.ToString();
}
}

Related

C# Getting error when generating tiles from big image

the sample panorama image url https://upload.wikimedia.org/wikipedia/commons/3/3b/360%C2%B0_Hoher_Freschen_Panorama_2.jpg which i saved in my pc and generate tile from that image programmatically and got
error like out of memory
this line throw the error Bitmap bmLevelSource =
(Bitmap)Bitmap.FromFile(levelSourceImage);
here is my program code in c# which throw the error
double maxZoom = 5;
string FILEPATH = #"C:\test\img.jpg";
string TARGETFOLDER = #"C:\test\Src";
bool REMOVEXISTINGFILES = true;
if (!System.IO.File.Exists(FILEPATH))
{
Console.WriteLine("file not exist");
return;
}
if (maxZoom >= 10)
{
Console.WriteLine("Scale multiplier should be an integer <=10");
return;
}
//Read image
Bitmap bmSource;
try
{
bmSource = (Bitmap)Bitmap.FromFile(FILEPATH);
}
catch
{
Console.WriteLine("image file not valid");
return;
}
//check directory exist
if (!System.IO.Directory.Exists(TARGETFOLDER))
{
System.IO.Directory.CreateDirectory(TARGETFOLDER);
}
else if (REMOVEXISTINGFILES)
{
string[] files = System.IO.Directory.GetFiles(TARGETFOLDER);
foreach (string file in files)
System.IO.File.Delete(file);
string[] dirs = System.IO.Directory.GetDirectories(TARGETFOLDER);
foreach (string dir in dirs)
System.IO.Directory.Delete(dir, true);
}
int actualHeight = bmSource.Height;
int actualWidth = bmSource.Width;
if (((actualHeight % 256) != 0)
||
((actualWidth % 256) != 0))
{
Console.WriteLine("image width and height pixels should be multiples of 256");
return;
}
int actualResizeSizeWidth = 1;
int level = 0;
while (level <= maxZoom)
{
string leveldirectory = System.IO.Path.Combine(TARGETFOLDER, String.Format("{0}", level));
if (!System.IO.Directory.Exists(leveldirectory))
System.IO.Directory.CreateDirectory(leveldirectory);
int rowsInLevel = Convert.ToInt32(Math.Pow(2, level));
actualResizeSizeWidth = 256 * rowsInLevel;
//create image to parse
int actualResizeSizeHeight = (actualHeight * actualResizeSizeWidth) / actualWidth;
Bitmap resized = new Bitmap(bmSource, new Size(actualResizeSizeWidth, actualResizeSizeHeight));
string levelSourceImage = System.IO.Path.Combine(leveldirectory, "level.png");
resized.Save(levelSourceImage);
for (int x = 0; x < rowsInLevel; x++)
{
string levelrowdirectory = System.IO.Path.Combine(leveldirectory, String.Format("{0}", x));
if (!System.IO.Directory.Exists(levelrowdirectory))
System.IO.Directory.CreateDirectory(levelrowdirectory);
Bitmap bmLevelSource = (Bitmap)Bitmap.FromFile(levelSourceImage);
//generate tiles
int numberTilesHeight = Convert.ToInt32(Math.Ceiling(actualResizeSizeHeight / 256.0));
for (int y = 0; y < numberTilesHeight; y++)
{
Console.WriteLine("Generating Tiles " + level.ToString() + " " + x.ToString() + " " + y.ToString()); int heightToCrop = actualResizeSizeHeight >= 256 ? 256 : actualResizeSizeHeight;
Rectangle destRect = new Rectangle(x * 256, y * 256, 256, heightToCrop);
//croped
Bitmap bmTile = bmLevelSource.Clone(destRect, System.Drawing.Imaging.PixelFormat.DontCare);
//full tile
Bitmap bmFullTile = new Bitmap(256, 256);
Graphics gfx = Graphics.FromImage(bmFullTile);
gfx.DrawImageUnscaled(bmTile, 0, 0);
bmFullTile.Save(System.IO.Path.Combine(levelrowdirectory, String.Format("{0}.png", y)));
bmFullTile.Dispose();
bmTile.Dispose();
}
}
level++;
}
i comment the below code when i run the program
if (((actualHeight % 256) != 0)
||
((actualWidth % 256) != 0))
{
Console.WriteLine("image width and height pixels should be multiples of 256");
return;
}
what is the fault for which i got the error called "Out of Memory"
Thanks
Edit
actual image height and width was 1250 and 2500.
actualResizeSizeWidth 256
actualResizeSizeHeight 128
i include a panorama image url in this post at top. can u plzz download url and execute my code at your end to see memory issue is coming?
Code Update
i modify the code a bit and dispose some Bitmap.
dispose like this way
bmLevelSource.Dispose(); and resized.Dispose();
while (level <= maxZoom)
{
string leveldirectory = System.IO.Path.Combine(TARGETFOLDER, String.Format("{0}", level));
if (!System.IO.Directory.Exists(leveldirectory))
System.IO.Directory.CreateDirectory(leveldirectory);
int rowsInLevel = Convert.ToInt32(Math.Pow(2, level));
actualResizeSizeWidth = 256 * rowsInLevel;
//create image to parse
int actualResizeSizeHeight = (actualHeight * actualResizeSizeWidth) / actualWidth;
Bitmap resized = new Bitmap(bmSource, new Size(actualResizeSizeWidth, actualResizeSizeHeight));
string levelSourceImage = System.IO.Path.Combine(leveldirectory, "level.png");
resized.Save(levelSourceImage);
for (int x = 0; x < rowsInLevel; x++)
{
string levelrowdirectory = System.IO.Path.Combine(leveldirectory, String.Format("{0}", x));
if (!System.IO.Directory.Exists(levelrowdirectory))
System.IO.Directory.CreateDirectory(levelrowdirectory);
Bitmap bmLevelSource = (Bitmap)Bitmap.FromFile(levelSourceImage);
//generate tiles
int numberTilesHeight = Convert.ToInt32(Math.Ceiling(actualResizeSizeHeight / 256.0));
for (int y = 0; y < numberTilesHeight; y++)
{
Console.WriteLine("Generating Tiles " + level.ToString() + " " + x.ToString() + " " + y.ToString()); int heightToCrop = actualResizeSizeHeight >= 256 ? 256 : actualResizeSizeHeight;
Rectangle destRect = new Rectangle(x * 256, y * 256, 256, heightToCrop);
//croped
Bitmap bmTile = bmLevelSource.Clone(destRect, System.Drawing.Imaging.PixelFormat.DontCare);
//full tile
Bitmap bmFullTile = new Bitmap(256, 256);
Graphics gfx = Graphics.FromImage(bmFullTile);
gfx.DrawImageUnscaled(bmTile, 0, 0);
bmFullTile.Save(System.IO.Path.Combine(levelrowdirectory, String.Format("{0}.png", y)));
bmFullTile.Dispose();
bmTile.Dispose();
}
bmLevelSource.Dispose();
}
level++;
resized.Dispose();
}
please see my bit modified code and give suggestion now.

cannot find part of path while storing image after resizing it mvc

I am resizing image after upload to the folder.I have stored the path in db in this format
/Content/Uploads//e1f1d755-2b6c-4ec0-8b5e-0a5fa569292c.Img0001.jpg
But on resizing image i haven given the same the path i have saved it in a variable path.But it is appearing in this form C:\Content\Uploads\e1f1d755-2b6c-4ec0-8b5e-0a5fa569292c.Img0001.jpg which causing error in saving resized image.cannot find part of path
C:\Content\Uploads\e1f1d755-2b6c-4ec0-8b5e-0a5fa569292c.Img0001.jpg
Here is my code:
[HttpPost]
public ActionResult UploadPic(FileManagement fmanage, HttpPostedFileBase file)
{
var path = String.Empty;
var directory = "/Content/Uploads/";
if (file != null && file.ContentLength > 0)
{
String FileExtn = System.IO.Path.GetExtension(file.FileName).ToLower();
if (!(FileExtn == ".jpg" || FileExtn == ".png" || FileExtn == ".gif"))
{
ViewBag.error = "Only jpg, gif and png files are allowed!";
}
else
{
var fileName = string.Format("{0}.{1}", Guid.NewGuid(), Path.GetFileName(file.FileName));
path = Path.Combine(directory + "/", fileName);
file.SaveAs(Server.MapPath(path));
using (var input = new Bitmap(file.InputStream))
{
int width;
int height;
if (input.Width > input.Height)
{
width = 128;
height = 128 * input.Height / input.Width;
} //if
else
{
height = 128;
width = 128 * input.Width / input.Height;
} //else
using (var thumb = new Bitmap(width, height))
using (var graphic = Graphics.FromImage(thumb))
{
graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
graphic.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
graphic.DrawImage(input, 0, 0, width, height);
using (var output = System.IO.File.Create(path))
{
thumb.Save(output, System.Drawing.Imaging.ImageFormat.Jpeg);
} //using
} //using
}
}
How can i have the same path while storing resized image.Thanks in advance for help.
Please try the following:
Instead of:
var directory = "/Content/Uploads/";
do this:
var directory = "~/Content/Uploads/";
Then replace:
path = Path.Combine(directory + "/", fileName);
with:
path = Path.Combine(Server.MapPath(directory), fileName);

C# graphics.drawImage() crops my Image

I am trying to put an image on a bigger image. But the inner image was cropped after drawImage(). Here is my code:
Bitmap im = new Bitmap("D:\\Steffen\\New folder\\I1\\I1\\" + filename + ".png");
int sizeX = im.Width;
int sizeY = im.Height;
int size = 0;
bool isWidth = false;
if (sizeX > sizeY)
{
size = sizeX; isWidth = true;
}
else if(sizeY > sizeX)
{
size = sizeY; isWidth = false;
}
filename = filename + "New";
Bitmap bg = new Bitmap(size,size);
SolidBrush brush = new SolidBrush(Color.Aqua);
using (Graphics g = Graphics.FromImage(bg))
{
g.FillRectangle(brush, 0, 0, size, size);
if (isWidth==true)
{
g.DrawImage(im, 0, (size - sizeY) / 2);
}
else if(isWidth==false)
{
g.DrawImage(im, (size-sizeX)/2, 0);
}
}
Thanks in advance
My guess would be the resolution of the image is the issue:
Try it like this:
Bitmap im = new Bitmap("D:\\Steffen\\New folder\\I1\\I1\\" + filename + ".png");
im.SetResolution(96F, 96F);

Would have only saved the resized images

I want it to only saves the resized images so have tried to do so. It deletes the original image again after it has been uploaded but cannot because it says the image is being used by another process. Please help.
Cannot simply remove where it stores the original because it uses it to resize.
I use this code to save the files:
string tempPath = "Galleryt";
string imgPath = "Gallery";
string savePath = Path.Combine(Request.PhysicalApplicationPath, tempPath);
string imgSavePath = Path.Combine(Request.PhysicalApplicationPath, imgPath);
string imgSavePath2 = Path.Combine(Request.PhysicalApplicationPath, imgPath);
string ProductImageNormal = Path.Combine(imgSavePath, imageName + Fileupload1.PostedFile.FileName);
string ProductImagetemp = Path.Combine(savePath, "t__" + imageName + Fileupload1.PostedFile.FileName);
string ProductImagetemp2 = Path.Combine(imgSavePath2, "b__" + imageName + Fileupload1.PostedFile.FileName);
string extension = Path.GetExtension(Fileupload1.PostedFile.FileName);
switch (extension.ToLower())
{
case ".png": goto case "Upload";
case ".gif": goto case "Upload";
case ".jpg": goto case "Upload";
case "Upload": Fileupload1.PostedFile.SaveAs(ProductImageNormal);
ImageTools.GenerateThumbnail(ProductImageNormal, ProductImagetemp, 250, 350, true, "heigh");
ImageTools.GenerateThumbnail(ProductImageNormal, ProductImagetemp2, 600, 600, true, "heigh");
Label1.Text = "";
break;
default:
Label1.Text = "Status: Denne filtype er ikke tilladt";
return;
}
if i try to delete the original file just after with code
File.Delete(Server.MapPath("~/Gallery/" + imageName + Fileupload1.PostedFile.FileName));
the method of GenerateThumbnail
public static void GenerateThumbnail(string filePath, string OriginalFile, int width, int height, bool retainAspect, string quality)
{
Bitmap bitmapNew;
float fx, fy, f;
int widthTh, heightTh;
int widthOrig, heightOrig;
bitmapNew = new Bitmap(filePath);
if (retainAspect)
{
widthOrig = bitmapNew.Width;
heightOrig = bitmapNew.Height;
fx = widthOrig / width;
fy = heightOrig / height;
f = Math.Max(fx, fy);
if (f<1)
{
f=1;
}
widthTh = (int)(widthOrig/f);
heightTh = (int)(heightOrig/f);
}
else
{
widthTh = width;
heightTh = height;
}
Size newSize = new Size(widthTh, heightTh);
using(Bitmap thumb = new Bitmap((System.Drawing.Image)bitmapNew, newSize))
{
Graphics g = Graphics.FromImage(thumb);
Int64 qualityLevel = 25L;
if (quality == "high")
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
qualityLevel = 95L;
}
if (quality == "medium" || quality == "low")
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
if (quality =="medium")
qualityLevel = 65L;
}
System.Drawing.Imaging.ImageCodecInfo codec = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()[1];
System.Drawing.Imaging.EncoderParameters eParams = new System.Drawing.Imaging.EncoderParameters(1);
eParams.Param[0]=new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qualityLevel);
//Her genereres den nye thumbnail
thumb.Save(OriginalFile, codec, eParams);
thumb.Dispose();
}
}
The problem is located in code we cannot see, GenerateThumbnail(). Guessing at the way it might work, it creates a bitmap from ProductImageNormal. That puts a lock on the file which prevents it from being deleted. You'll have to call the bitmap's Dispose() method to release the lock.
If the ImageTools.GenerateThumbnail method can take a Stream, consider writing the PostedFile to a [MemoryStream][1] and passing that to this method before saving the thumbnails, or even using PostedFile.InputStream directly if possible. This way the original image is only ever in memory and you do not even save it to disk.

create fixed size thumbnail dynamically on listview control

how to create fixed size thumbnail dynamically and resize image in listview best fit the size of the thumbnail.
private void Treeview1_AfterSelect(System.Object sender, System.Windows.Forms.TreeViewEventArgs e)
{
if (folder != null && System.IO.Directory.Exists(folder))
{
try
{
DirectoryInfo dir = new DirectoryInfo(#folder);
foreach (FileInfo file in dir.GetFiles())
{
try
{
imageList.ImageSize = new Size(136, 136);
imageList.ColorDepth = ColorDepth.Depth32Bit;
Image img = new Bitmap(Image.FromFile(file.FullName));
Graphics g = Graphics.FromImage(img);
g.DrawRectangle(Pens.Red, 0, 0, img.Width - 21, img.Height - 21);
//g.DrawRectangle(Pens.Red, 0, 0, img.Width, img.Height);
imageList.Images.Add(img);
}
catch
{
Console.WriteLine("This is not an image file");
}
}
for (int j = 0; j < imageList.Images.Count; j++)
{
this.ListView1.Items.Add("Item" + j);
this.ListView1.Items[j].ImageIndex = j;
}
this.ListView1.View = View.LargeIcon;
this.ListView1.LargeImageList = imageList;
//this.ListView1.DrawItem += new DrawListViewItemEventHandler(ListView1_DrawItem);
//import(folder);
}
catch (Exception ex)
{
}
}
I have code in this answer specifically for resizing images along with resolution:
public void GenerateThumbNail(HttpPostedFile fil, string sPhysicalPath,
string sOrgFileName,string sThumbNailFileName,
ImageFormat oFormat, int rez)
{
try
{
System.Drawing.Image oImg = System.Drawing.Image.FromStream(fil.InputStream);
decimal pixtosubstract = 0;
decimal percentage;
//default
Size ThumbNailSizeToUse = new Size();
if (ThumbNailSize.Width < oImg.Size.Width || ThumbNailSize.Height < oImg.Size.Height)
{
if (oImg.Size.Width > oImg.Size.Height)
{
percentage = (((decimal)oImg.Size.Width - (decimal)ThumbNailSize.Width) / (decimal)oImg.Size.Width);
pixtosubstract = percentage * oImg.Size.Height;
ThumbNailSizeToUse.Width = ThumbNailSize.Width;
ThumbNailSizeToUse.Height = oImg.Size.Height - (int)pixtosubstract;
}
else
{
percentage = (((decimal)oImg.Size.Height - (decimal)ThumbNailSize.Height) / (decimal)oImg.Size.Height);
pixtosubstract = percentage * (decimal)oImg.Size.Width;
ThumbNailSizeToUse.Height = ThumbNailSize.Height;
ThumbNailSizeToUse.Width = oImg.Size.Width - (int)pixtosubstract;
}
}
else
{
ThumbNailSizeToUse.Width = oImg.Size.Width;
ThumbNailSizeToUse.Height = oImg.Size.Height;
}
Bitmap bmp = new Bitmap(ThumbNailSizeToUse.Width, ThumbNailSizeToUse.Height);
bmp.SetResolution(rez, rez);
System.Drawing.Image oThumbNail = bmp;
bmp = null;
Graphics oGraphic = Graphics.FromImage(oThumbNail);
oGraphic.CompositingQuality = CompositingQuality.HighQuality;
oGraphic.SmoothingMode = SmoothingMode.HighQuality;
oGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
Rectangle oRectangle = new Rectangle(0, 0, ThumbNailSizeToUse.Width, ThumbNailSizeToUse.Height);
oGraphic.DrawImage(oImg, oRectangle);
oThumbNail.Save(sPhysicalPath + sThumbNailFileName, oFormat);
oImg.Dispose();
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}

Categories