ASP.NET error when uploading, renaming and resizing an image - asp.net

Afternoon, i am trying to upload a file using the asp.net FileUpload control. Before saving the image i need to rename the file with the users GUID, then resize the image to 128px.
However when it goes to save i am getting the error A generic error occurred in GDI+. and i can not work out how to get this sorted.
Could someone look over my code and provide some guidance please
protected void btnUpload_Click(object sender, EventArgs e)
{
Guid userGuid = (Guid)Membership.GetUser().ProviderUserKey;
string directory = Server.MapPath("imgs/users");
string fileExt = Path.GetExtension(fuSample.PostedFile.FileName);
string fileName = userGuid + fileExt;
//Check File ext, make sure its an image!
if (fileExt == ".jpeg" || fileExt == ".jpg" || fileExt == ".png" || fileExt == ".gif")
{
//Now we check to make sure its less than 600kb
if (fuSample.PostedFile.ContentLength < 614400)
{
//Delete an existing file.
if (File.Exists(directory + fileName))
File.Delete(directory + fileName);
// Create a bitmap of the content of the fileUpload control in memory
Bitmap originalBMP = new Bitmap(fuSample.FileContent);
// Calculate the new image dimensions
int origWidth = originalBMP.Width;
int origHeight = originalBMP.Height;
int sngRatio = origWidth / origHeight;
int newWidth = 128;
int newHeight = newWidth / sngRatio;
// Create a new bitmap which will hold the previous resized bitmap
Bitmap newBMP = new Bitmap(originalBMP, newWidth, newHeight);
// Create a graphic based on the new bitmap
Graphics oGraphics = Graphics.FromImage(newBMP);
// Set the properties for the new graphic file
oGraphics.SmoothingMode = SmoothingMode.AntiAlias; oGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Draw the new graphic based on the resized bitmap
oGraphics.DrawImage(originalBMP, 0, 0, newWidth, newHeight);
// Save the new graphic file to the server
newBMP.Save(directory + fileName);
// Once finished with the bitmap objects, we deallocate them.
originalBMP.Dispose();
newBMP.Dispose();
oGraphics.Dispose();
//Success!
}
else
{
//error here, img too big
}
}
else
{
notifybar.Attributes.Add("style", "display:block;");
notifybar.Attributes.Add("class", "failed");
notifyText.Text = "Valid Image files only please! (.png, .jpg, .jpeg, or .gif)";
}
}

It could be something as simple as a file overwrite conflict. There are many dangerous bugs in this code, however, and it's not using RAM very efficiently.
I would suggest a different approach (using the ImageResizer NuGet package):
var j = new ImageJob(fuSample,"~/imgs/users/<guid>.<ext>",
new ResizeSettings("maxwidth=128;maxheight=128"));
j.Build();
string imageUrl = PathUtils.GuessVirtualPath(j.FinalPath)

Related

GDI+ Error - loading image in Asp.net. Student [duplicate]

I create an asp.net 4.0 web application which has a web service for uploading images. I am uploading images by sending the image in form of Base64 string from my mobile app to the web service.
Following is my code:
public string Authenticate(string username, string password, string fileID, string imageData)
{
Dictionary<string, string> responseDictionary = new Dictionary<string, string>();
bool isAuthenticated = true; // Set this value based on the authentication logic
try
{
if (isAuthenticated)
{
UploadImage(imageData);
string result = "success";
var message = "Login successful";
responseDictionary["status"] = result;
responseDictionary["message"] = message;
}
}
catch (Exception ex)
{
responseDictionary["status"] = ex.Message;
responseDictionary["message"] = ex.StackTrace;
}
return new JavaScriptSerializer().Serialize(responseDictionary);
}
private void UploadImage(string uploadedImage)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(uploadedImage);
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)Image.FromStream(ms);
string uploadPath = Server.MapPath("..\\uploads\\") + DateTime.Now.Ticks.ToString() + ".jpeg";
ms.Close();
bitmap.Save(uploadPath, System.Drawing.Imaging.ImageFormat.Jpeg);
bitmap.Dispose();
}
This code was working fine on my local ASP.NET development server and I was able to see the uploaded image in my "uploads" directory. However, after transferring the code to the FTP directory, I am now getting the following error:
A generic error occurred in GDI+
I have checked that the upload directory has proper permission by creating a dummy .aspx page and creating a text file on page_load, and it works fine.
Even after doing google search, I was not able to solve this problem. Can anybody help me fixing this?
Thanks a lot in advance.
Instead of writing directly to files, save your bitmap to a MemoryStream and then save the contents of the stream to disk. This is an old, known issue and, frankly, I don't remember all the details why this is so.
MemoryStream mOutput = new MemoryStream();
bmp.Save( mOutput, ImageFormat.Png );
byte[] array = mOutput.ToArray();
// do whatever you want with the byte[]
In your case it could be either
private void UploadImage(string uploadedImage)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(uploadedImage);
string uploadPath = Server.MapPath("..\\uploads\\") + DateTime.Now.Ticks.ToString() + ".jpeg";
// store the byte[] directly, without converting to Bitmap first
using ( FileStream fs = File.Create( uploadPath ) )
using ( BinaryWriter bw = new BinaryWriter( fs ) )
bw.Write( imageBytes );
}
or
private void UploadImage(string uploadedImage)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(uploadedImage);
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)Image.FromStream(ms);
string uploadPath = Server.MapPath("..\\uploads\\") + DateTime.Now.Ticks.ToString() + ".jpeg";
ms.Close();
// convert to image first and store it to disk
using ( MemoryStream mOutput = new MemoryStream() )
{
bitmap.Save( mOutput, System.Drawing.Imaging.ImageFormat.Jpeg);
using ( FileStream fs = File.Create( uploadPath ) )
using ( BinaryWriter bw = new BinaryWriter( fs ) )
bw.Write( mOutput.ToArray() );
}
}
Furthermore I think it's worth pointing out that when MemoryStream is used, stream must always be closed and save method MUST be called before the stream closure
byte[] byteBuffer = Convert.FromBase64String(Base64String);
MemoryStream memoryStream = new MemoryStream(byteBuffer);
memoryStream.Position = 0;
Bitmap bmpReturn = (Bitmap)Bitmap.FromStream(memoryStream);
bmpReturn.Save(PicPath, ImageFormat.Jpeg);
memoryStream.Close();

