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

Вниз

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

 
alexandr-m ©   (2005-08-09 18:15) [0]

Все примеры которые были найдены в сети - медленные. Картинка JPEG с современного фотоаппарата размером 5Мб грузится и отображается минимум 1.5-2 секунды. Хочется сделать этот процесс моментальным.
Скажем фоновая подгрузка следующей картинки для последующего моментального отображения.


 
Eraser ©   (2005-08-09 20:28) [1]

alexandr-m ©   (09.08.05 18:15)

Скорее всего быстрее вряд ли получится. Скорость ограничена ресурсами конкретного компьютера. А декодирование jpeg картинки достаточно "процессороёмкий" процесс.


 
alexandr-m ©   (2005-08-09 23:22) [2]

а нельзя ли этот  "процессороёмкий" процесс проводить в фоновом режиме подгружая следующую картинку пока юзер смотрит на ту которая загрузилась?


 
Eraser ©   (2005-08-09 23:52) [3]

alexandr-m ©   (09.08.05 23:22) [2]

Можно! А какие проблемы в реализации этого?


 
programania ©   (2005-08-10 03:52) [4]

Для ускорения загрузки Jpeg можно ещеTJPEGScale = (jsFullSize, jsHalf, jsQuarter, jsEighth);грузить сначала не jsFullSize и показывать все равно большая картинка в экран не влезета потом jsFullSize уже незаметно пока что-то не нажмути вначале делать масштабирование не качественно но быстро, а потом уже улучшено.А для картинок больше 1mb лучше заранее сделать миниатюры.


 
miek ©   (2005-08-10 09:09) [5]

В принципе, 2 секунды на такой файл это много, ACDSEE распаковывает значительно быстрее. Значит, надо искать в сети более быстрый модуль для декодирования. Или библиотеку. IJL (Intel JPEG Library) здесь первый кандидат.


 
WondeRu ©   (2005-08-10 15:30) [6]

miek ©   (10.08.05 9:09) [5]
ACDSEE распаковывает значительно быстрее

ACDSEE - кеширует! так что Ваше предположение - бред!


 
Ландграф Павел ©   (2005-08-10 20:16) [7]

