5

I'm trying to resize my jpg image uploaded by using FileUpload control and convert it into byte before saving it to database (SQL Server 2008) as (varbinary(MAX)). What I have done and code show below was that I manage to convert it into byte and save into database as varbinary(MAX). I wish to know how to I resize the image before doing all those function. Do help me out. Thanks!

Read the file

string filePath = FileUpload1.PostedFile.FileName;
string filename = Path.GetFileName(filePath);
string ext = Path.GetExtension(filename);

Set the contenttype based on File Extension

string contenttype = String.Empty;            
switch (ext)
{
   case ".jpg":
   contenttype = "image/jpg";
   break;
}

Convert into byte and save into database using varbinary

if (contenttype != String.Empty)
{
            Stream fs = FileUpload1.PostedFile.InputStream;

            BinaryReader br = new BinaryReader(fs);

            Byte[] bytes = br.ReadBytes((Int32)fs.Length);

            //insert the file into database
            string strQuery = "insert into MemberReport(username, typeofcrime, location, crdatetime, citizenreport, image1, image2, image3, image4, image5)" +
               " values ('" + username + "','" + typeofcrime + "','" + location.Trim() + "','" + datetime + "','" + detail.Trim() + "', @Data, @Data2, @Data3, @Data4, @Data5)";
            SqlCommand cmd = new SqlCommand(strQuery);
            cmd.Parameters.Add("@Data", SqlDbType.Binary).Value = bytes;
            cmd.Parameters.Add("@Data2", SqlDbType.Binary).Value = bytes2;
            cmd.Parameters.Add("@Data3", SqlDbType.Binary).Value = bytes3;
            cmd.Parameters.Add("@Data4", SqlDbType.Binary).Value = bytes4;
            cmd.Parameters.Add("@Data5", SqlDbType.Binary).Value = bytes5;
            InsertUpdateData(cmd);

            lblMessage.ForeColor = System.Drawing.Color.Green;
            lblMessage.Text = "Report Sent!";

        }
        else
        {
            lblMessage.ForeColor = System.Drawing.Color.Red;
            lblMessage.Text = "File format not recognised." +
              " Upload Image formats";
        }