how to show image from database in asp:image with linq?

This is my table in database :
And I read the database like :
DataClassesDataContext db = new DataClassesDataContext();
usertable thisuser = db.usertables.First(p => p.username == User.Identity.Name);
So, thisuser.picture is a handle to the image. But how can I show it in asp:image control on my page ?
Edit
I save the picture with this code :
DataClassesDataContext db = new DataClassesDataContext();
usertable thisuser = db.usertables.First(p => p.username == User.Identity.Name);
byte[] filebyte = FileUpload1.FileBytes;
System.Data.Linq.Binary fileBinary = new System.Data.Linq.Binary(filebyte);
thisuser.picture = fileBinary;
db.SubmitChanges();
is there something wrong ?
The ASP.NET Image control loosely represents an <img> tag in HTML. As a result you can only get an image into an HTML doocument by setting the URL to the image content you want to embed in the page.
<img src="images/picture.png" />
This means that you need a mechanism to take an HTTP request asking for an image resource, and return a response containing the image binary data.
With ASP.NET Web API this becomes a trivial operation to implement:
public HttpResponseMessage GetImage(string username)
{
DataClassesDataContext db = new DataClassesDataContext();
usertable thisuser = db.usertables.FirstOrDefault(
p => p.username == username);
if (thisuser == null)
{
return new HttpResponseMessage(HttpStatusCode.NotFound));
}
// Create a stream to return to the user.
var stream = new MemoryStream(thisuser.picture.ToArray());
// Compose a response containing the image and return to the user.
var result = new HttpResponseMessage();
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("image/jpeg");
return result;
}
If you can't use Web API, you'll have to implement an HTTP Handler to do the same job.
In your ASP.NET page, you will have to set the property ImageUrl to the address configured for your controller/handler, including the username as part of the URL.
<asp:Image ImageUrl='<%# GetImage(Eval("IMG_DATA")) %>' />
Above we tell the ASPX engine that we want to take value of column [IMG_DATA], and pass it into method GetImage of the page, which should return a valid image. So, let's implement the method inside our page class:
public string GetImage(object img)
{
return "data:image/jpg;base64," + Convert.ToBase64String((byte[])img);
}
You'll need to create generic handler - lets call it ImageHandler.ashx, and it will be in the root of your web app.
public class ImageHandler : IHttpHandler {
public void ProcessRequest(HttpContext context) {
// here is the tricky part - you don't store image type anywhere (you should)
// assuming jpeg
context.Response.ContentType = "image/jpeg";
DataClassesDataContext db = new DataClassesDataContext();
if (HttpContext.Current.User != null && HttpContext.Current.User.Identity != null) {
var thisuser = db.usertables.First(p => p.username == HttpContext.Current.User.Identity.Name);
if (thisuser != null) {
byte[] buffer = thisuser.picture.ToArray();
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
}
}
}
public bool IsReusable {
get { return false; }
}
}
Then in the page, add:
<asp:Image runat="server" ImageUrl="~/ImageHandler.ashx" />
Few notes:
you should consider caching of the image
you should switch from image sql type to varbinary (http://msdn.microsoft.com/en-us/library/ms187993.aspx)
you should store image mimetype somewhere (if it is jpeg, png, bmp) - preferably in the same table, and server the correct mimetype in the handler
-
if thisuser.picture has a proper path to your image, you can try something like this:
Image im = new Image();
im.ID = "myImg";
im.ImageUrl = thisuser.picture.toString();
this.Controls.Add(im);
I am assuming that you are using web forms (I don't think it makes a difference).
Also, this might require a page refresh. The 'this' is referring to the Page object (in my case).
You can't render it directly using the ASP.NET Image control (or at least not that I'm immediately aware of). Quickly of the top of my head:
Solution 1:
You need some HttpHandler for your images. In your asp:image tag you need an ImageUrl that will be picked up by this specific HttpHandler. There you can write out the image content from the database as bytes using the right MIME type and headers.
Solution 2:
Take a look into embedding data in URLs, perhaps you can write out your image like this and add it to the asp:image ImageUrl like that: https://en.wikipedia.org/wiki/Data_URI_scheme
create ashx page. On it use somthing like this
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "image/jpeg";
Stream strm = new MemoryStream(GetImage(ID));
long length = strm.Length;
byte[] buffer = new byte[length];
int byteSeq = strm.Read(buffer, 0, 2048);
while (byteSeq > 0)
{
context.Response.OutputStream.Write(buffer, 0, byteSeq);
byteSeq = strm.Read(buffer, 0, 2048);
}
}
ON get image method
public static byte[] GetImage(string ImageId)
{
byte[] img = null;
DataTable dt = new DataTable();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "USP_SELECT_GLOBAL_METHOD";
cmd.Parameters.AddWithValue("#EVENT", 5);
cmd.Parameters.AddWithValue("#CODE", ImageId);
cmd.Connection = DL_CCommon.Connection();
SqlDataReader dr = null;
dr = cmd.ExecuteReader();
if (dr.Read())
{
img = (byte[])dr[0];
}
dr.Close();
return img;
}
this method return returns the image as ur ID.
on your aspx page..
Image1.ImageUrl = "somthing.ashx?ID="+userImageID;
I hope it will work. as i have found it worked in my own. Thank you

