2010-10-07 6 views
9

У меня есть снимок экрана, который я принимаю в своем мобильном приложении. Снимок экрана занимает около 32 КБ при сохранении в виде png на диске.Как уменьшить размер изображения в C# и .NET 3.5?

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

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

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

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

_signatureImage является Bitmap и скриншот в вопросе.

Вот пример скриншота я спасительный:

Screen Shot Image

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

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

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

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

+0

Я не вижу изображение, которое вы опубликовали (http-фильтрация на работе). Каковы размеры? – Kendrick

+0

@ Kendrick Это 480 x 640. – jdmichal

ответ

10
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. Тип и изменение размера или ширины, в зависимости от того, что подходит для ваших размеров изображения. Он также будет поддерживать масштаб.

EDIT:

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

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, но, похоже, это сработает для вас.

+0

Это хорошо выглядит. Но я не могу ее легко использовать. Я должен был указать это, но это приложение находится на Compact Framework, а GetThumbnailImage не находится в компактной структуре. Если дело доходит до него, я могу изменить размер изображения на стороне сервера, но я предпочел бы отправить меньшее изображение по воздуху, если это возможно. – Vaccano

+0

В любом случае вы должны избегать GetThumbnailImage - он подходит только для изображений размером 40x40 или меньше. –

3

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

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

+0

Любые подсказки о том, как это сделать на C#? – Vaccano

+0

Не лично, но быстрый поиск показал эту ссылку: http://www.microsoft.com/downloads/en/details.aspx?FamilyID=554acd82-d87d-43c6-a984-8c625387b198&displaylang=en Выбранная цитата: «В .NET Compact Framework нет простого метода для сохранения объектов Bitmap или получения обработчика растрового изображения из объекта Bitmap, поэтому для доступа к данным пиксельных изображений битмапа необходимо использовать немного обмана ». – arootbeer

+0

Продукт моей компании, DotImage Photo, может сделать это и является бесплатным SDK. Просто вызовите GetChangedPixelFormat() на AtalaImage - пропустите в индексированном формате, а затем сохраните с помощью AtalaImage.Save(). https://www.atalasoft.com/photofree –

0

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

EDIT: Я лжец. Просто попробовал это в Paint, и это около 40 тысяч по сравнению с оригинальными 20k. Я мог бы поклясться, что у них была огромная экономия пространства, когда я использовал их раньше ...

EDIT EDIT: Хорошо, по-видимому, они имеют огромную экономию. Просто для этих изображений PNG имеет еще более значительную экономию. Просто попробовал 16-цветное растровое изображение, и это взорвало его до 150 тыс.

EDIT EDIT EDIT: НО, монохромное растровое изображение молнии до 9k байт, в то время как PNG остается на 20k даже застегнутым молнией.


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

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

+0

Я не уверен точно, как окна хранят свои растровые файлы, но я знаю, что они полностью несжаты. .png, по крайней мере, имеет некоторое сжатие. – arootbeer

0

розжига Фейерверки с фотографией, которая не будет такой же, но должен дать представление

66% quality JPG with no smoothing is 17.5k 
PNG8 with 256 colours is 58K (down to 42 using websnap palette) 
PNG8 with black and white palette is 14k 

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

2

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

EDIT

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

EDIT 2

Если просто изменение размера изображения является разумным решением (вы, очевидно, потерять данные в этом), то вы можете использовать пространство имен визуализации в SDF, чтобы создать миниатюру в Alex explains here.

1

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

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

0

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

Смежные вопросы