くだすれDelphi(超初心者用)その49at TECH
くだすれDelphi(超初心者用)その49 - 暇つぶし2ch385:デフォルトの名無しさん
09/05/01 10:30:37
VirtualListViewに256x256のサムネイル画像を並べているのですが、StretchBlt

縦横比を変えずに縮小するために
JpegをTPictureで読み込んでBMP.Assignするときに凄く時間がかかってしまいます
最初は中村氏のBitmapUtils.Stretchを使ってからStretchBltしていましたからもっと時間がかかっていました
TVirtualExplorerEasyListviewなどはエクスプローラ並みのスピードで表示されるので方法次第だと思うのですが
ソースがないので手法が分かりません
どの方向で考えたらいいでしょうか?御指南ください

386:デフォルトの名無しさん
09/05/01 13:43:04
>>385
TJpegImageのScale使うか、
写真ならExifのサムネイルを読み込むか。

387:デフォルトの名無しさん
09/05/01 14:21:28
ありがとうございまし、そんなのもあるのですね
D2009のJpeg,GIFImg,pngimageを使っているので型によって縮小方法を変えるんですね
ググったら
URLリンク(jane.s89.xrea.com)
がでました。サンプルソ-スも生きていて落とせましたので読んでみます
でも、usesするだけでTImageとかでpngとか読めるんだから(これが凄いけど)
TImageListとTListViewも対応してくれるのが一番嬉しいんですよね

388:デフォルトの名無しさん
09/05/01 14:23:12
ソースだと思ったらJane本体だったorz
これだけがヒントですね
188 :Jane使いの名無しさん:05/07/27 00:00:41 ID:6kBZoROZ
>>174
・TJpegImage.Scale //←基本的にこれ
・TbitmapはDIBにする
・Jpeg.pasとiijのライブラリ改造

TApiBitmapとTBitmapで検索して掛かったとこちょっと
変えてみただけ

389:デフォルトの名無しさん
09/05/01 18:24:11
つGDI+

390:デフォルトの名無しさん
09/05/02 14:22:24
>>385
ちなみにサムネイル生成処理はちゃんと別スレッドでやってる?
画像ファイルが1000超えるような場合のエクスプローラの挙動見れば分かるけど、
非同期でやらないとどれだけ高速化しても厳しいと思うよ

391:デフォルトの名無しさん
09/05/02 19:20:06
そうですね、10個表示されてたらいくつも平行してサムネイルが描画されていってますものね
私もスレッドはやってみようとしかけたのですが、結局ImageListに登録する所あたりで挫けてしまいました
スレッドCreateでFileName、サムネイルの大きさを渡してBitMapを返してもらうのか(どうやって?)
スレッドの中でImageListにAddするのか
ListView.OnDataHintとスレッドがどんなお付き合いにしたらいいのかが分からないのです
あ、ちなみに>>389さんのGDI+は試したらずいぶんと速くなりました

392:デフォルトの名無しさん
09/05/02 20:16:40
CなどのコードをDelphiへ移植する時、Delphiで使えない識別子があった場合はみなさんどうしてますか?

393:デフォルトの名無しさん
09/05/02 21:58:43
comboboxのitemを右クリックしたらポップアップメニューを出したいんだけど、
どうしたら良いですか?
ContextPopupにPopupmenu1.Popup(X,Y)ってやっても何も起こらないです。

394:393
09/05/02 22:27:06
事故レスです。
レジマネジャーって言うフリーのコンポの
バグみたいです。
新規でテストプログラムかいたら出来ました。

395:デフォルトの名無しさん
09/05/03 19:27:46
>>391
実際にスレッド内部からImageList.Add呼んだら問題が起きた?そこまでやったの?
とりあえずぐちゃぐちゃになってもいいからやってみないことには問題点も分からないじゃない

396:デフォルトの名無しさん
09/05/03 22:11:13
やってみました。
何度も暴走させながらも(スレッドってまともに動かしたことがないもので)出来ました
目に見えるItemが同時に読み込まれている感がないのでまだまともに出来ている
ワケではないのでしょうが取り敢えず正確に表示できて明らかに今までより
表示速度は速くなりました(4000Filesほど読み込ませても数秒でした)
ありがとうございました