Insert CSV from file upload control directly to memory stream without physical path

I am not sure if this is possible so it would be nice to have some help.
What I want to do is use a fileupload control in asp.net to select a csv file. Then use my submit button on the page to run my server side code which will take that csv file and put it into memory stream where it will be parsed and then added to collection object.
I do know it's easier to save the csv file to a physical path and then do some kind of cleanup where I delete the file but if possible I would like to do it this way.
See below for code so far:
protected void btnUpload_Click(object sender, EventArgs e)
{
string connectingString = "";
if (ctrlFileUpload.HasFile)
{
string fileName =
Path.GetFileName(ctrlFileUpload.PostedFile.FileName);
string fileExtension =
Path.GetExtension(ctrlFileUpload.PostedFile.FileName);
ReadCsv(fileName);
}
}
protected void ReadCsv(string fileName)
{
// Some logic for parsing csv file in memory stream
}
}
Any ideas? Thanks!
I know this is an old question, but the below code will work for reading your posted text file into a memory stream using a StreamReader and is compatible with .NET 4.0:
protected void ReadCsv()
{
StreamReader reader = new StreamReader(ctrlFileUpload.PostedFile.InputStream);
string content = reader.ReadToEnd();
}
Note, this method is only efficient if you have enough memory on the server to handle larger files for multiple users concurrently. You don't want to use this approach if you have hundreds of users posting files simultaneously to a memory stream and causing your server to crash due to insufficient available memory. You'll also want to check if this is an acceptable method if you're on a shared hosting environment.
Does this help?
This should give you the stream. So you'd make your ReadCsv method accept a reference to the stream, and pass that to it rather than the filename, and work against the stream.
MSDN FileUpload.FileContent Property
//Try below one to capture data in MemoryStream from FileUpload Control
protected void btnFileUpload_Click(object sender, EventArgs e)
{
if (FileUploadControl.HasFile)
{
try
{
#region Capture file data in Memory Stream
byte[] fileData = null;
Stream fileStream = null;
int length = 0;
length = FileUploadControl.PostedFile.ContentLength;
fileData = new byte[length + 1];
fileStream = FileUploadControl.PostedFile.InputStream;
fileStream.Read(fileData, 0, length);
//Use MemoryStream to capture file data
MemoryStream stream = new MemoryStream(fileData);
Session["FileUploaded"] = stream;
#endregion
StreamReader strFile;
using (strFile = new StreamReader(stream))
{
string line;
DataTable dtStudentData = CreateDataTable();
DataRow drStudentRow;
List<String> errorMessages = new List<String>();
// Read and display lines from the file until the end of the file is reached.
while ((line = strFile.ReadLine()) != null)
{
if (line.Trim().Length > 0)
{
System.Threading.Thread.Sleep(1000);
string[] columns = line.Split('\t'); //splitting the line which was read by the stream reader object
Int32 charpos = (Int32)strFile.GetType().InvokeMember("charPos", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField, null, strFile, null);
Int32 charlen = (Int32)strFile.GetType().InvokeMember("charLen",
BindingFlags.DeclaredOnly |
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.GetField
, null, strFile, null);
int lineno = (Int32)strFile.BaseStream.Position - charlen + charpos;
//Add data row in Data Table
drStudentRow = dtStudentData.NewRow();
// TO DO code - Fill data table
dtStudentData.Rows.Add(drStudentRow);
}
}
strFile.Dispose();
dtStudentData.Rows.RemoveAt(0); //Remove the first column since its the column name not necessary to insert in the database table
PopulateStudentInvalidDataGridView(dtStudentData); // Bind Grid
Session["StudentData_FileParsedStudentRegistrtaionTable"] = dtStudentData;
strFile.Close(); //release the stream reader
}
}
catch (Exception ex)
{
String error = ex.Message;
}
}
}

