Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Media";
Текущий архив: 2005.07.31;
Скачать: [xml.tar.bz2];

Вниз

Cжатие jpg до определенного размера   Найти похожие ветки 

 
seregka   (2005-03-18 20:17) [0]

Доброго времени суток!

Нужно сжать картинку *.jpg (либо прежние размеры, но компрессия, либо изменять размеры, а процент сжатия jpg прежний). Как мне сделать так, чтобы сжатие прекратилось при достижении определенного размера файла в кбайтах. Например, картинку А.jpg сжимаем, пока она не станет 100 Кб.


 
programania ©   (2005-03-19 02:45) [1]

Сравнивать размер файла с нужным значением,
изменять качество в нужную сторону,
уменьшать изменение качества
и прекращать сжимать когда изменение
качества равно 1, точность размера будет +-2%.
А еще можно сосчитать качество по размеру картинки
и степени изменений цветов, это быстрее, но менее точно.
Могу подробней, но судя по вопросу это не поможет.


 
seregka   (2005-03-19 09:41) [2]

programania ©   (19.03.05 02:45) [1]
А еще можно сосчитать качество по размеру картинки
и степени изменений цветов, это быстрее, но менее точно.
Могу подробней, но судя по вопросу это не поможет.
---
Скажите, а можно это сделать без сохранения измененнных изображений в файл. Т.е. если меня устроит сжатия, тогда я его сохраняю, если нет - ау ревуар.
С этой точки зрения, как мне подсчитать размер изображения в КБ.


 
programania ©   (2005-03-19 22:27) [3]

>Скажите, а можно это сделать без сохранения измененнных изображений в файл.

Конечно можно в поток
mm:tmemoryStream;
jpegImage:tJpegImage;
....
mm:=tmemoryStream.Create;
jpegImage.SaveToStream(mm);
if mm.size<100000 then jpegImage.SaveToFile("I.jpg");

>С этой точки зрения, как мне подсчитать размер изображения в КБ.

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


 
seregka   (2005-03-19 23:18) [4]

Как соотносятся размер потока с размером картинки в kb?


 
programania ©   (2005-03-20 01:51) [5]

1024:1


 
seregka   (2005-03-20 09:12) [6]

thanks


 
seregka   (2005-03-27 22:42) [7]

Добрый вечер!

Я с потоками поработал. Когда открывает файл, то правильно
показывает размер (КБ*1024, как Вы и говорили). Но после
сжатия показывает размер потока, который не соотв. размеру
сохраняемого из него файла. Например, если я сжимаю картинку в два раза, то отношение потока к полученному jpg 1:10, если же сжимаю на 3/4, то 1:15.

В чем косяк?


 
programania ©   (2005-03-28 02:36) [8]

Никаких косяков нет,
что пишем то и получаем и в потоке и в файле:

program Project1;
uses Forms,windows,jpeg,classes,Dialogs,Sysutils,graphics;

{$R *.RES}
var
mm:tmemoryStream;
jpegImage:tJpegImage;
b:tbitmap;

begin
mm:=tmemoryStream.Create;
jpegImage:=tJpegImage.create;
jpegImage.CompressionQuality:=60;
b:=tbitmap.create;

b.width:=200;
b.height:=200;
b.Canvas.textOut(0,0,"текст");

jpegImage.assign(b);
jpegImage.SaveToStream(mm);
showMessage(intToStr(mm.size));
jpegImage.SaveToFile("I.jpg");
mm.free;
jpegImage.free;
end.


 
seregka   (2005-03-28 08:19) [9]

Спасибо, что помогаете.
Извиняюсь, с размерами потоков сам ступил.
Но вот проблему с jpg осталась. Суть ее в том, предсказать размер выходного изображения нельзя (или я так думаю). Для компрессии я использую встроенную в GraphicEx линейную интерполяцию. У меня на 700/256 на сжатие одной картинки 2032х1524 уходит 7-10 секунд. Можно, конечно, сравнивать файл больше или меньше порога, и если больше, то опять его сжимать,  но это очень долгая операция. Мне нужно что-то быстрое (относительно).


 
programania ©   (2005-03-28 20:03) [10]

> Мне нужно что-то быстрое (относительно).

Даже при упаковке потока, как в упаковщиках и кодировщиках
невозможно заранее точно предсказать размер результата
Поэтому например при кодировке в divX применяют 2 прохода
и ничего, ждут несколько часов, а не то что 7-10 сек.
А упаковка в jpeg вообще состоит из нескольких этапов
и каждый должен пройти до конца по всей картинке.
Подумайте еще раз для чего это надо.
Например я это сделал чтобы уминать много картинок
до нужного размера CD или дискеты и все происходит автоматически,
поэтому время не так важно, можете оценить скорость:
http://programania.com/ENJOL.ZIP 830kb
подробнее:
http://programania.com/i09_ru.htm  3kb
там же кнопкой J можете посмотреть график зависимости размера файла jpg
от качества, что интересно, он мало зависит от содержания и размера картинки
это можно использовать для примерного подбора качества,
чтобы получить нужный размер файла за одно сжатие.


 
seregka   (2005-03-28 21:05) [11]

