Как уменьшить размер изображения в C # и .NET 3.5? - PullRequest
10 голосов
/ 07 октября 2010

У меня есть снимок экрана, который я делаю в своем мобильном приложении. Снимок экрана занимает около 32 КБ при сохранении в формате PNG на диске.

Я отправляю их на центральный сервер SQL Server, и 32 КБ слишком велики для того количества раз, которое мне потребуется для сохранения этого снимка экрана (примерно 2500 раз в день).

Есть ли какая-нибудь хитрость, которую я могу сделать, чтобы сэкономить меньше?

Вот код, который я сейчас использую для переноса его из Bitmap в байты (для отправки на сервер для хранения):

MemoryStream stream = new MemoryStream();
 _signatureImage.Save(stream, ImageFormat.Png);
 return stream.ToArray();

_signatureImage - это Bitmap и это рассматриваемый скриншот.

Вот пример снимка экрана, который я сохраняю:

Screen Shot Image

Вещи, которые приходят на ум (но я не знаю, как это сделать):

  1. Уменьшите фактическую высоту и ширину изображения (но, надеюсь, таким образом, чтобы это не искажало его).
  2. Измените его на черно-белое изображение (не уверен, что я увижу от этого реальную экономию места)
  3. Сожмите это больше (мне это не очень нравится, потому что тогда это не читается из базы данных).

Обратите внимание, что все это должно быть сделано программно и не может занять очень много времени, поэтому сложные манипуляции с изображениями отсутствуют.

Спасибо за любую помощь.

Ответы [ 7 ]

10 голосов
/ 08 октября 2010
    private static Image ResizeImage(int newSize, Image originalImage)
    {
        if (originalImage.Width <= newSize)
            newSize = originalImage.Width;

        var newHeight = originalImage.Height * newSize / originalImage.Width;

        if (newHeight > newSize)
        {
            // Resize with height instead
            newSize = originalImage.Width * newSize / originalImage.Height;
            newHeight = newSize;
        }

        return originalImage.GetThumbnailImage(newSize, newHeight, null, IntPtr.Zero);
    }

Это должно работать с вашим растровым объектом. Введите и измените размер по высоте или ширине, в зависимости от того, что соответствует размерам вашего изображения.Это также будет поддерживать масштаб.

РЕДАКТИРОВАТЬ:

Вы можете создать новый растровый объект и изменить размер вашего исходного изображения в этот растровый объект.

Bitmap b = new Bitmap(newWidth, newHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;

g.DrawImage(imgToResize, 0, 0, newWidth, newHeight);
g.Dispose();

return (Image)b;

Я неЯ установил Compact Framework, но, похоже, это должно работать на вас.

3 голосов
/ 08 октября 2010

Если глубина цвета не является проблемой, вы можете изменить ее на черно-белый или 16-цветный режим. Должна быть значительная экономия по сравнению с 24-битным (или 32-битным с альфа-каналом) хранилищем png. Еще одна вещь, о которой стоит подумать - это сохранить его в формате .gif в режиме 256 цветов.

Поскольку вы сохраняете данные подписи, я думаю, что изменение размеров изображения было бы плохой идеей. Вы также можете рассмотреть возможность применения сжатия без потерь, такого как zip, но это, вероятно, требует больших вычислительных ресурсов, чем требуется.

2 голосов
/ 08 октября 2010

Измените цветовую палитру на более низкую глубину цвета. Взгляните на этот вопрос (хорошо посмотрите на ответ на самом деле), который показывает конвертацию в 1bpp. Вы можете перейти на 8bpp вместо 1bpp и получить значительную экономию. Механизм конвертации будет таким же, как показано.

EDIT

Думая «из коробки», вы можете также подумать о том, чтобы просто отправить точки данных из верхней части экрана и вектор подписи, чтобы сервер заново создал экран для вас. Если размер действительно является большой проблемой, я бы, вероятно, исследовал это.

РЕДАКТИРОВАТЬ 2

Если простое изменение размера изображения является разумным решением (при этом вы, очевидно, потеряете данные), то вы можете использовать пространство имен Imaging в SDF для создания эскиза, как Алекс объясняет здесь .

1 голос
/ 08 октября 2010

Если приемлемо монохромное изображение, вы можете попробовать TIFF G4 (сжатие без потерь).TIFF G4 известен как очень эффективный по размеру файла для хранения черно-белого изображения.К сожалению, у меня нет какой-либо информации о том, как он сравнивается с PNG, но стоит изучить его.

Здесь - это информация и пример того, как это сделать в C #

0 голосов
/ 12 октября 2010

FWIW, физически сохраняющий образ на сервере SQL, не является оптимальным решением. Если вы используете Sql Server 2008, вам следует обратиться к поддержке файлового потока, которая позволит вам хранить физические образы на диске и получать к ним доступ, как если бы они были внутренними по отношению к SQL Server. Это, скорее всего, избавит вас от необходимости беспокоиться о размере файла.

0 голосов
/ 08 октября 2010

Запуск Fireworks с фотографией, которая не будет такой же, но должна дать идеютот же цвет, и это может быть особенно верно с черным и белым.Вероятно, это также будет зависеть от алгоритма, используемого для преобразования изображения, но вы можете просто пойти с тем, что вы можете найти ...

0 голосов
/ 08 октября 2010

Попробуйте преобразовать в чисто монохромное растровое изображение. Они чрезвычайно малы, поскольку используют только один бит на пиксель.

РЕДАКТИРОВАТЬ: Я лжец. Только что попробовал это в Paint, и это около 40 КБ по сравнению с оригинальным 20 КБ. Я мог бы поклясться, что у них была огромная экономия места, когда я использовал их раньше ...

РЕДАКТИРОВАТЬ РЕДАКТИРОВАТЬ: ОК, очевидно, они имеют огромные сбережения. Просто для этих изображений PNG имеет еще большую экономию. Вместо этого просто попробовал 16-цветное растровое изображение, и оно увеличилось до 150 тыс.

РЕДАКТИРОВАНИЕ РЕДАКТИРОВАНИЕ РЕДАКТИРОВАНИЕ: НО, монохромное растровое изображение увеличивается до 9 КБ, в то время как PNG остается на 20 КБ даже сжатым.


Итак, похоже, что если вы хотите пойти по пути сжатия, вы можете сначала преобразовать в монохромное растровое изображение, а затем сжать для изображений примерно вдвое меньшего размера PNG.

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

...