И куда он их кеширует? имхо такой же бред, что, всю папку в 2 гега jpg`ов можно прокешировать? Специально провел тест и именно 2 гега скопировал всех моих картинок из разных папок в одну и все файлы переименовал, открывается ТАКЖЕ БЫСТРО!


 
Alexander Panov ©   (2005-08-10 20:38) [8]

Ландграф Павел ©   (10.08.05 20:16) [7]

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


 
Ландграф Павел ©   (2005-08-10 21:57) [9]

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


 
miek ©   (2005-08-11 09:50) [10]

>ACDSEE - кеширует! так что Ваше предположение - бред!

Одно другому не мешает. Да, кэширует.

Но даже если картинки нет в кэше, он работает быстро. Тут, правда, есть одно "но" - какой номинальный размер у картинки? 800x600 или 3000x3000? И то и другое можно сжать в 5МБ. Для первого случая 1,5 сек много.


 
Sapersky   (2005-08-11 10:42) [11]

Загрузка на P3-667 картинки 4096 * 4096, ужатой до 500 кб:

KOLJpegObj (аналог стандартного jpeg.pas): 2700 мс
IJL: 710 мс

Та же картинка с хорошим качеством (2.5 мб):

KOLJpegObj: 3000 мс
IJL: 820 мс

Единственный недостаток IJL - относительно большой размер (DLL в 370 кб, тот же JpegObj - около 70 кб). Хотя и 370 кб по современным меркам немного.

Пример использования:
http://prdownloads.sourceforge.net/skinner/FastLib.zip?download


 
alexandr-m ©   (2005-08-11 20:09) [12]

>ACDSee используется не кэширование, а предзагрузка. Т.е. при >последовательном просмотре рисунков программа предварительно >загружает следующий по списку файл в отдельный буфер и >обрабатывает его. При переходе пользователем на след. рисунок >загруженный рисунок уже не загружается, а лишь отображается на >экране.

Это я и хочу сделать, но во время загрузки следующей картинки прога висит, так как идёт процесс считывания с винта этих 5 Мб. Отображается потом моментально, а вот как сделать этот процесс загрузки низкоприоритетным чтобы он не вешал всё остальное и можно было жмакать на кнопки и т п.


 
alexandr-m ©   (2005-08-11 20:12) [13]

>Та же картинка с хорошим качеством (2.5 мб):

>KOLJpegObj: 3000 мс
>IJL: 820 мс

Значит качественную картинку в 5 метров с цифровика с хорошим качеством IJL: 820 мс *2= 1640 мс т.е. 1.5 секунды - это уже тормозззззззззз. Пробовал проги которые пользуют IJL именно такое время у них и уходит на это. Да и ACDCEE не чемпион при больших картинках так же тормозит.


 
alexandr-m ©   (2005-08-11 20:21) [14]

>http://prdownloads.sourceforge.net/skinner/FastLib.zip?download

загрузка картинки 1.5 метра те же 1.5 сек что и у делфийского TImage


 
alexandr-m ©   (2005-08-11 20:21) [15]

>http://prdownloads.sourceforge.net/skinner/FastLib.zip?download

загрузка 5-меировой картинки те же 1.5 сек что и у делфийского TImage


 
Alexander Panov ©   (2005-08-11 21:25) [16]

alexandr-m ©   (11.08.05 20:09) [12]
Это я и хочу сделать, но во время загрузки следующей картинки прога висит


Загружай в отдельном потоке с пониженным приоритетом.


 
Sapersky   (2005-08-12 11:10) [17]

Значит качественную картинку в 5 метров с цифровика с хорошим качеством IJL: 820 мс *2= 1640 мс т.е. 1.5 секунды - это уже тормозззззззззз

820 мс - это результат весьма престарелого по нынешним временам процессора... (P3-667)

загрузка 5-меировой картинки те же 1.5 сек что и у делфийского TImage

Странно. У меня IJL стабильно быстрее (протестировал ещё с 7 мб файлом). Или - как посмотреть - TImage/KOLJpegObj медленнее (думал на версию Дельфи - но в 5 и 7, во всяком случае, всё практически одинаково, 7 даже несколько медленнее).

Процессор не Athlon? Может, Intel Jpeg Library с ним принципиально не хочет быстро работать.

Ещё зависит от типа файла. Прогрессивные JPG, например, грузятся медленнее, и IJL на них даёт меньшее ускорение (но оно есть - в 1.5 раза).


 
Sapersky   (2005-08-12 11:41) [18]

Понял в чём дело - IJL быстрее при выключенном Smoothing (для качественной картинки он и не нужен).
В TBumpForm.LoadImage:
LoadJPGFile(Tmp,FileName,False);


 
Jeer ©   (2005-08-12 12:27) [19]

P-IV 2G
jpg 96% 4M 3000x3000 310 ms


 
alexandr-m ©   (2005-08-14 16:07) [20]

test


 
alexandr-m ©   (2005-08-14 16:27) [21]

>В ACDSee используется не кэширование, а предзагрузка. Т.е. при >последовательном просмотре рисунков программа предварительно >загружает следующий по списку файл в отдельный буфер и >обрабатывает его.

>Загружай в отдельном потоке с пониженным приоритетом.

Именно это и хочу сделать. Создал новый поток, но не могу из него вызвать компонент из первой формы, на попытку

Form1.Image2.Picture.LoadFromFile("c:\1YPB290680.JPG");

из нового Unit1.pas в котором создался этот Thread пишет:

Undeclared Indetifier Form1


 
alexandr-m ©   (2005-08-14 17:13) [22]

С этим разобрался надо было прописать

implementation

uses unit1;

теперь не могу вызвать эту процедуру прописанную в другом юните:

procedure LoadNextImage.execute;
begin
 SetName;
 { Place thread code here }

Form1.Image3.Picture.LoadFromFile("c:\1YPB290681.JPG");

end;

пишу в первой форме:
unit1.LoadNextImage(execute);

ошибка: Undeclared Indetifier Form1


 
alexandr-m ©   (2005-08-14 17:22) [23]

по идее должно вызываться типа

Synchronize(UpdateCaption);

пишу Synchronize(unit1.LoadNextImage(execute));

ошибка missing operator.

как блин вызвать эту процедуру с потоком?


 
miek ©   (2005-08-15 10:56) [24]

В обоих модулях пропиши uses друг друга.


 
alexandr-m ©   (2005-08-15 15:34) [25]

уже прописал, я же написал выше.
В обоих модулях пропиши uses друг друга.


 
Alexander Panov ©   (2005-08-15 15:47) [26]

Ты бы код потока привел лучше.


 
alexandr-m ©   (2005-08-15 16:04) [27]

http://delphimaster.net/view/8-1124107398/

вот создал отдельный топик по потоку, там привёл весь код.


 
Alexander Panov ©   (2005-08-15 18:28) [28]

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


{$WARN UNIT_PLATFORM OFF}
{$WARN SYMBOL_PLATFORM OFF}

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ComCtrls, Buttons, ExtCtrls, StdCtrls, ToolWin, JPeg,FIleCtrl;

type

 PFileRec=^TFileRec;
 TFileRec=record
   FilePath: String;
   FullFileName: String;
   FileName: String;
   FileExt: String;
   FileSize: Integer;
   isDir: Boolean;
 end;
 TFileRecArray=array of TFileRec;

 EErrorJpeg=Exception;
 TPreloadStatus=(psNone,psProcess,psComplete);
 TPreloadWait=(pwWait);
 TCompleteProc=procedure(const FilePath: String) of  object;

 TPreloadJpeg=class(TThread)
 private
   FFilePath: String;
   FJpeg: TJpegImage;
   FComplete: TCompleteProc;
   FStatus: TPreloadStatus;

   procedure FOnComplete;
   function GetJpegImage: TJpegImage;

 protected
   procedure Execute; override;
 public
   constructor Create;
   destructor Destroy; override;
   procedure Release;

   procedure Load(const FilePath: String); overload;
   procedure Load(const FilePath: String;aWait: TPreloadWait); overload;

   property OnComplete: TCompleteProc read FCOmplete write FComplete;
   property Status: TPreloadStatus read FStatus;
   property JpegImage: TJpegImage read GetJpegImage;

 end;

 TForm1 = class(TForm)
   sb: TStatusBar;
   ToolBar1: TToolBar;
   lb: TListBox;
   im: TImage;
   SpeedButton1: TSpeedButton;
   procedure FormCanResize(Sender: TObject; var NewWidth,
     NewHeight: Integer; var Resize: Boolean);
   procedure FormCreate(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
   procedure SpeedButton1Click(Sender: TObject);
   procedure lbClick(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

function DirSelect(const RootDir: String): String;

var
 Form1: TForm1;
 PJ: TPreloadJpeg;
 LastIndex: Integer;

implementation

{$R *.dfm}
function GetFileName(const FullFileName: String): String;
var
 i: Integer;
begin
 Result := FullFileName;
 for i := Length(FullFileName) downto 1 do
 begin
   if FullFileName[i]="." then
   begin
     Result := Copy(FullFileName,1,i-1);
     Break;
   end;
 end;
end;

function GetFileExt(const FullFileName: String): String;
var
 i: Integer;
begin
 Result := "";
 for i := Length(FullFileName)-1 downto 1 do
 begin
   if FullFileName[i]="." then
   begin
     Result := Copy(FullFileName,i+1,Length(FullFileName)-i);
     Break;
   end;
 end;
end;

procedure GetFilesSimple(const aPath: String;var FileArr: TFileRecArray);
var
 SR: TSearchRec;
 tPath: String;
begin
 tPath := IncludeTrailingBackSlash(aPath);
 if FindFirst(tPath+"\*.*",faAnyFile,SR)=0 then
 begin
   try
     repeat
       if (SR.Name=".") or (SR.Name="..") then Continue;
       if (SR.Attr and faDirectory)<>0 then
       begin
           Continue;
         SetLength(FileArr,Length(FileArr)+1);
         FileArr[High(FileArr)].FilePath := tPath+SR.Name;
         FileArr[High(FileArr)].FullFileName := SR.Name;
         FileArr[High(FileArr)].FileName := GetFileName(SR.Name);
         FileArr[High(FileArr)].FileName := GetFileExt(SR.Name);
         FileArr[High(FileArr)].isDir := True;
         GetFilesSimple(tPath+SR.Name,FileArr);
       end;
       if UpperCase(GetFileExt(SR.Name))="JPG" then
       begin
           SetLength(FileArr,Length(FileArr)+1);
           FileArr[High(FileArr)].FilePath := tPath+SR.Name;
           FileArr[High(FileArr)].FullFileName := SR.Name;
           FileArr[High(FileArr)].FileName := GetFileName(SR.Name);
           FileArr[High(FileArr)].FileExt := GetFileExt(SR.Name);
           FileArr[High(FileArr)].FileSize := SR.Size;
           FileArr[High(FileArr)].isDir := False;
       end;
     until FindNext(SR)<>0;
   finally
     Sysutils.FindClose(SR);
   end;
 end;
end;

procedure TForm1.FormCanResize(Sender: TObject; var NewWidth,
 NewHeight: Integer; var Resize: Boolean);
begin
   sb.Panels[0].Width := Form1.ClientWidth-30;
end;

function DirSelect(const RootDir: String): String;
var
 Dir: String;
begin
 Dir := RootDir;
 if SelectDirectory(
      Dir,
      [sdAllowCreate, sdPerformCreate, sdPrompt],
      0)
   then Result := Dir
   else Result := "";
end;

{ TPreloadJpeg }

constructor TPreloadJpeg.Create;
begin
   inherited Create(True);
   FreeOnTerminate := True;
   FJpeg := TJpegImage.Create;
   FStatus := psNone;
   Resume;
end;

destructor TPreloadJpeg.Destroy;
begin
 FJpeg.Free;
 inherited;
end;

procedure TPreloadJpeg.Execute;
begin
   while not Terminated do
   begin
       Suspend;
       if Terminated then Break;
       try
           FJpeg.LoadFromFile(FFilePath);
           Synchronize(FOnComplete);
       except
           fStatus := psNone;
       end;
   end;
end;

procedure TPreloadJpeg.FOnComplete;
begin
   FStatus := psComplete;
   if Assigned(FComplete) then FComplete(FFilePath);
end;

function TPreloadJpeg.GetJpegImage: TJpegImage;
begin
 if FStatus = psProcess then raise EErrorJpeg.Create("Не закончена загрузка рисунка");
 if FStatus = psNone then REsult := nil else Result := FJpeg;
end;

procedure TPreloadJpeg.Load(const FilePath: String);
begin
   if FStatus = psProcess then raise EErrorJpeg.Create("Не закончена загрузка предыдущего рисунка");
   fStatus := psProcess;
   If FilePath=FFilePath then Exit;
   FFilePath := FilePath;
   Resume;
end;

procedure TPreloadJpeg.Load(const FilePath: String; aWait: TPreloadWait);
begin
   Load(FilePath);
   while FStatus<>psComplete do Sleep(1);
end;

procedure TPreloadJpeg.Release;
begin
   Terminate;
   Resume;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   PJ := TPreloadJpeg.Create;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin


 
Alexander Panov ©   (2005-08-15 18:28) [29]

   PJ.Release;
end;

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
   s: String;
   fr: TFileRecArray;
   i: Integer;
begin
  s := DirSelect("e:\data\photo");
  if s="" then Exit;
  GetFilesSimple(s,fr);
  lb.Items.Clear;
  for i := Low(fr) to High(fr) do
  begin
   lb.Items.Add(fr[i].FilePath);
  end;
  lb.ItemIndex := 0;
  LastIndex := 0;
  if (PJ.FStatus<>psProcess) and (lb.Items.Count>1) then PJ.Load(lb.Items[1]);
end;

procedure TForm1.lbClick(Sender: TObject);
var
   Index: Integer;
begin
   Index := lb.ItemIndex;
   if Index=LastIndex then
   begin
       if PJ.FStatus=psComplete then im.Picture.Assign(PJ.JpegImage);
       Exit;
   end;
   if PJ.FStatus=psComplete then im.Picture.Assign(PJ.JpegImage);
   if PJ.FStatus=psNone then
   begin
       PJ.Load(lb.Items[Index],pwWait);
       im.Picture.Assign(PJ.JpegImage);
   end;
   if Index>LastIndex then
   begin
       if Index+1<lb.Items.Count then
       begin
           LastIndex := Index;
           Index := Index+1;
           PJ.Load(lb.Items[Index]);
       end;
   end
   else
   begin
       if Index-1>=0 then
       begin
           LastIndex := Index;
           Index := Index-1;
           PJ.Load(lb.Items[Index]);
       end;
   end;
end;

end.


Как должен работать - смотри по коду, разбирайся.
Я отлаживать до конца не стал, но общая идея, работа с потоком понятна.

Вот ссылка на проект:
ftp://ftp.almar.net.ru/pub/pload/pload.zip



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

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

Наверх





Память: 0.59 MB
Время: 0.043 c
8-1123675290
Voron
2005-08-10 16:01
2006.01.22
Как сделать снимок экрана


4-1130998303
M@xim
2005-11-03 09:11
2006.01.22
Microsoft Agent Control


14-1136009895
begin...end
2005-12-31 09:18
2006.01.22
С Днём рождения! 31 декабря


14-1135575782
begin...end
2005-12-26 08:43
2006.01.22
С Днём рождения! 26 декабря


14-1135675298
ArtemESC
2005-12-27 12:21
2006.01.22
Задачка...





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