Not able to display an image in repeater control for [thumbnail images]

i have imgae path in datatable[id, path] now this would a value like
ex: id path
1 F:\R&D\RD\RD\Images\a1.JPG;
2 F:\R&D\RD\RD\Images\a2.JPG;
3 F:\R&D\RD\RD\Images\a3.JPG;
now these images are in size width*height (1018*768). now i need to convert these images into thumnail
caling the function
**C_Thumbnails(100, "F:\R&D\RD\RD\Images\a1.JPG", "F:\R&D\RD\RD\Images]thum.jpg")**
public static void C_Thumbnails(int size, string FilePath, string ThumbPath)
{
System.Drawing.Image image = System.Drawing.Image.FromFile(FilePath);
try
{
int thumbHeight, thumbWidth;
decimal h = image.Height;
decimal w = image.Width;
if (image.Height > image.Width)
{
thumbHeight = size;
decimal tWidth = (w / h) * thumbHeight;
thumbWidth = Convert.ToInt32(tWidth);
}
else
{
thumbWidth = size;
decimal tHeight = (h / w) * thumbWidth;
thumbHeight = Convert.ToInt32(tHeight);
}
System.Drawing.Image thumbnailImage = image.GetThumbnailImage(thumbWidth, thumbHeight, null, IntPtr.Zero);
image.Dispose();
thumbnailImage.Save(ThumbPath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (Exception ex)
{
image.Dispose();
throw ex;
}
}
like this i am coverting into thumbnail image. but here i am saving the thumbnail image under the path F:\R&D\RD\RD\Images\thum.jpg .
so is there any way without saving the thumbnail in the disk and how to bind the new thumbnail image in the repeater control and i need to show image there. but if once user clicks on the thumnail image a orignal image should pop up.
if any one have did this functionlity any where let me know
working on this solution from past 2 days.
any help would be greatly appreciated
now after changing code
like this
public void ProcessRequest(HttpContext context)
{
string imageid = context.Request.Params["ImageID"];
string thumbnail = context.Request.Params["thumbnail"];
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString);
connection.Open();
SqlCommand command = new SqlCommand("select Image from Image where ImageID=" + imageid, connection);
SqlDataReader dr = command.ExecuteReader();
dr.Read();
string filePath = dr["image"].ToString();
dr.Close();
if (!System.IO.File.Exists(filePath))
{
//you have a problem
return;
}
if (context.Request.Params["thumbnail"] == "true")
{
//TODO: the thumbnail
// Image thumbnailImage = originalImage.GetThumbnailImage to generate thumbnail then
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "image/" + format;
thumbnailImage.Save(Response.OutputStream, imageFormat);
thumbnailImage.Dispose();
}
else
{ //stream directly the image fromdisk
System.IO.FileStream fs = System.IO.File.OpenRead(filepath);
const int ChunkSize = 10000;
Byte[] buffer = new Byte[ChunkSize];
long dataLengthToRead = fs.Length;
while (dataLengthToRead > 0)
{
int lengthRead = fs.Read(buffer, 0, ChunkSize);
Response.OutputStream.Write(buffer, 0, lengthRead);
System.Web.HttpContext.Current.Response.Flush();
dataLengthToRead = dataLengthToRead - lengthRead;
}
fs.Close();
}
}
}
in repeater control i have added this line of code
','_blank','toolbar=no,menubar=no'))" > '/>
my thumbnail image is not displayed still but once i click my thumbnail image i am able to see the entire image in new pop up
You should use a Photo Image Handler to serve the pages from your disk to the clients.
Then in the repeater control
<a href="ImageHandler.ashx?thumbnail=false&id='<%# Eval("ID")%>'>
<img src="ImageHandler.ashx?thumbnail=true&id='<%# Eval("ID")%>' border='0'/>
</a>
The ideea is not to pass in the actual path/name of the file, but the ID of the item you wish to view. Then the handler will:
public void ProcessRequest(System.Web.HttpContext context)
{
string filePath = //TODO: Get File Path from ItemID = context.Request.Params["id"]
if (!System.IO.File.Exists(filePath))
{
//you have a problem
return;
}
if(context.Request.Params["thumbnail"]=="true")
{
//TODO: the thumbnail
// Image thumbnailImage = originalImage.GetThumbnailImage to generate thumbnail then
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "image/" + format;
thumbnailImage.Save(Response.OutputStream, imageFormat);
thumbnailImage.Dispose();
} else
{ //stream directly the image fromdisk
System.IO.FileStream fs = System.IO.File.OpenRead(filepath);
const int ChunkSize = 10000;
Byte[] buffer = new Byte[ChunkSize];
long dataLengthToRead = fs.Length;
while (dataLengthToRead > 0)
{
int lengthRead = fs.Read(buffer, 0, ChunkSize);
Response.OutputStream.Write(buffer, 0, lengthRead);
System.Web.HttpContext.Current.Response.Flush();
dataLengthToRead = dataLengthToRead - lengthRead;
}
fs.Close();
}
}

