Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.07.30;
Скачать: CL | DM;

Вниз

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

 
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 вся ветка

Текущий архив: 2006.07.30;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.027 c
15-1151912318
Александр Иванов
2006-07-03 11:38
2006.07.30
500 ГГц


2-1152694817
Neket
2006-07-12 13:00
2006.07.30
Редактирование TreeView1


1-1150649616
AlexAlex
2006-06-18 20:53
2006.07.30
Можно ли отрезать кусок от файла без копирования его содержимого?


2-1152693377
hgd
2006-07-12 12:36
2006.07.30
Polygon


2-1152288270
AlexanderMS
2006-07-07 20:04
2006.07.30
Чтение TGA-файлов