Сохранить поток в файл - PullRequest
2 голосов
/ 25 августа 2009

У меня есть элемент управления загрузкой файлов, который позволяет пользователям загружать изображения, но прежде чем они смогут загружать изображения, я хочу изменить размер этих изображений до размера 640x480, проблема в том, что я не могу понять, что делать дальше. Это то, что у меня есть;

// 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;
} 

Спасибо

Ответы [ 6 ]

1 голос
/ 25 августа 2009

Может быть, что-то вроде

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);
}
0 голосов
/ 25 августа 2009
  1. Ваш текущий код будет пропускать ресурсы при возникновении исключений. Вы всегда должны делать вызовы к .Dispose в блоке finally или catch (в зависимости от того, всегда ли ресурс нуждается в утилизации или только в случае ошибки). попробуй ... наконец, Dispose можно кратко записать с помощью ключевого слова using - избавь себя от головной боли в будущем и попробуй поместить все IDisposables в блок using или try..catch.
  2. Для изменения размера изображений с помощью Windows Forms по умолчанию будет использоваться некачественный ресамплер. Это обычно приводит к плохо выглядящему результату; вам нужно специально установить соответствующий режим интерполяции (см. код ниже).
  3. Если вы сохраняете изображения, у вас могут возникнуть проблемы с настройками кодека изображения: например, кодер jpeg по умолчанию имеет ужасно низкое качество вывода по умолчанию. Это также вам нужно будет установить вручную (см. Ниже).
  4. Наконец, сохранение файла на диск или в базу данных - действительно самая легкая часть всего этого - вместо сохранения в потоке памяти просто выберите параметр потока. Этот параметр затем может быть создан для записи в файл или базу данных в соответствии с потребностями вызывающей стороны.

Я использую следующую функцию для изменения размера изображений (это изменит соотношение сторон):

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;
}

Сохранение файла в формате jpeg может быть выполнено, например, с помощью:

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);
    }
}

, который вы могли бы использовать через что-то вроде ...

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);
}
0 голосов
/ 25 августа 2009

Если вы не используете поток, возвращенный ResizeFromStream, вы также можете изменить этот метод и заставить его возвращать преобразованный Bitmap. А затем используйте Bitmap.Save(<path>), чтобы сохранить изображение в виде файла.

0 голосов
/ 25 августа 2009
FileStream fs=new FileStream("filename",FileMode.Create);
ir.ResizeFromStream(640, fupItemImage.PostedFile.InputStream).WriteTo(fs);
fs.Close();
0 голосов
/ 25 августа 2009

Я только бросил быстрый взгляд, но если вы уже выполнили изменение размера изображения, то все, что вам нужно сделать, это использовать пространство имен System.IO File Class, чтобы сохранить поток памяти в файл, записав байты из потока памяти в объект File, который вы создаете. Если вам нужен пример кода, дайте мне знать.

0 голосов
/ 25 августа 2009

Сброс в файл будет выглядеть примерно так:

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);
}
...