Ryan
Ryan

Reputation:

Save stream to file

I have a fileupload control that allows users to upload images but before they can upload images I want to resize thomse images to mas 640x480 size the problem is I can't figure out what to do next. This is what I have;

// CALL THE FUNCTION THAT WILL RESIZE THE IMAGE
protected void btnUploadFile_Click(object sender, EventArgs e)
{
    Stream imgStream = ir.ResizeFromStream(640, fupItemImage.PostedFile.InputStream);

    // What to do next? 
}

// THE FUNCTION THAT WILL RESIZE IMAGE THEN RETURN AS MEMORY STREAM
public MemoryStream ResizeFromStream(int MaxSideSize, Stream Buffer)
{
    int intNewWidth;
    int intNewHeight;
    System.Drawing.Image imgInput = System.Drawing.Image.FromStream(Buffer);

    // GET IMAGE FORMAT
    ImageFormat fmtImageFormat = imgInput.RawFormat;

    // GET ORIGINAL WIDTH AND HEIGHT
    int intOldWidth = imgInput.Width;
    int intOldHeight = imgInput.Height;

    // IS LANDSCAPE OR PORTRAIT ?? 
    int intMaxSide;

    if (intOldWidth >= intOldHeight)
    {
        intMaxSide = intOldWidth;
    }
    else
    {
        intMaxSide = intOldHeight;
    }


    if (intMaxSide > MaxSideSize)
    {
        // SET NEW WIDTH AND HEIGHT
        double dblCoef = MaxSideSize / (double)intMaxSide;
        intNewWidth = Convert.ToInt32(dblCoef * intOldWidth);
        intNewHeight = Convert.ToInt32(dblCoef * intOldHeight);
    }
    else
    {
        intNewWidth = intOldWidth;
        intNewHeight = intOldHeight;
    }

    // CREATE NEW BITMAP
    Bitmap bmpResized = new Bitmap(imgInput, intNewWidth, intNewHeight);

    // SAVE BITMAP TO STREAM
    MemoryStream imgMStream = new MemoryStream();
    bmpResized.Save(imgMStream, imgInput.RawFormat);

    // RELEASE RESOURCES
    imgInput.Dispose();
    bmpResized.Dispose();
    Buffer.Close();

    return imgMStream;
} 

Thank you

Upvotes: 2

Views: 2500

Answers (6)

Eamon Nerbonne
Eamon Nerbonne

Reputation: 48066

  1. Your current code will leak resources when faced with exceptions. You should always place calls to .Dispose in a finally or catch block (depending on whether the resource always needs disposing, or only needs disposing in case of error). try...finally Dispose can succinctly be written with the using keyword - Save yourself future headaches and try and place all IDisposables in a using or try..catch block.
  2. Resizing images using Windows Forms will use a low-quality resampler by default. This leads generally to bad-looking output; you'll need to specifically set the appropriate interpolation mode (see below for code).
  3. If you're saving images, you may run into image codec settings issues: the default jpeg encoder, for instance, has a terribly low output quality by default. This too you will need to manually set (see below).
  4. Finally, saving the file to disk or database is really the easiest part of it all - instead of saving to a memorystream, simply take a stream parameter instead. This parameter can then be constructed to write to a file or a database as needed by the caller.

I use the following function to resize images (this will change the aspect ratio):

public static Bitmap Resize(Image oldImage, int newWidth, int newHeight)
{
    Bitmap bitmap = null;
    try
    {
        bitmap = new Bitmap(newWidth, newHeight);
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.PixelOffsetMode = PixelOffsetMode.HighQuality;
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.DrawImage(oldImage, new Rectangle(0, 0, newWidth, newHeight));
        }
    }
    catch
    {
        if (bitmap != null) bitmap.Dispose();
        throw;
    }
    return bitmap;
}

Saving a file as jpeg could be performed for instance via:

public static void SaveImageAsJpeg(Image image, Stream outputStream, int quality)
{
    ImageCodecInfo jpgInfo = ImageCodecInfo.GetImageEncoders()
        .Where(codecInfo => codecInfo.MimeType == "image/jpeg").First();
    using (EncoderParameters encParams = new EncoderParameters(1))
    {
        encParams.Param[0] = new EncoderParameter(Encoder.Quality,(long)quality);
        //quality should be in the range [0..100]
        image.Save(outputStream, jpgInfo, encParams);
    }
}

which you could use via something along the lines of...

using(var origImage=Image.FromStream(inputStream, true, true))
{
    //set newWidth, newHeight however you wish; determine outputFilePath
    using(var newImage = Resize(origImage, newWidth, newHeight))
    using(var outputStream = File.Open(outputFilePath, FileMode.Create))
        SaveImageAsJpeg(newImage,outputStream, 90);
}

Upvotes: 0

heijp06
heijp06

Reputation: 11788

If you are not using the stream returned by ResizeFromStream you could also change that method and make it return the converted Bitmap. And then use Bitmap.Save(<path>) to save the image as file.

Upvotes: 0

KV Prajapati
KV Prajapati

Reputation: 94645

FileStream fs=new FileStream("filename",FileMode.Create);
ir.ResizeFromStream(640, fupItemImage.PostedFile.InputStream).WriteTo(fs);
fs.Close();

Upvotes: 0

intelex
intelex

Reputation: 11

I only took a quick glance, but if you have already performed the image re size successfully then all you need to do is use the System.IO name space File Class to save the Memory Stream to a file by writing out the bytes from the Memory Stream to the File object you create. If you need a code example let me know.

Upvotes: 0

Wolfwyrd
Wolfwyrd

Reputation: 15916

Dumping to a file will look something like:

using (FileStream fsOut = new FileStream("my\\file\\path.img", FileMode.Create))
using (MemoryStream msImg = new MemoryStream(ir.ResizeFromStream(640 ...)) )
{
    byte[] imgData = msImg.ToArray();
    fsOut.Write(imgData, 0, imgData.Length);
}

Upvotes: 0

Instantsoup
Instantsoup

Reputation: 15265

Maybe something like

int length = 256;
int bytesRead = 0;
Byte[] buffer = new Byte[length];
using (FileStream fs = new FileStream(filename, FileMode.Create))
{
  do
  {
    bytesRead = imgStream.Read(buffer, 0, length);
    fs.Write(buffer, 0, bytesRead);
  }
  while (bytesRead == length);
}

Upvotes: 1

Related Questions