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

Вниз

Как быстро уменьшить изображение ?   Найти похожие ветки 

 
sco ©   (2006-02-04 21:11) [0]

Я при загрузке проги делая загрузку 24 рисунков достаточно большого размера (~1024-768), точнее их миниатюр(150х150). И ето всё занимает 8 секунд. Когда я закончу прогу у меня будет 120 рисунков, так вот прога будет грузится ~45 секунд! Так конечно не пойдёт. Я знаю что можно поисать способ облегчения например грузить по мере надобности, но думаю что я просто что-то криво очень делаю миниатюры. Всего 24 рисунка и целых 8 сек. Притом что у меня камп быстрый, а там где прога будет юзаться стоят Пентиумы 1-2. Скажите как правильно, БЫСТРО, сделать из большого рисунка - маеленькую копию. Вот мой код, он оптимален, или долго грузится из-за того что код очень кривой?:

function ResizeImage(bitmp: TBitmap; wid, hei: Integer): Boolean;
var
TmpBmp: TBitmap;
ARect: TRect;
begin
Result := False;
try
 TmpBmp:=TBitmap.Create;
 try
  TmpBmp.Width  := wid;
  TmpBmp.Height := hei;
  ARect := Rect(0,0, wid, hei);
  TmpBmp.Canvas.StretchDraw(ARect, Bitmp);
  bitmp.Assign(TmpBmp);
 finally
  TmpBmp.Free;
 end;
 Result := True;
except
 Result := False;
end;
end;

procedure MadeMiniImageList;
var
i: longInt;
BitMap,ItogBitMap: TBitMap;
ci: TImage;
begin
BitMap:=TBitMap.Create;
ItogBitMap:=TBitMap.Create;
ItogBitMap.Width:=SizeMiniWidth;
ItogBitMap.Height:=SizeMiniHeight;

with MainF do
begin
 MiniImageList.Clear;
 if Length(Data)>0 then
 for i:=1 to Length(Data) do
 begin
  //=================== показ загрузки ======
  ZastF.LoadI.Width:=(((i*100) div Length(Data))*ZastF.HideI.width) div 100;
  ZastF.LoadI.Refresh;
  //=================== создание миниатюры ======
  if FileExists(DataDir+Data[i-1].FileName) then
  begin
   BitMap:=LoadJPEG(DataDir+Data[i-1].FileName);
   if Max(BitMap.Width,BitMap.Height)=BitMap.Width
    then ResizeImage(BitMap,SizeMiniWidth,Round(BitMap.Height*SizeMiniWidth/BitMap.Width))
     else ResizeImage(BitMap,Round(SizeMiniHeight*BitMap.Width/BitMap.Height),SizeMiniHeight);
   BitMap.Dormant;
   ItogBitMap.Canvas.Rectangle(0,0,ItogBitMap.Width,ItogBitMap.Height);
   ItogBitmap.Canvas.Draw(
    Round((SizeMiniWidth-BitMap.Width)/2),
    Round((SizeMiniHeight-BitMap.Height)/2),BitMap);
   MiniImageList.Add(ItogBitMap,nil);
  end;
 end;
end;
BitMap.Free;
ItogBitMap.Free;
end;


 
PAVIA ©   (2006-02-05 01:37) [1]

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


 
PAVIA ©   (2006-02-05 01:57) [2]

А зачем BitMap.Dormant; стоит выкинуть будет быстрее.


 
sco ©   (2006-02-05 15:12) [3]

BitMap.Dormant; ставлю вот зачем
Когда битмап загрузит рисунок она его адаптирует под всякие там proportional-ы и strechi-ы. Но сам битмап остаётся тот же. После dormand-а битмап мтановится таким каким мы его видим. Понял експерементально.
Значит другого пути нет? ASDSee их конкретно быстро делает! Может есть таки алгоритм?


 
Sco ©   (2006-02-05 15:15) [4]

PAVIA: "Только можно сразу рисовать по середине."
Обьясни, плиз, а то я не понял.


 
Sapersky   (2006-02-05 16:51) [5]

BitMap:=LoadJPEG(DataDir+Data[i-1].FileName);

