Текущий архив: 2005.07.31;
Скачать: CL | DM;
Вниз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 вся ветка
Текущий архив: 2005.07.31;
Скачать: CL | DM;
Память: 0.49 MB
Время: 0.043 c