HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2018
1104
hexagonプロパティからの高速な画像縦横サイズ取得4解決


hexagon

リンク

2018/11/4(Sun) 12:11:08|NO.85777

現在、画像ビューワーを作っています。
その中で、縦横比の長さで表示するものをフィルタリングするなどの機能を考えており
大量の画像の処理を行う中で、素早く画像の縦横サイズを取得したいと考えています。

画像サイズ取得で考え付くのがbufferなどで作成した先にpicloadで読み込んだ後、変形したクライアント領域を取得するという方法ですが
これだと巨大な画像だと時間がかかったり読み込みエラーを起こしてしまいます。
(加えてすべての画像を一枚一枚完全に読み込むのでディスクへの負荷も高くなる?)
一方、エクスプローラー上、あるいはプロパティを開いた際に出てくる「大きさ」の項目は非常に高速です。
これをHSPから取得し、利用できれば高速に処理できるのではと考えました。

この「ファイルのプロパティ情報のみ」といった情報の取得は難しいのでしょうか?
以上よろしくお願いします。



この記事に返信する


バイト

リンク

2018/11/4(Sun) 12:43:25|NO.85778

画像サイズかぁ…
http://www.tvg.ne.jp/menyukko/cauldron/hmfileinfo.html
FileI_InfoFileの7、8とかがもしかしたら



あらや

リンク

2018/11/4(Sun) 13:06:24|NO.85779

プロパティに出て来る幅、高さは
ファイル内のヘッダ情報を読み込んで表示しているだけかと思います。

例えば、BMP画像を例に挙げると

Windowsフォーマットの場合
ファイル先頭から18バイト目から21バイトまでの4バイトが幅
同じく、22バイトから25バイトまでの4バイトが高さ

OS/2フォーマットの場合
18から19の2バイトが幅
20から21の2バイトが高さ

という感じです。

これらの分別の仕方や画像ファイルの種類ごとのサイズ取得方法は
単に拡張子からある程度判断するか、ヘッダ情報のファイルタイプを読み込んで
種類ごとに条件分けをして、〇〇形式なら何バイト目を読むと幅・高さが取得できる。
という形で、難しいというよりもあつかう画像の全てのパターンを用意するという
若干面倒なことをすれば可能です。

結局一度データを読み込むことになりますが、
bloadで読み込む最大サイズを指定すれば無闇にメモリを消費せずに済みます。



そしてどれだけの種類の画像ファイルを扱うのかわかりませんが
「BMPファイル 構造」もしくは「BMPファイル フォーマット」などで検索すれば
各種ファイルの構造がわかると思います。



ソラ(スペース)

リンク

2018/11/4(Sun) 13:59:45|NO.85780