Если рисунки - jpeg, то, возможно, их загрузка тормозит больше создания миниатюр. Можно грузить jpeg в уже уменьшенном в 2, 4, 8 раз виде. Или использовать IJL (Intel Jpeg Library), которая быстрее для большинства jpeg в 2-3 раза.
Ну и, как уже было предложено, грузить "на ходу", т.е. либо в отдельном потоке, либо после загрузки каждого рисовать его и делать ProcessMessages.

ASDSee их конкретно быстро делает!

ASDSee, кроме того что использует приведённые выше методы, сохраняет один раз сделанные миниатюры в своём кэше и потом грузит оттуда. Собственно, этим "грешит" и встроенная гляделка WinXP - скрытый файлик thumbs.db в папках с картинками замечал?


 
antonn ©   (2006-02-05 17:50) [6]

внесу свое имхо:
вынести TmpBmp: TBitmap; из процедуры ResizeImage(), сздавать его один раз, когда нужно построить все миниатюры, а не при каждой. а еще лучше типа этого (без содержимого ResizeImage()):

BitMap:=LoadJPEG(DataDir+Data[i-1].FileName); //в общем - грузим...
BitMap.canvas.copyrect(rect(0,0,100,100),BitMap.canvas,rect(0,0,BitMap.width,BitMap.height));
BitMap.width:=100;
BitMap.height:=100;
MiniImageList.Add(BitMap);


ItogBitmap.Canvas.Draw() - фуфел, используйте canvas.copyrect() в крайнем случае


 
sco ©   (2006-02-06 10:48) [7]

to: antonn: Твой способ не срабатывает! Там изображения выходят некоторые правильно некоторые нет. Но я нашёл выход: jpg гружу с scale в восемь раз меньше чем картинка! Очень быстро. Но есть одна проблема вот мой код:

procedure MadeMiniImageList;
var
i: longInt;
t: byte;
BitMap,ItogBitMap: TBitMap;
ci: TImage;
begin
BitMap:=TBitMap.Create;
ItogBitMap:=TBitMap.Create;
ItogBitMap.Width:=SizeMiniWidth;
ItogBitMap.Height:=SizeMiniHeight;

with MainF do
begin
 MiniImageList.Clear;
 if Length(Data)>0 then
//  for t:=1 to 3 do
 for i:=1 to Length(Data) do
 begin
  //=================== показ загрузки ======
  ZastF.LoadI.Width:=(((i*100) div Length(Data))*ZastF.HideI.width) div 100;
  ZastF.LoadI.Refresh;
  //=================== создание миниатюры ======
  if FileExists(DataDir+Data[i-1].FileName) then
  begin
   BitMap:=LoadMiniJPEG(DataDir+Data[i-1].FileName);
   if Max(BitMap.Width,BitMap.Height)=BitMap.Width
    then ResizeImage(BitMap,SizeMiniWidth,Round(BitMap.Height*SizeMiniWidth/BitMap.Width))
     else ResizeImage(BitMap,Round(SizeMiniHeight*BitMap.Width/BitMap.Height),SizeMiniHeight);
   
   ItogBitMap.Canvas.Rectangle(0,0,ItogBitMap.Width,ItogBitMap.Height);
//    canvas.copyrect()
   ItogBitmap.Canvas.Draw(
    Round((SizeMiniWidth-BitMap.Width)/2),
    Round((SizeMiniHeight-BitMap.Height)/2),BitMap);
   MiniImageList.Add(ItogBitMap,nil);
  end;
 end;
end;
BitMap.Free;
ItogBitMap.Free;
end;

Дело в том что некоторые картинки не делаются! Просто белый квадрат. И причём когда какие! Почти наугад. Подряд запущу одни и теже, поработаю 10 минут другие! В общем моразм. Нашёл один выход:

   if Max(BitMap.Width,BitMap.Height)=BitMap.Width
    then ResizeImage(BitMap,SizeMiniWidth,Round(BitMap.Height*SizeMiniWidth/BitMap.Width))
     else ResizeImage(BitMap,Round(SizeMiniHeight*BitMap.Width/BitMap.Height),SizeMiniHeight);
BitMap.SaveToFile("temp\"+IntToStr(i)+".bmp"); // вот ета ненужнаяя строчка решает проблему.

Но ета строчка мне не нужна 1, 2 ето нафиг мне каждый раз сохранять файлы! 3 прога будет грузиться с сидюка. 4 полный моразм если я изменю ету строчку на ету: BitMap.SaveToFile(IntToStr(i)+".bmp"); то опять некоторые рисунки белые! идиотизм какойто! Помогите плиз! Проясните ситуацию!


 
sco ©   (2006-02-06 10:48) [8]

to: antonn: Твой способ не срабатывает! Там изображения выходят некоторые правильно некоторые нет. Но я нашёл выход: jpg гружу с scale в восемь раз меньше чем картинка! Очень быстро. Но есть одна проблема вот мой код:

procedure MadeMiniImageList;
var
i: longInt;
t: byte;
BitMap,ItogBitMap: TBitMap;
ci: TImage;
begin
BitMap:=TBitMap.Create;
ItogBitMap:=TBitMap.Create;
ItogBitMap.Width:=SizeMiniWidth;
ItogBitMap.Height:=SizeMiniHeight;

with MainF do
begin
 MiniImageList.Clear;
 if Length(Data)>0 then
//  for t:=1 to 3 do
 for i:=1 to Length(Data) do
 begin
  //=================== показ загрузки ======
  ZastF.LoadI.Width:=(((i*100) div Length(Data))*ZastF.HideI.width) div 100;
  ZastF.LoadI.Refresh;
  //=================== создание миниатюры ======
  if FileExists(DataDir+Data[i-1].FileName) then
  begin
   BitMap:=LoadMiniJPEG(DataDir+Data[i-1].FileName);
   if Max(BitMap.Width,BitMap.Height)=BitMap.Width
    then ResizeImage(BitMap,SizeMiniWidth,Round(BitMap.Height*SizeMiniWidth/BitMap.Width))
     else ResizeImage(BitMap,Round(SizeMiniHeight*BitMap.Width/BitMap.Height),SizeMiniHeight);
   
   ItogBitMap.Canvas.Rectangle(0,0,ItogBitMap.Width,ItogBitMap.Height);
//    canvas.copyrect()
   ItogBitmap.Canvas.Draw(
    Round((SizeMiniWidth-BitMap.Width)/2),
    Round((SizeMiniHeight-BitMap.Height)/2),BitMap);
   MiniImageList.Add(ItogBitMap,nil);
  end;
 end;
end;
BitMap.Free;
ItogBitMap.Free;
end;

Дело в том что некоторые картинки не делаются! Просто белый квадрат. И причём когда какие! Почти наугад. Подряд запущу одни и теже, поработаю 10 минут другие! В общем моразм. Нашёл один выход:

   if Max(BitMap.Width,BitMap.Height)=BitMap.Width
    then ResizeImage(BitMap,SizeMiniWidth,Round(BitMap.Height*SizeMiniWidth/BitMap.Width))
     else ResizeImage(BitMap,Round(SizeMiniHeight*BitMap.Width/BitMap.Height),SizeMiniHeight);
BitMap.SaveToFile("temp\"+IntToStr(i)+".bmp"); // вот ета ненужнаяя строчка решает проблему.

Но ета строчка мне не нужна 1, 2 ето нафиг мне каждый раз сохранять файлы! 3 прога будет грузиться с сидюка. 4 полный моразм если я изменю ету строчку на ету: BitMap.SaveToFile(IntToStr(i)+".bmp"); то опять некоторые рисунки белые! идиотизм какойто! Помогите плиз! Проясните ситуацию!


 
antonn ©   (2006-02-06 13:58) [9]

sco ©   (06.02.06 10:48) [7]
to: antonn: Твой способ не срабатывает! Там изображения выходят некоторые правильно некоторые нет.

ну конкретней нужно говрорить, что там не правильно.
на картинке обводка добавляется? это врожденное :)


 
PAVIA ©   (2006-02-06 15:46) [10]

Дело тут не в уменьшении изоброжении, а в том что картинка грузится долго. Для ускорения загрузки можно использовать такой способ скорость возрастет в 16 раз.
uses jpeg;

var
jpg:TJPEGImage;
begin
jpg:=TJPEGImage.Create;
jpg.Scale:=jsEighth;
//jpg.Scale:=jsQuarter;
jpg.Performance:=jpBestSpeed;
jpg.LoadFromFile("f:\warlok.jpg");

bp:=TBitmap.Create;
bp.Assign(jpg);


 
sco ©   (2006-02-06 16:23) [11]

to PAVIA: я ето уже сделал, скорость возросла в 8 раз, в общем круто, но одна трабла: некоторые не делаются, и всегда поразному. А больше 8 раз уменьшение мне не нужно, 8 раз и так  меньше многих моих рисунков. В общем лажа! И чо делатьь я не знаю.

to antonn: трабла в том что они (минирисунки) иногда меньше чем размер уже адаптированного рисунка, и короче там по бокам пустота, они не центрированиы, в общем видимо етот способ только для больших чем мини рисунков.


 
Fenik ©   (2006-02-06 17:02) [12]

> antonn ©   (05.02.06 17:50) [6]
> ItogBitmap.Canvas.Draw() - фуфел, используйте canvas.copyrect()
> в крайнем случае


CopyRect - фуфел, надо юзать BitBlt.


 
antonn ©   (2006-02-06 17:31) [13]

sco ©   (06.02.06 16:23) [11]
to antonn: трабла в том что они (минирисунки) иногда меньше чем размер уже адаптированного рисунка

дык они должны растянуться, copyrect() и растянет. а вообще проверять надо размер сначала:) я лишь примерно показал.
Fenik ©   (06.02.06 17:02) [12]
CopyRect - фуфел, надо юзать BitBlt.