InsertUpdateData method

    private Boolean InsertUpdateData(SqlCommand cmd)
    {
        SqlConnection con = new SqlConnection("Data Source=localhost; Initial Catalog=project; Integrated Security=True");
        cmd.CommandType = CommandType.Text;
        cmd.Connection = con;
        try
        {
            con.Open();
            cmd.ExecuteNonQuery();
            return true;
        }
        catch (Exception ex)
        {
            Response.Write(ex.Message);
            return false;
        }
        finally
        {
            con.Close();
            con.Dispose();
        }
Dan Teesdale
  • 1,823
  • 15
  • 26
XiAnG
  • 245
  • 2
  • 9
  • 25
  • Read these articles an you can achieve what you want: [**Resize an Image C#**](http://stackoverflow.com/questions/1922040/resize-an-image-c-sharp) , [**Resizing an Image**](http://stackoverflow.com/questions/87753/resizing-an-image-without-losing-any-quality), [**C# Image to Byte Array and Byte Array to Image Converter Class**](http://www.codeproject.com/Articles/15460/C-Image-to-Byte-Array-and-Byte-Array-to-Image-Conv) – John Woo Jun 27 '13 at 02:19

1 Answers1

13

You need to convert the uploaded file to an Image object, which can be done simply with:

Image uploaded = Image.FromStream(FileUpload1.PostedFile.InputStream);

Next, figure out how big you want the image to be. Let's say you want the largest dimension to be 256 pixels, and maintain aspect ratio. Some code adapted from the CodeProject article Resizing an Image On-The-Fly using .NET:

int originalWidth = uploaded.Width;
int originalHeight = uploaded.Height;
float percentWidth = (float)256 / (float)originalWidth;
float percentHeight = (float)256 / (float)originalHeight;
float percent = percentHeight < percentWidth ? percentHeight : percentWidth;
int newWidth = (int)(originalWidth * percent);
int newHeight = (int)(originalHeight * percent);

Now create a new Bitmap object to contain the resized image (from the same CodeProject article) and draw the original image to it:

Image newImage = new Bitmap(newWidth, newHeight);
using (Graphics g = Graphics.FromImage(newImage))
{
    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
    g.DrawImage(uploaded, 0, 0, newWidth, newHeight);
}

And finally, convert back to bytes to save into the database:

byte[] results;
using (MemoryStream ms = new MemoryStream())
{
    ImageCodecInfo codec = ImageCodecInfo.GetImageEncoders().FirstOrDefault(c => c.FormatID == ImageFormat.Jpeg.Guid);
    EncoderParameters jpegParms = new EncoderParameters(1);
    jpegParms.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
    newImage.Save(ms, codec, jpegParms);
    results = ms.ToArray();
}

I took the long route to set the quality level of the output. If you don't mind what compression level is used, a simple img.Save(ms, ImageFormat.Jpeg); call replaces the first 4 lines inside the using code block.

Check out the CodeProject article I mentioned above for more information on resizing images, and read C# Image to Byte Array and Byte Array To Image Converter Class (also on CodeProject) for more on converting images to/from byte arrays.


The last part, inserting the image into a database table. I'll assume Microsoft SQL, and do a very simple table insert.

Table is defined as:

CREATE TABLE [Images](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [ImageData] [varbinary](max) NULL,
    CONSTRAINT [PK_Images] PRIMARY KEY CLUSTERED 
    (
        [ID] ASC
    ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

And the code to insert the image data into the table:

static string connString = "Data Source=localhost; Initial Catalog=project; Integrated Security=True";

public static int InsertImage(byte[] imgdata)
{
    using (SqlConnection conn = new SqlConnection(connString))
    {
        conn.Open();

        using (SqlCommand cmd = new SqlCommand("INSERT INTO Images(ImageData) OUTPUT inserted.ID VALUES(@p1)", conn))
        {
            cmd.Parameters.AddWithValue("@p1", imgdata);

            int res = (int)cmd.ExecuteScalar()
            return res;
        }
    }
}

The returned value is the auto-increment value generated by SQL for the record.

Or to update an existing image:

public static void UpdateImage(int id, byte[] imgdata)
{
    using (SqlConnection conn = new SqlConnection(connString))
    {
        conn.Open();
        using (SqlCommand cmd = new SqlCommand("UPDATE Images SET ImageData = @p1 WHERE ID = @p2", conn))
        {
            cmd.Parameters.AddWithValue("@p1", imgdata);
            cmd.Parameters.AddWithValue("@p2", id);

            cmd.ExecuteNonQuery();
        }
    }
}
f0rfun
  • 716
  • 4
  • 14
  • 36
Corey
  • 15,524
  • 2
  • 35
  • 68
  • `Image uploaded = Image.FromStream(FileUpload1.PostedFile.InputStream);` this line give error : system.web.ui.webcontrol.image does not contain a definition for FromStream – XiAnG Jun 27 '13 at 06:21
  • Wrong `Image` class. You need to add a reference to `System.Drawing` or use `System.Drawing.Image uploaded = System.Drawing.Image.FromStream(FileUpload1.PostedFile.InputStream);` to specify the correct class. – Corey Jun 27 '13 at 22:17
  • @JasonAJXiang Add `using System.Drawing.Imaging;` to the uses block of your code to get the `ImageCodecInfo`, `EncoderParameters` and `EncoderParameter` classes as well. Since you already have a conflict with the `Image` class I'd stick with fully specifying the namespace path for it like in my last comment. – Corey Jun 27 '13 at 22:21
  • The method u post is resize base on the image width and height right? Is there anyway to make it resize with a specify width and height? And also if I have 5 fileupload control in my project I have to use the method 5 times or there anyway to call the function with any fileupload control? – XiAnG Jun 28 '13 at 01:21
  • @JasonAJXiang The code I posted will resize the image so that the largest dimension (height or width) will be 256 pixels after resize, with the same aspect ratio as the input. So if you upload an image that is 4000x1000 pixels, the output will be 256x64 pixels in size. If you just want a specific size, and don't care about aspect ratio, you can skip the calculations and just set newWidth and newHeight to whatever you want them to be. This might stretch the image out of shape, depending on what you upload. – Corey Jun 28 '13 at 02:43
  • Thanks for ur explaination. I still new to all this code, how do I save those images into sql server as varbinary after using the method above? – XiAnG Jun 28 '13 at 02:57
  • @JasonAJXiang The code produces a `byte[]` result which you can pass to an SQL insert query as the value for your varbinary field. Will write some simple code and add to the answer. – Corey Jun 28 '13 at 03:13