#module #define ctype BigEndianInt(%1) (%1 >> 24 & 255) | ((%1 >> 16 & 255) << 8) | ((%1 >> 8 & 255) << 16) | (( %1 & 255) << 24) #define ctype wBigEndianInt(%1) (%1 >> 8) | (%1 & 255) << 8 /* p1 画像のパス jpegの場合、正常に完了するとstatが0。 jpegでサイズが取得できなかった場合は-1が返ります。 pngは1、bmpは2が返ります。 つまり正常に終了した場合、0以上が返ります。 jpeg以外はサイズが書き込まれている位置が固定なので、 取得できないことはあり得ませんが、 正常な値が取得されているとは限りません。 */ #deffunc GetImg str p1 if ct=0:{//初回に限り変数を初期化。 //ファイルの0バイト目から取得する長さ。 //明確に何バイト目までにサイズが書かれているか調べてもわからなかったので、 //手元のファイルを元に適当に設定。 長さ=1024 sdim Fbin,長さ sdim bin,長さ*2+1 ct=1 } bload p1,Fbin,長さ,0//ロード repeat 3//バイナリデータを扱いやすいように変換 poke bin,cnt*2,strf("%02x",peek(Fbin,cnt)) loop 状態=0 形式=-2 //0バイト目~数バイトを調べて形式を判定。 if instr(bin,0,"ffd8")=0:{//jpeg repeat 長さ-3//バイナリデータを扱いやすいように変換 poke bin,6+(cnt*2),strf("%02x",peek(Fbin,cnt+3)) loop in=instr(bin,0,"ffc00011")//サイズの位置が可変なので、サイズの始まりを示す文字を検索。 if in!-1:{//発見できたら処理。 in+10 //sx=strf("%d",int("$"+strmid(bin,in+4,4))) //sy=strf("%d",int("$"+strmid(bin,in+0,4))) sx=int(strf("%d",wBigEndianInt(wpeek(Fbin,(in/2)+2))))//これでいいはず・・・? sy=int(strf("%d",wBigEndianInt(wpeek(Fbin,(in/2)))))//でも何故かうまくいかない。 }else:状態=-1//出来なかったら 形式=0 } //jpeg以外はサイズが書き込まれている位置が固定なのでjpegより簡単。 if instr(bin,0,"89504e")=0:{//png sx=int(strf("%d",BigEndianInt(lpeek(Fbin,16)))) sy=int(strf("%d",BigEndianInt(lpeek(Fbin,20)))) 形式=1 } if instr(bin,0,"424d")=0:{//bmp //リトルエンディアンで書かれているので注意。 sx=int(strf("%d",wpeek(Fbin,18))) sy=int(double(strf("%d",wpeek(Fbin,3)))/22.5) 形式=2 } if instr(bin,0,"474946")=0:{//gif //リトルエンディアン sx=int(strf("%d",wpeek(Fbin,6))) sy=int(strf("%d",wpeek(Fbin,8))) 形式=3 } if instr(bin,0,"00000a")=0:{//tga //リトルエンディアン sx=int(strf("%d",wpeek(Fbin,12))) sy=int(strf("%d",wpeek(Fbin,14))) 形式=4 } return (状態+形式) //取得できたサイズを返す。 #defcfunc Gsx return sx #defcfunc Gsy return sy #global #include "winmm.as"//pcの起動時間を測定 n=1000.0 button "開く",*開く stop *開く dialog "",16,"画像" if stat=1:{ timegettime:開始時間=stat //n回の平均 repeat n GetImg refstr st=stat if st=-2:形式="未知" if st=-1:形式="JPEG(サイズの取得に失敗)" if st=0:形式="JPEG" if st=1:形式="PNG" if st=2:形式="BMP" if st=3:形式="GIF" if st=4:形式="TGA" loop timegettime 終了時間=stat Color 255,255,255:boxf:Color 0,0,0 pos 10,50:mes "形式"+形式+"\n"+gsx()+"x"+gsy()+"\n"+(double(終了時間-開始時間)/n)+"" }

かなり前に書いたコードで、自分でも何故そうやってるのかよく分からない部分があります。
特にwpeekで取得した16進のサイズをstrfで10進に変換してint型を変換して・・・という部分は、
なんかもっと簡単なやり方があると思います。

また、以下のスレでFlatさんが同じようなモジュールを投稿しています。
http://hsp.tv/play/pforum.php?mode=pastwch&num=72960



hexagon

リンク

2018/11/4(Sun) 14:13:26|NO.85782

>バイトさん
ありがとうございます
しかしそちらはあくまでファイルそのもののサイズでした

>あらやさん、ソラ(スペース)さん
ありがとうございます
対象としてはメジャーな(個人規準)ものを扱おうと考えてました
しかしなるほど、ヘッダ部分から取得していたんですね
16進数からの抜出というものがソラさんサンプルの見よう見まねでようやくできた形ではあります

//Windows bmp用 sdim eee dialog "",16 bload refstr,eee,,18 mes int(strf("%d",wpeek(eee))) mes int(strf("%d",wpeek(eee,4)))
まだこういったバッファ操作がさっぱりではありますがこの辺を勉強して攻めていきたいと思います
ありがとうございました



ONION software Copyright 1997-2023(c) All rights reserved.