ASP.NET Image uploading with Resizing

I have an aspx page which will upload images to server harddisk from client pc
But now i need to change my program in such a way that it would allow me to resize the image while uploading.
Does anyone has any idea on this ? I couldnt not find such properties/methods with Input file server control
Any one there to guide me ?
Once the file has been saved to the server you can use code like this to resize. This code will take care of length/width ratio on the resize.
public static Bitmap CreateThumbnail(string lcFilename, int lnWidth, int lnHeight)
{
System.Drawing.Bitmap bmpOut = null;
try
{
Bitmap loBMP = new Bitmap(lcFilename);
ImageFormat loFormat = loBMP.RawFormat;
decimal lnRatio;
int lnNewWidth = 0;
int lnNewHeight = 0;
if (loBMP.Width < lnWidth && loBMP.Height < lnHeight)
return loBMP;
if (loBMP.Width > loBMP.Height)
{
lnRatio = (decimal)lnWidth / loBMP.Width;
lnNewWidth = lnWidth;
decimal lnTemp = loBMP.Height * lnRatio;
lnNewHeight = (int)lnTemp;
}
else
{
lnRatio = (decimal)lnHeight / loBMP.Height;
lnNewHeight = lnHeight;
decimal lnTemp = loBMP.Width * lnRatio;
lnNewWidth = (int)lnTemp;
}
bmpOut = new Bitmap(lnNewWidth, lnNewHeight);
Graphics g = Graphics.FromImage(bmpOut);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.FillRectangle(Brushes.White, 0, 0, lnNewWidth, lnNewHeight);
g.DrawImage(loBMP, 0, 0, lnNewWidth, lnNewHeight);
loBMP.Dispose();
}
catch
{
return null;
}
return bmpOut;
}
You will not be able to resize "on the fly" since you will need to have the full image before you perform any image transformations. However, after the upload is complete and before you display any results to your user, you can use this basic image resizing method that I've used in a couple of my apps now:
''' <summary>
''' Resize image with GDI+ so that image is nice and clear with required size.
''' </summary>
''' <param name="SourceImage">Image to resize</param>
''' <param name="NewHeight">New height to resize to.</param>
''' <param name="NewWidth">New width to resize to.</param>
''' <returns>Image object resized to new dimensions.</returns>
''' <remarks></remarks>
Public Shared Function ImageResize(ByVal SourceImage As Image, ByVal NewHeight As Int32, ByVal NewWidth As Int32) As Image
Dim bitmap As System.Drawing.Bitmap = New System.Drawing.Bitmap(NewWidth, NewHeight, SourceImage.PixelFormat)
If bitmap.PixelFormat = Drawing.Imaging.PixelFormat.Format1bppIndexed Or _
bitmap.PixelFormat = Drawing.Imaging.PixelFormat.Format4bppIndexed Or _
bitmap.PixelFormat = Drawing.Imaging.PixelFormat.Format8bppIndexed Or _
bitmap.PixelFormat = Drawing.Imaging.PixelFormat.Undefined Or _
bitmap.PixelFormat = Drawing.Imaging.PixelFormat.DontCare Or _
bitmap.PixelFormat = Drawing.Imaging.PixelFormat.Format16bppArgb1555 Or _
bitmap.PixelFormat = Drawing.Imaging.PixelFormat.Format16bppGrayScale Then
Throw New NotSupportedException("Pixel format of the image is not supported.")
End If
Dim graphicsImage As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bitmap)
graphicsImage.SmoothingMode = Drawing.Drawing2D.SmoothingMode.HighQuality
graphicsImage.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
graphicsImage.DrawImage(SourceImage, 0, 0, bitmap.Width, bitmap.Height)
graphicsImage.Dispose()
Return bitmap
End Function
Another approach would to allow the user to adjust the size in the browser and then resize the image as described in other answers.
So take a look at this solution which allows you to upload and crop images with jQuery, jCrop & ASP.NET.
How to resize & Upload Image only for .jpg Extensions :
In upload.aspx page
<asp:FileUpload ID="ProductImage" runat="server"/>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Upload" />
<asp:TextBox runat="server" ID="txtProductName" CssClass="form-control" />
<asp:RequiredFieldValidator runat="server" ControlToValidate="txtProductName" ErrorMessage="The Product name field is required." />
And upload.aspx.cs
For resize
/// <summary>
/// Created By Rajib Chowdhury Mob. 01766-306306; Web: http://onlineshoping.somee.com/
/// Complete This Page Coding On January 05, 2014
/// Programing C# By Visual Studio 2013 For Web
/// Dot Net Version 4.5
/// Database Virsion MSSQL Server 2005
/// </summary>
public bool ResizeImageAndUpload(System.IO.FileStream newFile, string folderPathAndFilenameNoExtension, double maxHeight, double maxWidth)
{
try
{
// Declare variable for the conversion
float ratio;
// Create variable to hold the image
System.Drawing.Image thisImage = System.Drawing.Image.FromStream(newFile);
// Get height and width of current image
int width = (int)thisImage.Width;
int height = (int)thisImage.Height;
// Ratio and conversion for new size
if (width > maxWidth)
{
ratio = (float)width / (float)maxWidth;
width = (int)(width / ratio);
height = (int)(height / ratio);
}
// Ratio and conversion for new size
if (height > maxHeight)
{
ratio = (float)height / (float)maxHeight;
height = (int)(height / ratio);
width = (int)(width / ratio);
}
// Create "blank" image for drawing new image
Bitmap outImage = new Bitmap(width, height);
Graphics outGraphics = Graphics.FromImage(outImage);
SolidBrush sb = new SolidBrush(System.Drawing.Color.White);
// Fill "blank" with new sized image
outGraphics.FillRectangle(sb, 0, 0, outImage.Width, outImage.Height);
outGraphics.DrawImage(thisImage, 0, 0, outImage.Width, outImage.Height);
sb.Dispose();
outGraphics.Dispose();
thisImage.Dispose();
// Save new image as jpg
outImage.Save(Server.MapPath(folderPathAndFilenameNoExtension + ".jpg"), System.Drawing.Imaging.ImageFormat.Jpeg);
outImage.Dispose();
return true;
}
catch (Exception)
{
return false;
}
}
And Button1_Click Event
string filePath = "~\\Image\\";//your normal image path
if (Page.IsValid)
{
HttpPostedFile myFile = ProductImage.PostedFile;//Get Slected Image
int nFileLen = myFile.ContentLength;//Get slected Image Size
string myimag = txtProductName.Text;//Get user input image name
Guid ImageName = Guid.NewGuid();//get unique id
if ((myFile != null) && (nFileLen > 1048576))
{
LabelAddStatus.Text = "minimum size exceed"; //If file image size 1 MB above
}
else
{
try
{
if (ProductImage.HasFile)
{
String fileExtension = System.IO.Path.GetExtension(ProductImage.FileName).ToLower();
String[] allowedExtensions = { ".jpg" };//Declare For Allowed Extension
for (int i = 0; i < allowedExtensions.Length; i++)
{
if (fileExtension == allowedExtensions[i])
{
// Read file into a data stream
byte[] myData = new Byte[nFileLen];
myFile.InputStream.Read(myData, 0, nFileLen);
myFile.InputStream.Dispose();
// Save the stream to disk as temporary file. make sure the path is unique!
System.IO.FileStream newFile
= new System.IO.FileStream(Server.MapPath(filePath + "_temp.jpg"),
System.IO.FileMode.Create);
newFile.Write(myData, 0, myData.Length);
bool success = ResizeImageAndUpload(newFile, filePath + ("thumbs"+myimag + ImageName), 100, 100);//Save image your thumb image path
success = ResizeImageAndUpload(newFile, filePath + (myimag + ImageName), 768, 1024);//Save image your normal image path
//delete the temp file.
newFile.Close();
System.IO.File.Delete(Server.MapPath(filePath + "_temp.jpg"));
LabelAddStatus.Text = "File uploaded.";
}
else
{
LabelAddStatus.Text = "Unable to accept file type..";
}
}
}
}
catch (Exception)
{
//No Exception Message
}
}
}
Thanks...
This is how I did in my project, based on your condition (height/width) you can change the parameter ie(MaxHeight)
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;
}
On Button click:
protected void Button1_Click(object sender, EventArgs e)
{
lblmsg.Text="";
if ((File1.PostedFile != null) && (File1.PostedFile.ContentLength > 0))
{
Guid uid = Guid.NewGuid();
string fn = System.IO.Path.GetFileName(File1.PostedFile.FileName);
string SaveLocation = Server.MapPath("LogoImagesFolder") + "\\" + uid+fn;
try
{
string fileExtention = File1.PostedFile.ContentType;
int fileLenght = File1.PostedFile.ContentLength;
if (fileExtention == "image/png" || fileExtention == "image/jpeg" || fileExtention == "image/x-png")
{
if (fileLenght <= 1048576)
{
System.Drawing.Bitmap bmpPostedImage = new System.Drawing.Bitmap(File1.PostedFile.InputStream);
System.Drawing.Image objImage = ScaleImage(bmpPostedImage, 81);
objImage.Save(SaveLocation,ImageFormat.Png);
lblmsg.Text = "The file has been uploaded.";
lblmsg.Style.Add("Color", "Green");
}
else
{
lblmsg.Text = "Image size cannot be more then 1 MB.";
lblmsg.Style.Add("Color", "Red");
}
}
else {
lblmsg.Text = "Invaild Format!";
lblmsg.Style.Add("Color", "Red");
}
}
catch (Exception ex)
{
lblmsg.Text= "Error: " + ex.Message;
lblmsg.Style.Add("Color", "Red");
}
}
}
You'll need to use the WebClient class to download the remote image.
After that, then you can resize it...Use DrawImage, not GetThumbnailImage. Make sure you dispose of your bitmap and graphics handles.. (use using{}). Set all quality settings to high.
You might want to take a look at the source code for my popular image resizer first... It will help you avoid some common trouble areas.
//Here is another WAY fox!!! i have actually modify the code from You all. HIHI
//First, add one textBox and one FileUpload Control, and a button
//paste this in your code behind file... after public partial class admin : System.Web.UI.Page
string OriPath;
string ImageName;
public Size NewImageSize(int OriginalHeight, int OriginalWidth, double FormatSize)
{
Size NewSize;
double tempval;
if (OriginalHeight > FormatSize && OriginalWidth > FormatSize)
{
if (OriginalHeight > OriginalWidth)
tempval = FormatSize / Convert.ToDouble(OriginalHeight);
else
tempval = FormatSize / Convert.ToDouble(OriginalWidth);
NewSize = new Size(Convert.ToInt32(tempval * OriginalWidth), Convert.ToInt32(tempval * OriginalHeight));
}
else
NewSize = new Size(OriginalWidth, OriginalHeight); return NewSize;
}
//Now, On Button click add the folwing code.
if (FileUpload1.PostedFile != null)
{
ImageName = TextBox1.Text+".jpg";
OriPath = Server.MapPath("pix\\") + ImageName;
//Gets the Full Path using Filecontrol1 which points to actual location in the hardisk :)
using (System.Drawing.Image Img = System.Drawing.Image.FromFile(System.IO.Path.GetFullPath(FileUpload1.PostedFile.FileName)))
{
Size ThumbNailSize = NewImageSize(Img.Height, Img.Width, 800);
using (System.Drawing.Image ImgThnail = new Bitmap(Img, ThumbNailSize.Width, ThumbNailSize.Height))
{
ImgThnail.Save(OriPath, Img.RawFormat);
ImgThnail.Dispose();
}
Img.Dispose();
}
}
//Enjoy. If any problem,, mail me at izacmail#gmail.com
To resize down a image and get smaller sizes just make the changes below
bmpOut = new Bitmap(lnNewWidth, lnNewHeight, **System.Drawing.Imaging.PixelFormat.Format24bppRgb**);
Graphics g = Graphics.FromImage(bmpOut);
as you above a set the imagem to Format24bppRgb PixelFormat.
and when you save the file, you set the ImageFormat also. Like this:
bmpOut.Save(PathImage, System.Drawing.Imaging.ImageFormat.Jpeg);
You can use this, it does a dandy job for me. But it does not handle low res images well for me. Thankfully I down use to many of them. Just sent it the image byte[] and the expected output and you'll be good to go.
public static byte[] ResizeImageFile(byte[] imageFile, int targetSize)
{
using (System.Drawing.Image oldImage = System.Drawing.Image.FromStream(new MemoryStream(imageFile)))
{
Size newSize = CalculateDimensions(oldImage.Size, targetSize);
using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height, PixelFormat.Format32bppRgb))
{
newImage.SetResolution(oldImage.HorizontalResolution, oldImage.VerticalResolution);
using (Graphics canvas = Graphics.FromImage(newImage))
{
canvas.SmoothingMode = SmoothingMode.AntiAlias;
canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
canvas.DrawImage(oldImage, new Rectangle(new Point(0, 0), newSize));
MemoryStream m = new MemoryStream();
newImage.Save(m, ImageFormat.Jpeg);
return m.GetBuffer();
}
}
}
}
private static Size CalculateDimensions(Size oldSize, int targetSize)
{
Size newSize = new Size();
if (oldSize.Width > oldSize.Height)
{
newSize.Width = targetSize;
newSize.Height = (int)(oldSize.Height * (float)targetSize / (float)oldSize.Width);
}
else
{
newSize.Width = (int)(oldSize.Width * (float)targetSize / (float)oldSize.Height);
newSize.Height = targetSize;
}
return newSize;
}
You could resize before sending to the server using an ActiveX control. There is a free ASP.net image uploading component (I believe this is the same one that Facebook actually uses) available here:
http://forums.aurigma.com/yaf_postst2145_Image-Uploader-ASPNET-Control.aspx
Let me know if it works, I am thinking about implementing it in my projects here at work.
Edit: Looks like the wrapper for the object is free, however the actual component itself is going to run you about $200. I confirmed it is the same component Facebook is using though.
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
public partial class admin_AddPhoto : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string reportPath = Server.MapPath("../picnic");
if (!Directory.Exists(reportPath))
{
Directory.CreateDirectory(Server.MapPath("../picnic"));
}
}
protected void PhotoForm_ItemInserting(object sender, FormViewInsertEventArgs e)
{
FormView uploadForm = sender as FormView;
FileUpload uploadedFile = uploadForm.FindControl("uploadedFile") as FileUpload;
if (uploadedFile != null)
{
string fileName = uploadedFile.PostedFile.FileName;
string pathFile = System.IO.Path.GetFileName(fileName);
try
{
uploadedFile.SaveAs(Server.MapPath("../picnic/") + pathFile);
}
catch (Exception exp)
{
//catch exception here
}
try
{
Bitmap uploadedimage = new Bitmap(uploadedFile.PostedFile.InputStream);
e.Values["ImageWidth"] = uploadedimage.Width.ToString();
e.Values["ImageHeight"] = uploadedimage.Height.ToString();
// Make output File Name
char[] splitter = { '.' };
string[] splitFile = pathFile.Split(splitter);
string OutputFilename = splitFile[0] + "s";
System.Drawing.Image.GetThumbnailImageAbort myCallback = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
System.Drawing.Image thumbImage = uploadedimage.GetThumbnailImage(74, 54, myCallback, IntPtr.Zero);
thumbImage.Save(Server.MapPath("../picnic/") + OutputFilename + ".jpg");
e.Values["Thumbnail"] = "./picnic/" + OutputFilename + ".jpg";
}
catch (Exception ex)
{
//catch exception here
}
e.Values["Pic"] = "./picnic/" + pathFile;
e.Values["Url"] = "./picnic/" + pathFile;
e.Values["dateEntered"] = DateTime.Now.ToString();
}
}
public bool ThumbnailCallback()
{
return false;
}
}
This uses a FileUpload and a FormView to insert. Then I use the GetThumnailImage() method provided in System.Drawing.Imaging. You can enter any Width and Height values and it will shrink/stretch accordingly.
uploadedimage.GetThumbnailImage(W, H, myCallback, IntPtr.Zero);
Hope this helps.
The uploading of the image file is performed by ASP.NET 4.0 Client Callbacks. If you are not familiar with client callbacks then I suggest that you take a look at ASP.Net AJAX Control Toolkit AsyncFileUpload Control without page refresh or PostBack in ASP.Net Web Page or ASP.Net AJAX Update Panel. The callback is fired as soon as the file is selected by the user using the file field control.
public string ResizeImageAndSave(int Width, int Height, string imageUrl, string destPath)
{
System.Drawing.Image fullSizeImg = System.Drawing.Image.FromFile(imageUrl);
double widthRatio = (double)fullSizeImg.Width / (double)Width;
double heightRatio = (double)fullSizeImg.Height / (double)Height;
double ratio = Math.Max(widthRatio, heightRatio);
int newWidth = (int)(fullSizeImg.Width / ratio);
int newHeight = (int)(fullSizeImg.Height / ratio);
//System.Drawing.Image.GetThumbnailImageAbort dummyCallBack = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
System.Drawing.Image thumbNailImg = fullSizeImg.GetThumbnailImage(newWidth, newHeight, new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);
//DateTime MyDate = DateTime.Now;
//String MyString = MyDate.ToString("ddMMyyhhmmss") + imageUrl.Substring(imageUrl.LastIndexOf("."));
thumbNailImg.Save(destPath, ImageFormat.Jpeg);
thumbNailImg.Dispose();
return "";
}
public bool ThumbnailCallback() { return false; }
private void ResizeImage(FileUpload fileUpload)
{
// First we check to see if the user has selected a file
if (fileUpload.HasFile)
{
// Find the fileUpload control
string filename = fileUpload.FileName;
// Check if the directory we want the image uploaded to actually exists or not
if (!Directory.Exists(MapPath(#"Uploaded-Files")))
{
// If it doesn't then we just create it before going any further
Directory.CreateDirectory(MapPath(#"Uploaded-Files"));
}
// Specify the upload directory
string directory = Server.MapPath(#"Uploaded-Files\");
// Create a bitmap of the content of the fileUpload control in memory
Bitmap originalBMP = new Bitmap(fileUpload.FileContent);
// Calculate the new image dimensions
int origWidth = originalBMP.Width;
int origHeight = originalBMP.Height;
int sngRatio = origWidth / origHeight;
int newWidth = 100;
int newHeight = newWidth / sngRatio;
// Create a new bitmap which will hold the previous resized bitmap
Bitmap newBMP = new Bitmap(originalBMP, newWidth, newHeight);
// Create a graphic based on the new bitmap
Graphics oGraphics = Graphics.FromImage(newBMP);
// Set the properties for the new graphic file
oGraphics.SmoothingMode = SmoothingMode.AntiAlias;
oGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Draw the new graphic based on the resized bitmap
oGraphics.DrawImage(originalBMP, 0, 0, newWidth, newHeight);
// Save the new graphic file to the server
newBMP.Save(directory + "tn_" + filename);
// Once finished with the bitmap objects, we deallocate them.
originalBMP.Dispose();
newBMP.Dispose();
oGraphics.Dispose();
// Write a message to inform the user all is OK
label.Text = "File Name: <b style='color: red;'>" + filename + "</b><br>";
label.Text += "Content Type: <b style='color: red;'>" + fileUpload.PostedFile.ContentType + "</b><br>";
label.Text += "File Size: <b style='color: red;'>" + fileUpload.PostedFile.ContentLength.ToString() + "</b>";
// Display the image to the user
Image1.Visible = true;
Image1.ImageUrl = #"Uploaded-Files/tn_" + filename;
}
else
{
label.Text = "No file uploaded!";
}
}

Resources