views:

635

answers:

6

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

+1  A: 

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);
}
Instantsoup
You may need to rewind the position of `imgStream` first, by setting `imgStream.Position = 0`.
Fredrik Mörk
FWIW, it's perfectly legal for bytesRead != length but bytesRead != 0 and the stream imgStream is not empty, if imgStream is e.g. a NetworkStream. `while (bytesRead != 0)` is safer.
Barry Kelly
(I know imgStream is a memory stream in this case, but it's worth knowing the semantic contract of `Stream` in general when copying from one stream to another.)
Barry Kelly
Rather than copy the memory stream to the output stream manually, you'd be better off saving the image directly to the output stream.
Eamon Nerbonne
A: 

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);
}
Wolfwyrd
A: 

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.

intelex
Thank you. Please post an example code.
A: 
FileStream fs=new FileStream("filename",FileMode.Create);
ir.ResizeFromStream(640, fupItemImage.PostedFile.InputStream).WriteTo(fs);
fs.Close();
adatapost
Thank you. I'll try this one.
It created a file but it's empty. I tried to upload an image by the way and there was nothing there.
A: 

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.

Peter van der Heijden
A: 
  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);
}
Eamon Nerbonne