может тогда уж до StretchBlt сразу дойти?


 
PAVIA ©   (2006-02-06 18:26) [14]

Сделай проверку на размер, а затем jpg.Scale чтобы картинка была больше миниатюры. Затем подгоняешь под свой размер.

> Fenik ©   (06.02.06 17:02) [12]
> CopyRect - фуфел, надо юзать BitBlt.
> может тогда уж до StretchBlt сразу дойти?

Тогда уж DrawDibDraw.


 
sco ©   (2006-02-06 19:33) [15]

Не, здесь я уже про большие! Типа слайд-шоу, хотя не типа, а именно так. Но я нажимаю некст, а он ещё секунду думает. Ну ето плохо! Вот и хочу ускорить.


 
Sco ©   (2006-02-06 19:35) [16]

Я топики перепутал:
"Не, здесь я уже про большие! Типа слайд-шоу, хотя не типа, а именно так. Но я нажимаю некст, а он ещё секунду думает. Ну ето плохо! Вот и хочу ускорить." Ето не сюда, извините за флуд, виноват, в етом топике про маленькие. Ещё раз извиняюсь, админа попрошу его снести.


 
PAVIA ©   (2006-02-06 22:47) [17]

Если про большии заведи буфер BMP:TBitmap. И грузи в него следующую картинку до таго как будет нажата кнопка Next. А по щелчку по кнопки выводи этот BMP в image


 
Sapersky   (2006-02-07 11:54) [18]

Тогда уж DrawDibDraw.

Сам не проверял, но из комментариев к SpriteUtils:
"According to MSDN this procedures should provide faster bitmap drawing than BitBlt, but they doesn"t."


 
Sco ©   (2006-02-07 12:57) [19]

Всё сделал! Работает, скорость неплохая 120 минирисунков из больших за 3.5 секунды! Вполне подойдёт, а если учесть что гружу по ходу дела отлично.



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

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

Наверх





Память: 0.51 MB
Время: 0.011 c
2-1152698967
DelphiN!
2006-07-12 14:09
2006.07.30
Главная форма = Nil при обращении к ней из датамодуля


2-1152267447
Gerald
2006-07-07 14:17
2006.07.30
Объединить записи 2х таблиц


1-1150709334
Den_is
2006-06-19 13:28
2006.07.30
Многострочные ячейки в TdxInspector


2-1152618826
Tort
2006-07-11 15:53
2006.07.30
Указатели или что?


2-1152009047
Zilog
2006-07-04 14:30
2006.07.30
Как преобразовать 48-битное число?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский