Отзыв о коде для сериализации, десериализации и сохранения изображения - PullRequest
1 голос
/ 21 июля 2009

Вот мой код для сериализации, десериализации и сохранения изображения в файловой системе. Я просмотрел множество примеров сериализации / десериализации и просто хочу получить отзывы, так как уверен, что мой код можно улучшить Любая обратная связь будет принята с благодарностью. Я знаю, что это общая проблема, поэтому надеюсь, что в будущем этот вопрос станет хорошим источником информации для других.

Это пересмотренный код с использованием рекомендаций:

    private void Form1_Load(object sender, EventArgs e)
    {
        RunTest();
    }

    private void RunTest()
    {
        byte[] jpgba = ConvertFileToByteArray("D:\\Images\\Image01.jpg");
        using (Image jpgimg = ConvertByteArrayToImage(jpgba))
        {
            SaveImageToFileSystem(jpgimg, "D:\\Images\\Image01_Copy.jpg");
        }

        byte[] pngba = ConvertFileToByteArray("D:\\Images\\Image02.png");
        using (Image pngimg = ConvertByteArrayToImage(pngba))
        {
            SaveImageToFileSystem(pngimg, "D:\\Images\\Image02_Copy.png");
        }

        byte[] gifba = ConvertFileToByteArray("D:\\Images\\Image03.gif");
        using (Image gifimg = ConvertByteArrayToImage(gifba))
        {
            SaveImageToFileSystem(gifimg, "D:\\Images\\Image03_Copy.gif");
        }

        MessageBox.Show("Test Complete");
        this.Close();
    }

    private static byte[] ConvertFileToByteArray(String FilePath)
    {
        return File.ReadAllBytes(FilePath);
    }

    private static Image ConvertByteArrayToImage(byte[] ImageByteArray)
    {
        using (MemoryStream ms = new MemoryStream(ImageByteArray))
        {
            return Image.FromStream(ms);
        }
    }

    private static void SaveImageToFileSystem(Image ImageObject, string FilePath)
    {
        // ImageObject.Save(FilePath, ImageObject.RawFormat);
        // This method only works with .png files.

        // This method works with .jpg, .png and .gif
        // Need to copy image before saving.
        using (Image img = new Bitmap(ImageObject.Width, ImageObject.Height))
        {
            using (Graphics tg = Graphics.FromImage(img))
            {
                tg.DrawImage(ImageObject, 0, 0);
            }
            img.Save(FilePath, img.RawFormat);
        }
        return;
    }

Ответы [ 3 ]

3 голосов
/ 21 июля 2009

Что я вижу из быстрого взгляда:

Потоки должны быть обернуты в с использованием шаблона (...) , в вашем случае, если во время обработки возникнет исключение, Dispose () не будет вызываться.

using (FileStream fs = new FileStream(FilePath, FileMode.Open))
{
    // Another small optimization, removed unnecessary variable 
    byte[] iba = new byte[(int)fs.Length];
    fs.Read(iba, 0, iba.Length);
}

Вы должны ловить только те исключения, которые ожидаете. Например, в SerializeImage это будет IOException . Поймать все исключения - очень плохая практика.

}
catch (IOException ex)
{

Метод Image.FromStream зависит от потока, поэтому, если вы закроете основной поток и вернете Image, вы можете получить непредсказуемое поведение (в большинстве случаев это будет работать, но иногда возникает ошибка). Поэтому вам нужно создать копию изображения и вернуть его.

using (MemoryStream ms = new MemoryStream(ImageByteArray))
{
    using (Image img = Image.FromStream(ms))
    {
        return new Bitmap(img);
    }
}

Вы не располагаете графический объект и объект img в методе SaveImage (но располагаете ImageObject, см. Следующий абзац). И вообще я не вижу необходимости в такой логике, просто вызовите ImageObject.Save (..., ImageFormat.Png), если вы хотите сохранить изображение с сохранением качества.

В этом же методе (SaveImage) вы располагаете параметр ImageObject. Это также плохая практика в большинстве случаев, рассмотрите возможность удаления этого изображения вне рабочего метода, используя , используя (...) pattern.

1 голос
/ 21 июля 2009

Вот еще немного:

private void RunTest()
{
    // byte array that can be stored in DB
    byte[] iba;

    // image object to display in picturebox or used to save to file system.

    iba = ReadImage("D:\\Images\\Image01.jpg");
    using (Image img = DeserializeImage(iba))
    {
        SaveImage(img, "D:\\Images\\Image01_Copy.jpg");
    }

    iba = ReadImage("D:\\Images\\Image02.png");
    using (Image img1 = DeserializeImage(iba))
    {
        SaveImage(img1, "D:\\Images\\Image02_Copy.png");
    }

    iba = ReadImage("D:\\Images\\Image03.gif");
    using (var img2 = DeserializeImage(iba))
    {
        SaveImage(img2, "D:\\Images\\Image03_Copy.gif");
    }

    MessageBox.Show("Test Complete");
}

private static byte[] ReadImage(String filePath)
{
    // This seems to be the easiest way to serialize an image file
    // however it would be good to take a image object as an argument
    // in this method.
    using (var fs = new FileStream(filePath, FileMode.Open))
    {
        Int32 fslength = Convert.ToInt32(fs.Length);
        var iba = new byte[fslength];
        fs.Read(iba, 0, fslength);
        return iba;
    }
}

private static Image DeserializeImage(byte[] imageByteArray)
{
    using (var ms = new MemoryStream(imageByteArray))
    {
        return Image.FromStream(ms);
    }
}

private static void SaveImage(Image imageObject, string filePath)
{
    // I could only get this method to work for .png files.
    // imageObject.Save(filePath, imageObject.RawFormat);

    // This method works with .jpg, .png and .gif
    // Need to copy image before saving.
    using (Image img = new Bitmap(imageObject.Width, imageObject.Height))
    {
        using (Graphics tg = Graphics.FromImage(img))
        {
            tg.DrawImage(imageObject, 0, 0);
        }

        img.Save(filePath, img.RawFormat);
    }

    return;
}

Обратите внимание, что вы назвали сериализацию просто чтением байтов. Сериализация - это больше, чем вы делаете при сохранении.

Я избавился от всех блоков try / catch. Лучшее, что они сделали для вас, - это сообщило вам, возникла ли проблема при чтении, сохранении или десериализации. Вы можете определить это по трассировке стека, которую вы уничтожали, только отображая ex.Message.

Вы также возвращали null в серьезном исключении, распространяющем ошибку.

Кроме того, я согласен со всем, что сказал арбитр.

0 голосов
/ 21 июля 2009

Как говорит Джон Саундер, сериализация и десериализация - это больше, чем просто чтение необработанных данных из файла. См. Вики на Сериализация

Для изображений в .net вам не нужно использовать что-то большее, чем предоставляемые методы платформы (в большинстве случаев)

Итак, загрузка изображения (десериализация) в .net - это.

using System.Drawing.Image;

Image test;

test = Image.FromFile(@"C:\myfile.jpg")
test = Image.FromStream(myStream); // or you can load from an existing stream

Аналогично, сохранение изображения (сериализация):

test.Save(@"C:\anotherFile.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);

Это основы загрузки и сохранения изображения в .net. Если у вас более конкретный сценарий, задайте другой вопрос.

...