397:デフォルトの名無しさん
09/05/03 23:11:33
マルチスレッド歴1ヶ月のおいらがわかる事はとりあえず、
ImageList.Addメソッドの呼び出しは最低限、クリティカルセクションなりを用いて排他制御
しなきゃいけなさそうと言う事だけ。
後はわかんない。ぷぎゃ。
CriticalSection.Accuire;
try
ImageList.Add
finally
CriticalSection.Release;
end;

398:デフォルトの名無しさん
09/05/04 00:36:07
いや、いらないからw

399:デフォルトの名無しさん
09/05/04 01:01:10
>>397だけど、今、具体的にImageListのAddメソッド追ってみたけど、
内部でHandleNeededが呼ばれて、そのHandleNeededでフィールドのFHandleを参照しているから、
下手すると、
procedure TCustomImageList.HandleNeeded;
begin
if FHandle = 0 then CreateImageList;
end;
で、CreateImageListに複数のスレッドが同時に突入すると、イメージリストのハンドル
が複数作成され、迷子になっちゃわない?
ハンドルリークだから、まぁ、そこまで被害拡大しないと思うけど。


400:デフォルトの名無しさん
09/05/04 01:12:08
ああ、というか、そもそも前提がお互い違うのかもね。
おいらの場合は、サムネイル作成するサブスレッドでImageListのAddメソッド
呼ぶ事を前提にしてた(それで出来るか分からないけど、ぷぎゃ)。
メインスレッドだけで、ImageList.Addメソッド呼ぶなら必要ないと思う。


401:デフォルトの名無しさん
09/05/04 01:42:09
勉強のため、勝手にちょっと作ってみたけど、今のおいらのレベルで作るとこんな感じかな。
 TThumnailEvent = procedure (Sender: TObject; ABitmap: TBitmap) of object;
 TThumnailer = class(TThread)
 private
  FFileName: string;
  FSize: TSize;
  FBitmap: TBitmap;
 private
  FOnThumnail: TThumnailEvent;
 private
  procedure CallOnThumnailEvent;
 protected
  procedure Execute; override;
 public
  constructor Create(CreateSuspended: Boolean; AFileName: string; ASize: TSize);
 public
  property OnThumnail: TThumnailEvent read FOnThumnail write FOnThumnail;
 end;


402:デフォルトの名無しさん
09/05/04 01:43:02
で、実装は
{ TThumnailer }
constructor TThumnailer.Create(CreateSuspended: Boolean; AFileName: string; ASize: TSize);
begin
 FFileName := AFileName;
 FSize := ASize;
 FBitmap := TBitmap.Create;
 inherited Create(CreateSuspended);
end;

procedure TThumnailer.CallOnThumnailEvent;
begin
 if Assigned(FOnThumnail) then
  FOnThumnail(Self, FBitmap);
end;

procedure TThumnailer.Execute;
begin
 // サムネイル作成処理
 // ごにょごにょ
 if Assigned(FOnThumnail) then
  Synchronize(CallOnThumnailEvent); // VCLのメインスレッドど同期を取る
 FBitmap.Free;
end;


403:デフォルトの名無しさん
09/05/04 01:46:47
メインのVCLスレッドでは、
procedure TMainForm.Button1Click(Sender: TObject);
var
 Thumnailer: TThumnailer;
begin
 Thumnailer := TThumnailer.Create(True, FileName, Size, Bitmap);
 Thumnailer.FreeOnTerminate := True; // 自動破棄
 Thumnailer.OnThumnail := OnThumnail;
 Thumnailer.Resume;
end;

procedure TMainForm.OnThumnail(Sender: TObject; ABitmap: TBitmap);
begin
 if ABitmap <> nil then
  ImageList.Add(ABitmap);
end;
とか。ListView.OnDataHintとかは良くわかってないので省略。



404:デフォルトの名無しさん
09/05/04 01:47:39
Thumnailer := TThumnailer.Create(True, FileName, Size, Bitmap);

Thumnailer := TThumnailer.Create(True, FileName, Size);
だった。orz


405:デフォルトの名無しさん
09/05/04 01:51:34
「こんなクラス名は嫌だ」


最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch