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


HSPTV!掲示板


未解決 解決 停止 削除要請

2022
0713
hamSusieでPNGなどの透過部分のみを読み込みたい12解決


ham

リンク

2022/7/13(Wed) 09:30:33|NO.96797

Susieを使用してPNGなどの画像からアルファチャンネルのみをロードしたいのですが、
どこをどのように弄れば出来るのかが分かりません。
少し変えるだけで可能でしょうか?分かる方がいらっしゃれば教えていただきたいです。

個人的に
if spi_IsSupported(hModule.cnt, fn, varptr(filebuffer)+128) {
となってるところが気になるのですが、+128...これが何の役割を果たすのかも理解できずにいます...

以下のスクリプトは「https://tu3.jp/0228」につーさ様が公開していたものです。

#module #uselib "kernel32.dll" #cfunc LoadLibrary "LoadLibraryA" sptr #cfunc GetProcAddr "GetProcAddress" int,sptr #cfunc LocalLock "LocalLock" int #func LocalUnlock "LocalUnlock" int #func LocalFree "LocalFree" int #func VirtualProtect "VirtualProtect" var, int, int, var #define mdim(%1,%2)dim %1,%2 :VirtualProtect %1,(%2)*4,$40,AZSD #uselib "gdi32.dll" #func SetDIBitsToDevice "SetDIBitsToDevice" \ int,int,int,int,int,int,int,int,int,int,int,int #deffunc GetBmpSize str fn, array val_sz, local bmpsz bmpsz = 0,0,0 bload fn,bmpsz, 12,14 if bmpsz = 40 : val_sz = bmpsz.1, bmpsz.2 : return 0 if bmpsz = 12 : val_sz = wpeek(bmpsz,4), wpeek(bmpsz,6) : return 1 return -1 ;// 初期化 #deffunc _spi_init LoadedPlugins = 0 mdim cbfunc,2 cbfunc = 0x0CC2C033,0x00000000 ;// xor eax,eax : ret 12 pfnCallback = varptr(cbfunc) return ;// 単一DLL読み込み #deffunc spi_Load str _dllname, local hDll ,\ local pfn, local prm, local ret hDll = LoadLibrary(_dllname) if hDll = 0 : return -1 ;// Load失敗 pfn = GetProcAddr(hDll,"GetPluginInfo") if pfn = 0 : return -2 ;// susie pluginじゃない sdim buf,256 prm = 0,varptr(buf), 256 ret = callfunc(prm,pfn,3) ;// 4E493030 = '00IN' 画像読み込みプラグインじゃない if lpeek(buf,0) != 0x4E493030 : return -3 hModule.LoadedPlugins = hDll LoadedPlugins++ return 0 ;// フォルダ内DLL全読み込み #deffunc spi_LoadAll str _dlldir ,local curdir, local rdptr, local list, local dllfn curdir = dir_cur : chdir _dlldir rdptr = 0 dirlist list, "*.spi" repeat stat getstr dllfn,list,rdptr : rdptr += strsize spi_Load dllfn loop chdir curdir return LoadedPlugins #defcfunc spi_IsSupported int _hModule, str _filename, int _dw, local fn, \ local pfn, local prm, local ret fn = _filename pfn = GetProcAddr(_hModule,"IsSupported") if pfn = 0 : return 0 prm = varptr(fn), _dw return callfunc(prm,pfn,2) #deffunc spi_GetPicture int _hModule, int _buf, int _len, int _mode ,\ local pfn, local prm, local ret pfn = GetProcAddr(_hModule,"GetPicture") ;LPSTR buf, long len, unsigned int 1, HANDLE *pHBInfo, HANDLE *pHBm, pfnCallback, 0 prm = _buf, _len, 1, varptr(HBi), varptr(HBm), pfnCallback, 0 ret = callfunc(prm,pfn,7) if ret ! 0 : return ret pbi = LocalLock(HBi) pbm = LocalLock(HBm) dupptr bi,pbi+4,8,vartype("int") w = bi.0 h = bi.1 curgsel = ginfo_sel repeat 1 if _mode ! 0 : break mref bmscr,67 ;// ぷましゃんスクリを参考にしてみた if bmscr.17=1 : buffer ginfo_sel, w, h : break if bmscr.17=2 : screen ginfo_sel, w, h, bmscr.19&$ffff<<1 : break bgscr ginfo_sel, w, h, 0 loop SetDIBitsToDevice hdc,ginfo_cx,ginfo_cy,w,h,0,0,0,h,pbm,pbi,0 redraw LocalUnlock HBi LocalUnlock HBm LocalFree HBi LocalFree HBm return 0 ;// 画像ロード ファイル名, picload モード ;// ……とてつもなく中途半端 #deffunc spi_Picload str _fn, int _mode, local fn ,\ local pfn, local prm, local ret fn = _fn exist fn : if strsize = -1 : return -1 : else : sz = strsize ; if getpath(fn,18)=".bmp" : picload fn,_mode : return 0 ret = -2 sdim filebuffer,sz bload fn,filebuffer repeat LoadedPlugins if spi_IsSupported(hModule.cnt, fn, varptr(filebuffer)) { spi_GetPicture hModule.cnt, varptr(filebuffer), sz, _mode if stat = 0 { ret = 0 : break } } if spi_IsSupported(hModule.cnt, fn, varptr(filebuffer)+128) { spi_GetPicture hModule.cnt, varptr(filebuffer)+128, sz-128, _mode if stat = 0 { ret = 0 : break } } loop return ret #global _spi_init ////////////////////////////////////////////////// spi_LoadAll dir_cur ;// フォルダ内のspi全読み込み onclick gosub *load stop *load dialog"",16 dir=getpath(refstr,32) file=getpath(refstr,3+8) chdir dir spi_Picload file,1;// 画像ロード ;// stat=0なら成功、-1ならファイルが見つからない、-2はそれ以外のエラー return



この記事に返信する


窓月らら

リンク

2022/7/13(Wed) 20:38:29|NO.96801

> varptr(filebuffer)
これは変数 filebuffer のポインタを取得という意味ですから
+128はそのポインタから+128バイト(ヘッダ?)先を示していると思われます。
固定長ヘッダならこれでいいかもしれませんが、固定長なんでしょうか?
pngについて調べたほうがよさそうです。

参考
PNG ファイルフォーマット
https://www.setsuki.com/hsp/ext/png.htm



沢渡

リンク

2022/7/13(Wed) 21:37:51|NO.96802

Susieプラグインは過去に実験的に弄ったことがある程度なので
間違っていたら申し訳ないのですが、私が検証してみた限り、

・DLL Export Viewerを使ってIFPNG.SPIに内蔵されている関数を調べても、  Susieプラグインの標準的なAPIしかなく、pngならではのものは無かった。 ・spi_GetPicture内で使われているBITMAPINFOHEADERのbiBitCountを見ても24で  (R・G・Bがそれぞれ8bitで合計24bit)、透過色に関する情報は無い様子。 ・ConfigurationDlgで設定ダイアログを表示する、というのもやってみたが、  見た感じどうも「特定の背景色に透過情報ありの画像データを合成する」という  作業をIFPNG.SPI自身が自動的に行ってしまうようで、  透過情報を抜き出すことはできない模様?
というわけで、私が調べた限りでは、どうやらSusieプラグインを使って
pngの透過情報を抜き出すことはできない様子です。
Artlet2Dを使えばpngの透過情報は抜き出せると思いますが、
Susieプラグインでなければいけない理由があるのでしょうか?
(以下、Artlet2Dを使った場合)

#include "a2d.hsp" dir=dir_cur dialog "*.*",16 if stat=0 : end chdir dir alCreateImageByFile 0,refstr : alSelectImage 0 w=alGetWidth() : h=alGetHeight() screen 0,w,h ddim mat,20 mat(MAT_R)=0.0, 0.0, 0.0, 1.0, 0.0 mat(MAT_G)=0.0, 0.0, 0.0, 1.0, 0.0 mat(MAT_B)=0.0, 0.0, 0.0, 1.0, 0.0 mat(MAT_A)=0.0, 0.0, 0.0, 0.0, 1.0 alCopyModeColorMatrix mat alCopyImageToScreen 0,0,0,0,w,h,0,0 redraw 1

>+128...これが何の役割を果たすのかも理解できずにいます
Macバイナリ対策のようです。
まずMacバイナリが無いものとして、ロードしたファイルが
Susieプラグインで扱える画像ファイルなのかどうかをチェックし、
その後にMacバイナリがあるものとして同じことを繰り返しているという
流れです。



ham

リンク

2022/7/14(Thu) 09:43:32|NO.96803

窓月らら様、沢渡様、ご回答ありがとうございます。

+128は自分も画像の形式に関連するヘッダの先を示しているかと思っていたのですが、
Macバイナリというものがあるのは初めて知りました。

Susieプラグインを詳しく調べていただきありがとうございます。
とても勉強になりました。


>Artlet2Dを使えばpngの透過情報は抜き出せると思いますが、
>Susieプラグインでなければいけない理由があるのでしょうか?

Susieを使う理由は、自分で試した限りでは他のどの方法よりも高速に画像を読み込めるようだったからです。
作っているソフトの都合上、透過情報のみを抜き出す必要があり、今はimgctl.dllを使って抜き出しています。
Artlet2Dでも良いのですが、解像度が高い画像だとどうしても速度が遅くなってしまうのです...(imgctlでもやや遅いですが)

事前に書いておくべきでした。失礼しました。


現状維持しながら他にもっと高速な方法が無いか調べてみます。



usagi

リンク

2022/7/14(Thu) 16:49:54|NO.96805

Artlet2Dの中身ってgdiだと思うので、そこまで遅くないような気がしていて、
hamさんのホームページにあるようなデスクトップマスコットのような使い方であれば、
おそらく、透明情報だけを抜き出して何かしらレイヤーウインドウに設定するのに速度が遅くなっている様な気がしまして、
アルファ付きのバッファをそのまま使ったらダメですかね。私の環境だと以下の例で一瞬で表示されます。

※画像ドロップ:開く、ESC:終了
※あとSusieは24bitみたいで、きれいなアルファ抜きは出来ないですね。(内部で背景色に合成される)
 もし何かのライブラリを利用されるなら32bitのDIBを返すプラグインを探されるのが良いかと思います。


;------------------------------------------------- #module LAYERED_WINDOW #uselib "gdi32.dll" #cfunc CreateCompatibleDC "CreateCompatibleDC" sptr #func DeleteDC "DeleteDC" sptr #cfunc CreateCompatibleBitmap "CreateCompatibleBitmap" sptr,sptr,sptr #func SelectObject "SelectObject" sptr,sptr #func DeleteObject "DeleteObject" sptr #func StretchDIBits "StretchDIBits" sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr #define SRCCOPY 0x00CC0020 #define CAPTUREBLT 0x40000000 #uselib "user32.dll" #cfunc GetWindowLongA "GetWindowLongA" sptr,sptr #func SetWindowLongA "SetWindowLongA" sptr,sptr,sptr #define GWL_STYLE -16 #define GWL_EXSTYLE -20 #define WS_EX_LAYERED 0x00080000 #func UpdateLayeredWindow "UpdateLayeredWindow" sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr #define ULW_COLORKEY 0x00000001 #define ULW_ALPHA 0x00000002 #define ULW_OPAQUE 0x00000004 #define ULW_EX_NORESIZE 0x00000008 #cfunc GetDC "GetDC" sptr #func ReleaseDC "ReleaseDC" sptr,sptr #define ctype BLEND_FUNCTION(%1=0,%2=0,%3=255,%4=1) (((%4&0xFF)<<24)|((%3&0xFF)<<16)|((%2&0xFF)<<8)|(%1&0xFF)) #define AC_SRC_OVER 0x00 #define AC_SRC_ALPHA 0x01 #deffunc lwAlpha var bmp, int alpha _hdc = GetDC(hwnd) hsrcdc = CreateCompatibleDC(_hdc) hbitmap = CreateCompatibleBitmap(_hdc, ginfo_sx, ginfo_sy) ReleaseDC hwnd, _hdc SelectObject hsrcdc, hbitmap bmpinfo = 40, ginfo_sx, ginfo_sy, 0x200001, 0 ; StretchDIBits hsrcdc, 0,0,ginfo_sx, ginfo_sy, 0,0,ginfo_sx, ginfo_sy, varptr(bmp), varptr(bmpinfo), DIB_RGB_COLORS, SRCCOPY|CAPTUREBLT StretchDIBits hsrcdc, 0,0,ginfo_sx, ginfo_sy, 0,ginfo_sy,ginfo_sx, -ginfo_sy, varptr(bmp), varptr(bmpinfo), DIB_RGB_COLORS, SRCCOPY|CAPTUREBLT; 上下反転が必要な場合 wpt = ginfo_wx1, ginfo_wy1 : wsize = ginfo_sx, ginfo_sy : pt = 0, 0 blend = BLEND_FUNCTION(AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA) SetWindowLongA hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED UpdateLayeredWindow hwnd, hdc, varptr(wpt), varptr(wsize), hsrcdc, varptr(pt), 0, varptr(blend), ULW_ALPHA DeleteObject hbitmap DeleteDC hsrcdc return #global ;------------------------------------------------ #include "a2d.hsp" #uselib "shell32.dll" #func DragAcceptFiles "DragAcceptFiles" sptr,sptr #func DragQueryFile "DragQueryFileA" sptr,sptr,sptr,sptr #func DragFinish "DragFinish" sptr DragAcceptFiles hwnd, 1 oncmd gosub *WM_DROPFILES, 0x0233 oncmd gosub *WM_LBUTTONDOWN, 0x0201 onkey gosub *ON_KEY stop *WM_DROPFILES hDrop = wParam : sdim file, 260 : DragQueryFile hDrop, 0, varptr(file), 260 : DragFinish hDrop alCreateImageByFile 0,file : if stat != 0 : return screen 0,alGetWidth(),alGetHeight(),screen_hide : DragAcceptFiles hwnd, 1 ;-------------------------- alGetBitmapVData _size, _bitmap ; alpha付きbitmap取得 lwAlpha _bitmap, 255 ; ←追加した命令 ;-------------------------- gsel 0,2 : redraw 1 return *WM_LBUTTONDOWN gsel ginfo_intid sendmsg hwnd , 0x00a1 , 0x02 , lparam return *ON_KEY if iparam = 27 : end return



ham

リンク

2022/7/15(Fri) 09:23:17|NO.96808

usagi様、ご回答ありがとうございます。

Artlet2Dでも32bitのDIBのまま処理するとこんなにも高速になるのですね。
お察しの通り、今までHSPの通常のウィンドウに描画してから処理していたのですが、それが非常に遅いのですね。
Susieが高速だったのは、元々24bit故に24bitへの変換が必要なかったからでしょうかね?

今の自分の知識で上手く扱えるかどうか少し不安ですが、有難く使わせていただきます!



ham

リンク

2022/7/15(Fri) 13:51:03|NO.96809

自力で解決しようかと思いましたが、無理だったので教えて欲しいです。

usagi様のスクリプトでいくつか透過PNGを読み込んで試してみたのですが、
何かがおかしいようで、透過が正しく行われていない?ようなのです。

例としてこの画像を読み込むと
https://imgur.com/KpaF59R

こうなってしまいます。
https://imgur.com/4RyFcod



usagi

リンク

2022/7/16(Sat) 05:34:12|NO.96810

おぉ、すみません。MSDNの説明みたらアルファ値を事前乗算してくれとありましたね。
https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-blendfunction
"the red, green and blue channel values in the bitmap must be premultiplied"

もしかしたら遅いと仰られていた原因がコレなのかもですね。(HSPで事前乗算すると結構時間かかるので)
この部分だけCでやった方が良いのかもしれませんが、Artlet2Dでこのまま作ってみました。
どう早くするかは時間のある時に考えてみますが、取り急ぎ正しく表示されると思いますのでどうぞ。


;================================================ #module LAYERED_WINDOW ; gdi32 --------------------- #uselib "gdi32.dll" #func CreateDIBSection "CreateDIBSection" sptr,sptr,sptr,sptr,sptr,sptr #cfunc CreateCompatibleDC "CreateCompatibleDC" sptr #func DeleteDC "DeleteDC" sptr #cfunc CreateCompatibleBitmap "CreateCompatibleBitmap" sptr,sptr,sptr #func SelectObject "SelectObject" sptr,sptr #func DeleteObject "DeleteObject" sptr #func StretchDIBits "StretchDIBits" sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr #define SRCCOPY 0x00CC0020 #define CAPTUREBLT 0x40000000 ; user32 -------------------- #uselib "user32.dll" #cfunc GetWindowLongA "GetWindowLongA" sptr,sptr #func SetWindowLongA "SetWindowLongA" sptr,sptr,sptr #func UpdateLayeredWindow "UpdateLayeredWindow" sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr #cfunc GetDC "GetDC" sptr #func ReleaseDC "ReleaseDC" sptr,sptr #define GWL_STYLE -16 #define GWL_EXSTYLE -20 #define WS_EX_LAYERED 0x00080000 #define ULW_COLORKEY 0x00000001 #define ULW_ALPHA 0x00000002 ;#define ctype BLEND_FUNCTION(%1=255) (0x01000000|((%1&0xFF)<<16)) #define ctype BLEND_FUNCTION(%1=255) (0x01000104|((%1&0xFF)<<16)) ; function ------------------ #deffunc lwAlpha var bmp, int alpha bmpinfo = 40, ginfo_sx, ginfo_sy, 1|(32<<16), 0 ,0,0,0,0,0 hdcDst = GetDC(0) hsrcdc = CreateCompatibleDC(hdcDst) hbitmap = CreateCompatibleBitmap(hdcDst, ginfo_sx, ginfo_sy) SelectObject hsrcdc, hbitmap StretchDIBits hsrcdc, 0,0,ginfo_sx,ginfo_sy, 0,ginfo_sy,ginfo_sx,-ginfo_sy, varptr(bmp), varptr(bmpinfo), 0, SRCCOPY|CAPTUREBLT SetWindowLongA hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ptDst = ginfo_wx1, ginfo_wy1 size = ginfo_sx, ginfo_sy ptSrc = 0, 0 blend = BLEND_FUNCTION(alpha) crKey = 0 dwFlags = ULW_ALPHA UpdateLayeredWindow hwnd, hdcDst, varptr(ptDist), varptr(size), hsrcdc, varptr(ptSrc), crKey, varptr(blend), dwFlags ReleaseDC 0, hdcDst DeleteObject hbitmap DeleteDC hsrcdc return #global ;================================================ #include "a2d.hsp" #uselib "shell32.dll" #func DragAcceptFiles "DragAcceptFiles" sptr,sptr #func DragQueryFile "DragQueryFileA" sptr,sptr,sptr,sptr #func DragFinish "DragFinish" sptr DragAcceptFiles hwnd, 1 oncmd gosub *WM_DROPFILES, 0x0233 oncmd gosub *WM_LBUTTONDOWN, 0x0201 onkey gosub *ON_KEY stop *WM_DROPFILES hDrop = wParam : sdim file, 260 : DragQueryFile hDrop, 0, varptr(file), 260 : DragFinish hDrop alCreateImageByFile 0,file : if stat != 0 : return screen 0,alGetWidth(),alGetHeight(),screen_hide : DragAcceptFiles hwnd, 1 ; ※追加 事前乗算 ※※※※※※※※ alCreateImage 1, alGetWidth(), alGetHeight() alColor: alFillRect : alCopyImageToImage 0,1 alSelectImage 0 : alGetBitmapVData _size, _bitmap ; alpha付きbitmap取得 alSelectImage 1 : alGetBitmapVData _size, _bitmapm ; alpha事前乗算済bitmap取得 repeat length(_bitmap) _bitmap(cnt) = (_bitmap(cnt)&0xFF000000) | (_bitmapm(cnt)&0x00FFFFFF) loop ;※※※※※※※※※※※※※※※※※ lwAlpha _bitmap, 255 ; ←追加した命令 gsel 0,2 : redraw 1 return *WM_LBUTTONDOWN gsel ginfo_intid sendmsg hwnd , 0x00a1 , 0x02 , lparam return *ON_KEY if iparam = 27 : end return



usagi

リンク

2022/7/16(Sat) 06:05:35|NO.96811

あっ、hamさんが作られてるソフトの方が断然読み込み早いです。(気合入ってますね。)
愚直なループ部分を何んとかしないとダメですね。



MIZUSHIKI

リンク

2022/7/16(Sat) 06:25:25|NO.96812

a2d.hsp の alGetBitmapVData命令内では PixelFormat32bppARGB を指定してピクセルデータを取得しているのですが、PixelFormat32bppPARGB を指定するとアルファ値が事前乗算されたデータを取得することができます。
ということで、a2d.hsp を少し拡張しました。

;------------------------------------------------- #module LAYERED_WINDOW #uselib "gdi32.dll" #cfunc CreateCompatibleDC "CreateCompatibleDC" sptr #func DeleteDC "DeleteDC" sptr #cfunc CreateCompatibleBitmap "CreateCompatibleBitmap" sptr,sptr,sptr #func SelectObject "SelectObject" sptr,sptr #func DeleteObject "DeleteObject" sptr #func StretchDIBits "StretchDIBits" sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr #define SRCCOPY 0x00CC0020 #define CAPTUREBLT 0x40000000 #uselib "user32.dll" #cfunc GetWindowLongA "GetWindowLongA" sptr,sptr #func SetWindowLongA "SetWindowLongA" sptr,sptr,sptr #define GWL_STYLE -16 #define GWL_EXSTYLE -20 #define WS_EX_LAYERED 0x00080000 #func UpdateLayeredWindow "UpdateLayeredWindow" sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr #define ULW_COLORKEY 0x00000001 #define ULW_ALPHA 0x00000002 #define ULW_OPAQUE 0x00000004 #define ULW_EX_NORESIZE 0x00000008 #cfunc GetDC "GetDC" sptr #func ReleaseDC "ReleaseDC" sptr,sptr #define ctype BLEND_FUNCTION(%1=0,%2=0,%3=255,%4=1) (((%4&0xFF)<<24)|((%3&0xFF)<<16)|((%2&0xFF)<<8)|(%1&0xFF)) #define AC_SRC_OVER 0x00 #define AC_SRC_ALPHA 0x01 #deffunc lwAlpha var bmp, int alpha _hdc = GetDC(hwnd) hsrcdc = CreateCompatibleDC(_hdc) hbitmap = CreateCompatibleBitmap(_hdc, ginfo_sx, ginfo_sy) ReleaseDC hwnd, _hdc SelectObject hsrcdc, hbitmap bmpinfo = 40, ginfo_sx, ginfo_sy, 0x200001, 0 ; StretchDIBits hsrcdc, 0,0,ginfo_sx, ginfo_sy, 0,0,ginfo_sx, ginfo_sy, varptr(bmp), varptr(bmpinfo), DIB_RGB_COLORS, SRCCOPY|CAPTUREBLT StretchDIBits hsrcdc, 0,0,ginfo_sx, ginfo_sy, 0,ginfo_sy,ginfo_sx, -ginfo_sy, varptr(bmp), varptr(bmpinfo), DIB_RGB_COLORS, SRCCOPY|CAPTUREBLT; 上下反転が必要な場合 wpt = ginfo_wx1, ginfo_wy1 : wsize = ginfo_sx, ginfo_sy : pt = 0, 0 blend = BLEND_FUNCTION(AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA) SetWindowLongA hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED UpdateLayeredWindow hwnd, hdc, varptr(wpt), varptr(wsize), hsrcdc, varptr(pt), 0, varptr(blend), ULW_ALPHA DeleteObject hbitmap DeleteDC hsrcdc return #global ;------------------------------------------------ #include "a2d.hsp" ;-- a2d.hsp を拡張 ------------------------------ #module a2dp #const PixelFormat32bppPARGB $E200B #deffunc alGetBitmapPVData_start var ps, var pv ; size, vvar if imgValid@a2d { ; LockBits して bitmap image へのポインタを得る rect@a2d = 0, 0, imgWidth@a2d, imgHeight@a2d dim BitmapData@a2d, 8 GdipBitmapLockBits@a2d imgImage@a2d, varptr(rect@a2d), 1, PixelFormat32bppPARGB, varptr(BitmapData@a2d) ;GdipBitmapUnlockBits@a2d imgImage@a2d, varptr(BitmapData@a2d) ps = BitmapData@a2d(0) * BitmapData@a2d(1) * 4 ; Width * Height * ByPP dupptr pv, BitmapData@a2d(4), ps ;ロックしたままにして return 0 } return -1 #deffunc alGetBitmapPVData_end if imgValid@a2d { GdipBitmapUnlockBits@a2d imgImage@a2d, varptr(BitmapData@a2d) ;アンロック return 0 } return -1 #global ;------------------------------------------------ #uselib "shell32.dll" #func DragAcceptFiles "DragAcceptFiles" sptr,sptr #func DragQueryFile "DragQueryFileA" sptr,sptr,sptr,sptr #func DragFinish "DragFinish" sptr DragAcceptFiles hwnd, 1 oncmd gosub *WM_DROPFILES, 0x0233 oncmd gosub *WM_LBUTTONDOWN, 0x0201 onkey gosub *ON_KEY stop *WM_DROPFILES hDrop = wParam : sdim file, 260 : DragQueryFile hDrop, 0, varptr(file), 260 : DragFinish hDrop alCreateImageByFile 0,file : if stat != 0 : return screen 0,alGetWidth(),alGetHeight(),screen_hide : DragAcceptFiles hwnd, 1 ;-------------------------- alGetBitmapPVData_start _size, _bitmap ; alpha付きbitmap取得(ロックしたまま) lwAlpha _bitmap, 255 ; ←追加した命令 alGetBitmapPVData_end ; (ロック解除) ;-------------------------- gsel 0,2 : redraw 1 return *WM_LBUTTONDOWN gsel ginfo_intid sendmsg hwnd , 0x00a1 , 0x02 , lparam return *ON_KEY if iparam = 27 : end return
ただ、 alGetBitmapVData命令内の GdipBitmapLockBits をすぐアンロックしてしまうと上手くいかないようなので(?)、ロックしたままにして使ったあとアンロックしています。
(なんで PixelFormat32bppARGB の場合は問題ないのに、PixelFormat32bppPARGB だと上手くいかないのかはよくわかっていません;;)



usagi

リンク

2022/7/16(Sat) 10:44:20|NO.96813

>MIZUSHIKIさん
素晴らしいですね! Artlet2Dを改造しないと出来ないなぁと思ってたのですが、
拡張の記入の発想。大変参考になりました。

ロックビットは私的には使い終わったらアンロックするようなイメージがあったので、
元がすぐにアンロックして動いているのが不思議に思ってました。
MIZUSHIKIさんのやり方が正しいと考えてます。



usagi

リンク

2022/7/16(Sat) 12:09:34|NO.96814

ご指摘を反映して修正と整理をしてみました。
Artlet2Dのカレントイメージで現在のスクリーンをレイヤーウインドウで表示します。
速度的な問題はなさそうです。


;================================================ ; Include guard #ifndef alInitModule #include "a2d.hsp" #endif #ifndef lwAlpha #module LAYERED_WINDOW ; gdi+ ---------------------- #const PixelFormat32bppPARGB $E200B ; gdi32 --------------------- #uselib "gdi32.dll" #func CreateDIBSection "CreateDIBSection" sptr,sptr,sptr,sptr,sptr,sptr #cfunc CreateCompatibleDC "CreateCompatibleDC" sptr #func DeleteDC "DeleteDC" sptr #cfunc CreateCompatibleBitmap "CreateCompatibleBitmap" sptr,sptr,sptr #func SelectObject "SelectObject" sptr,sptr #func DeleteObject "DeleteObject" sptr #func StretchDIBits "StretchDIBits" sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr #define SRCCOPY 0x00CC0020 #define CAPTUREBLT 0x40000000 ; user32 -------------------- #uselib "user32.dll" #cfunc GetWindowLongA "GetWindowLongA" sptr,sptr #func SetWindowLongA "SetWindowLongA" sptr,sptr,sptr #func UpdateLayeredWindow "UpdateLayeredWindow" sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr #cfunc GetDC "GetDC" sptr #func ReleaseDC "ReleaseDC" sptr,sptr #define GWL_STYLE -16 #define GWL_EXSTYLE -20 #define WS_EX_LAYERED 0x00080000 #define ULW_COLORKEY 0x00000001 #define ULW_ALPHA 0x00000002 #define ctype BLEND_FUNCTION(%1=255) (0x01000000|((%1&0xFF)<<16)) ; Function ------------------ #deffunc lwAlpha int alpha ; a2dのカレントからLockBits if imgValid@a2d == 0 { return -1 } rect@a2d = 0, 0, imgWidth@a2d, imgHeight@a2d dim BitmapData@a2d, 8 GdipBitmapLockBits@a2d imgImage@a2d, varptr(rect@a2d), 1, PixelFormat32bppPARGB, varptr(BitmapData@a2d) dupptr bmp, BitmapData@a2d(4), BitmapData@a2d(0) * BitmapData@a2d(1) * 4 ; スクリーンと互換性のあるデバイスコンテキスト、ビットマップ作成 hdcDst = GetDC(0) hsrcdc = CreateCompatibleDC(hdcDst) hbitmap = CreateCompatibleBitmap(hdcDst, ginfo_sx, ginfo_sy) ; ビットマップコピー SelectObject hsrcdc, hbitmap bmpinfo = 40, ginfo_sx, ginfo_sy, 1|(32<<16), 0 ,0,0,0,0,0 StretchDIBits hsrcdc, 0,0,ginfo_sx,ginfo_sy, 0,ginfo_sy,ginfo_sx,-ginfo_sy, varptr(bmp), varptr(bmpinfo), 0, SRCCOPY|CAPTUREBLT ; レイヤードウインドウ SetWindowLongA hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ptDst = ginfo_wx1, ginfo_wy1 : size = ginfo_sx, ginfo_sy ptSrc = 0, 0 : blend = BLEND_FUNCTION(alpha) crKey = 0 : dwFlags = ULW_ALPHA UpdateLayeredWindow hwnd, hdcDst, varptr(ptDst), varptr(size), hsrcdc, varptr(ptSrc), crKey, varptr(blend), dwFlags ; 解放 ReleaseDC 0, hdcDst : DeleteObject hbitmap : DeleteDC hsrcdc GdipBitmapUnlockBits@a2d imgImage@a2d, varptr(BitmapData@a2d) return #global #endif ;================================================ ; サンプル #uselib "shell32.dll" #func DragAcceptFiles "DragAcceptFiles" sptr,sptr #func DragQueryFile "DragQueryFileA" sptr,sptr,sptr,sptr #func DragFinish "DragFinish" sptr alpha = 255 DragAcceptFiles hwnd, 1 oncmd gosub *WM_DROPFILES, 0x0233 oncmd gosub *WM_LBUTTONDOWN, 0x0201 onkey gosub *ON_KEY stop *WM_DROPFILES hDrop = wParam : sdim file, 260 : DragQueryFile hDrop, 0, varptr(file), 260 : DragFinish hDrop alCreateImageByFile 0,file : if stat != 0 : return screen 0,alGetWidth(),alGetHeight(),screen_hide : DragAcceptFiles hwnd, 1 lwAlpha alpha : gsel 0,2 return *WM_LBUTTONDOWN sendmsg hwnd , 0x00a1 , 0x02 , lparam return *ON_KEY if wparam = 27 : end if wparam = 38 : alpha = limit(alpha+16, 32,255) if wparam = 40 : alpha = limit(alpha-16, 32,255) alSelectImage 0 : lwAlpha alpha return



ham

リンク

2022/7/16(Sat) 14:15:37|NO.96816

usagi様、MIZUSHIKI様、ありがとうございます。
素晴らしく完璧です!自分も早く同じような事が出来るようになりたいです。

後は頑張って組み込んでみます。
仕組みの完全な理解は時間が掛かりそうですが^^;



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