Да-м, мне долго еще подобную программу ваять. Может быть повторюсь, но как вы просчитывали сжатие (см. график). Извиняюсь за тупизну, но просто так не могу понять.

И еще вопрос: если не секрет, как сделать подобный футуристический дизайн. Мне понравился Ваш очень. Хотелось и у себя нечто подобное. Поплагиатим немножко, если Вы не против. Преподу понравится :-))


 
programania ©   (2005-03-28 21:43) [12]

>но как вы просчитывали сжатие

Да также как как в [3] и [8] jpegImage.SaveToStream(mm);
через 5,3  CompressionQuality  ничего хитрого тут нет.

>как сделать подобный футуристический дизайн

использую компонент KS Development newsgroup"ThemeEngine" ksdev.com
как и пишу в about с доработкой исходников
Главное что мне от него нужно это возможность рисовать все элементы самому,
а дальше дело техники: программой можно нарисовать что угодно
и скины не нужны.
Например, в статьях была статья о заливках.

>Поплагиатим немножко, если Вы не против. Преподу понравится
Конечно я не против и готов помочь,
но такие вещи можно сделать только для собственного
удовольствия, а не для препода.


 
seregka   (2005-03-28 21:58) [13]

Я так делаю:
procedure TMainForm.Button2Click(Sender: TObject);
var jpeg:tjpegimage;
   bitmap:tbitmap;
   imw,imh,compression,size:integer;
   stream:tmemorystream;
   start:longint;
begin

start:=gettickcount;
Jpeg := TjpegImage.Create;
Jpeg.LoadFromFile(filenam);
Bitmap := TBitmap.Create;
bitmap.Assign(Jpeg);
Jpeg.Free;

ImW := Bitmap.Width;
ImH := Bitmap.Height;

if not Bitmap.Empty then
begin
try
 Bitmap.PixelFormat := pf24Bit;
 Compression := 95;
 Stream := TMemoryStream.Create;

 repeat
  Stream.Clear;
  Jpeg:= TJpegImage.Create;
  Jpeg.Assign(Bitmap);
  Jpeg.CompressionQuality := Compression;
  Jpeg.SaveToStream (Stream);
  size := Stream.Size;
Jpeg.Free;
  Compression:=compression-5;

   until size <= StrToInt(labelededit1.Text)*1024;

     Bitmap.Free;
     Stream.SaveTostream(md);
   
   finally
      Stream.Free;
   end;
 end;
end;


работает относительно приемлимо.
Но одна проблема:
мне нужно перекидывать bitmap в поток md. На выходе этой процедуры получается jpeg-поток (stream). Мне нужно именно не сжатый поток, так как с изображением после сжатия еще нужно/можно поиграться (эффекты).
Если я делаю так после repeat...until

Jpeg := TjpegImage.Create;
Jpeg.LoadFromStream(Stream);
Bitmap := TBitmap.Create;
bitmap.Assign(Jpeg);
bitmap.savetostream(md);
Jpeg.Free;

то выкидывает ошибку 42 Неправильный JPEG

Я уже устал с этой программкой. Постучитесь мне на мыло, пожалуйста, nstav@mail.ru, а то Ваше возвращает демон с ошибкой.
Есть предложение икры на бутерброд.


 
programania ©   (2005-03-29 19:03) [14]

может перед Jpeg.LoadFromStream(Stream);
установить поток на начало
stream.seek(0,soFromBeginning);

>после сжатия еще нужно/можно поиграться (эффекты).
сжатие лучше делать в конце всех игр
один раз и навсегда иначе вся возня с подбором теряет смысл.

Послал письмо с моей
перекодировкой картинок в другой размер файла или картинки
и подбором качества от 100 с уменьшением шага в 2 раза
до максимальной точности размера файла,
может чем поможет

>Ваше возвращает демон с ошибкой
А мне приходит масса бессмысленных писем
но без бутербродов.



Страницы: 1 вся ветка

Форум: "Media";
Текущий архив: 2005.07.31;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.033 c
4-1117688968
Strech
2005-06-02 09:09
2005.07.31
Модальные окна


14-1120844696
Kerk
2005-07-08 21:44
2005.07.31
Сдохло колесико у мышки :(


9-1113763228
Yegorchic
2005-04-17 22:40
2005.07.31
Как определить виден ли объект на сцене через определённую камеру


4-1117804136
Fedor
2005-06-03 17:08
2005.07.31
пропало окно программы, помогите найти, плз


1-1121062314
KIR
2005-07-11 10:11
2005.07.31
Изображения неправильной формы





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский