I'm just learning GDI+ and I found this reference manual:
http://www.autohotkey.com/forum/topic70935.html
Now, I want to apply some glass effect into a bmp image (see attached image from oxygen4.6.2 free iconset):
I think I need this:
1. Make a copy of the original image.
2. Make a mask of the glass effect.
3. A way to increase the white level of the copied image.
4. A way to make some gradient of the white level image.
5. blend or mix both images using the mask.
Before reinvent the wheel.... does anybody has done this before?
After this I want to make a crystal reflex affect, just like itunes does. any idea?
best regards.
By the way: here is my -blind- code to load a memory file image using the Gdi+, I just take some pieces from this forum.
I dunno if everything is "legal" with GDI+ methods.... I will read the methods next week. Any way... you're welcome to flame my code!
The pMemoryFile parameter is a (Invoke GlobalAlloc,GPTR,eax) object with a copy of the bmp/jpg/pgn/etc file.
The dFileSize is a ancient reptilium dna code
align 4
Dib32FromGDIPlusMemory proc pMemoryFile:DWORD,dFileSize:DWORD
;
LOCAL dLastError:DWORD
LOCAL hBuffer:DWORD
LOCAL pBuffer:DWORD
LOCAL pStream:DWORD
LOCAL dToken:DWORD
LOCAL oBmp:DWORD
LOCAL hBmp:DWORD
LOCAL GdipSI:GdiplusStartupInput
;
;
xor eax,eax
mov dLastError,eax
;
xor eax,eax
mov GdipSI.GdiplusVersion,1
mov GdipSI.DebugEventCallback,eax
mov GdipSI.SuppressBackgroundThread,eax
mov GdipSI.SuppressExternalCodecs,eax
mov hBmp,eax
Invoke GdiplusStartup,addr dToken,addr GdipSI,0 ;Init the GDI+ Engine. ;token:DWORD, inputbuf:GdiplusStartupInput, Optional outputbuf:DWORD = 0
.if eax!=S_OK
xor eax,eax
.else
Invoke CreateStreamOnHGlobal,pMemoryFile,FALSE,addr pStream ;Create a Stream from the hBuffer
.if eax==S_OK
Invoke GdipCreateBitmapFromStream,pStream,addr oBmp ;Create a Bmp Object
Invoke GdipCreateHBITMAPFromBitmap,oBmp,addr hBmp,0 ;Create a regular hBmp from oBmp ; bitmap:DWORD, hbmReturn:DWORD, background:DWORD
Invoke GdipDisposeImage,oBmp ;Delete the oBmp Object ;image:DWORD
mov eax,pStream
push eax
mov eax,dword ptr [eax]
call [eax].IStream.IUnknown.Release ;Delete the Stream
.endif
;Invoke GdiplusShutdown,addr dToken ;Kill the GDI+ Engine ;addr dToken: returns S_OK
;Invoke GdiplusShutdown,NULL ;Kill the GDI+ Engine ;NULL: returns S_OK
Invoke GdiplusShutdown,dToken ;Kill the GDI+ Engine ;dToken returns S_OK
;Invoke GdiplusShutdown,addr szTexts ;Kill the GDI+ Engine ;addr szTexts returns S_OK
;.if eax==S_OK
; Invoke MessageBox,NULL,addr szTexts,NULL,NULL
;.endif
;
.if hBmp==0 ;Oops! the pMemoryFile has an invalid or bad format
Invoke SetLastError,ERROR_NOT_SUPPORTED
xor eax,eax
.else
mov eax,hBmp
.endif
.endif
;
Exit_Dib32FromGDIPlusFile:
;
ret
Dib32FromGDIPlusMemory endp
Best regards
Your example look like made with an Image editor (Photoshop,...). You will get similarly results by drawing parts of a huge, white circle with an opacity of ~15% (alpaha=0.15) over the button-image. Using a radial gradint brush for the circle would be fine tuning :8)
BTW: the GDIp-initialization should be done at process begin and not if the functions are needed (overheap)
Quote from: qWord on November 19, 2011, 01:53:53 AM
BTW: the GDIp-initialization should be done at process begin and not if the functions are needed (overheap)
Nice tip!
What about this:
;Invoke GdiplusShutdown,addr dToken ;Kill the GDI+ Engine ;addr dToken: returns S_OK
;Invoke GdiplusShutdown,NULL ;Kill the GDI+ Engine ;NULL: returns S_OK
Invoke GdiplusShutdown,dToken ;Kill the GDI+ Engine ;dToken returns S_OK
;Invoke GdiplusShutdown,addr szTexts ;Kill the GDI+ Engine ;addr szTexts returns S_OK
Why, no matter how the GdiplusShutdown is called, always returns S_OK ?
I'll swim deep in the GDI+ api to guess about it!
Thank you!
The flow for a 'normal' window application:
...
Invoke GdiplusStartup,addr dToken,addr GdipSI,0
...
<window creation>
...
<message loop>
...
invoke GdiplusShutdown,dToken
invoke ExitProcess,0
For creating alpha effect, you have to add each channel from 2 pixel from 2 image and then average it. Or, you can set Pic A each channel for10% and Pic B each channel 90% and then add it. That simple. But, if you used GPU, it is automatically, and for 800x600 pixel it only took 1% each 30 picture.
And for glass effect you have to bias it. For example, pixel from POINT(100,100) substrac the Y by 10 for every pixel on the region.
(http://ompldr.org/vYmNsMQ/SS.gif)
Here is the code, NigthWare Optimized it
nwBlendPixel proc pixel:dword,pixel2:dword,percent:dword
; NightWare algo from www.masm32.com
mov eax,percent ; 0 to 100
mov edx,0FFh
mul edx
mov edx,42949673
mul edx ; become 0 to 255 in edx
shl edx,24 ; A,_,_,_
mov eax,pixel ; _,R,G,B read pixel
or eax,edx ; A,R,G,B add alpha
mov edx,pixel2 ; _,R,G,B read pixel2
pxor MM7,MM7 ; MM7 = 0,0,0,0 , 0,0,0,0
movq MM6,QWORD PTR Sprite_Simd_Mask_RVB_unpck_1 ; MM6 = 0,0,0,1 , 0,1,0,1
movd MM1,eax ; MM1 = _,_,_,_ , A,R,G,B (pixel)
movd MM0,edx ; MM0 = _,_,_,_ , A,R,G,B (pixel2)
punpcklbw MM1,MM7 ; MM1 = 0,A,0,R , 0,G,0,B
punpcklbw MM0,MM7 ; MM0 = 0,A,0,R , 0,G,0,B
movq MM2,MM1 ; MM2 = 0,A,0,R , 0,G,0,B
pshufw MM2,MM2,0FFh ; MM2 = 0,A,0,A , 0,A,0,A
movq MM3,QWORD PTR Sprite_Simd_Mask_RVB_unpck_255 ; MM3 = 0,0,0,255 , 0,255,0,255
psubw MM3,MM2 ; MM3 = 0,~A,0,~A , 0,~A,0,~A
paddw MM2,MM6 ; MM2 = 0,A+1,0,A+1 , 0,A+1,0,A+1
paddw MM3,MM6 ; MM3 = 0,~A+1,0,~A+1 , 0,~A+1,0,~A+1
pmullw MM1,MM2 ; MM1 = A*A,R*A , G*A,B*A
pmullw MM0,MM3 ; MM0 = A*0,R*A , G*A,B*A
paddw MM0,MM1 ; MM0 = A*0+A*0,R*A+R*A , G*A+G*A,B*A+B*A
psrlw MM0,8 ; MM0 = 0,A,0,R , 0,G,0,B
packuswb MM0,MM7 ; MM0 = _,_,_,_ , A,R,G,B
movd eax,MM0 ; A,R,G,B new
emms
and eax,000FFFFFFh ; _,R,G,B only keep RGB
ret
nwBlendPixel endp
Try to take 2 pixel from the same coordinate from 2 picture, and the blend it on a new picture. Youll see it.
Wow, Just played around BlendPixel... that's what I need...
also found usefull this link to make the elaborate gradient:
http://www.flounder.com/gradientfiller.htm
Thank you!
;)
Quote from: Farabi on November 19, 2011, 04:40:28 AM
Here is the code, NigthWare Optimized it
nwBlendPixel proc pixel:dword,pixel2:dword,percent:dword
; NightWare algo from www.masm32.com
mov eax,percent ; 0 to 100
mov edx,0FFh
mul edx
mov edx,42949673
mul edx ; become 0 to 255 in edx
shl edx,24 ; A,_,_,_
mov eax,pixel ; _,R,G,B read pixel
or eax,edx ; A,R,G,B add alpha
mov edx,pixel2 ; _,R,G,B read pixel2
pxor MM7,MM7 ; MM7 = 0,0,0,0 , 0,0,0,0
movq MM6,QWORD PTR Sprite_Simd_Mask_RVB_unpck_1 ; MM6 = 0,0,0,1 , 0,1,0,1
movd MM1,eax ; MM1 = _,_,_,_ , A,R,G,B (pixel)
movd MM0,edx ; MM0 = _,_,_,_ , A,R,G,B (pixel2)
punpcklbw MM1,MM7 ; MM1 = 0,A,0,R , 0,G,0,B
punpcklbw MM0,MM7 ; MM0 = 0,A,0,R , 0,G,0,B
movq MM2,MM1 ; MM2 = 0,A,0,R , 0,G,0,B
pshufw MM2,MM2,0FFh ; MM2 = 0,A,0,A , 0,A,0,A
movq MM3,QWORD PTR Sprite_Simd_Mask_RVB_unpck_255 ; MM3 = 0,0,0,255 , 0,255,0,255
psubw MM3,MM2 ; MM3 = 0,~A,0,~A , 0,~A,0,~A
paddw MM2,MM6 ; MM2 = 0,A+1,0,A+1 , 0,A+1,0,A+1
paddw MM3,MM6 ; MM3 = 0,~A+1,0,~A+1 , 0,~A+1,0,~A+1
pmullw MM1,MM2 ; MM1 = A*A,R*A , G*A,B*A
pmullw MM0,MM3 ; MM0 = A*0,R*A , G*A,B*A
paddw MM0,MM1 ; MM0 = A*0+A*0,R*A+R*A , G*A+G*A,B*A+B*A
psrlw MM0,8 ; MM0 = 0,A,0,R , 0,G,0,B
packuswb MM0,MM7 ; MM0 = _,_,_,_ , A,R,G,B
movd eax,MM0 ; A,R,G,B new
emms
and eax,000FFFFFFh ; _,R,G,B only keep RGB
ret
nwBlendPixel endp
Try to take 2 pixel from the same coordinate from 2 picture, and the blend it on a new picture. Youll see it.
caraveiro,
do you want to use GDI+ or not?
I'm not sure why Farabi has shown these SSEx code, but it is absolutely not needed when using the GDI+.
In the attachment an example, which is using linear and path-gradients to get a glass-effect.
Because some calculations are needed, I've used my own macros, which can be downloaded here (http://sourceforge.net/projects/smplmath/).
here is an example how you can blend with right textures
Quote from: qWord on November 23, 2011, 08:39:59 PM
In the attachment an example, which is using linear and path-gradients to get a glass-effect.
Because some calculations are needed, I've used my own macros, which can be downloaded here (http://sourceforge.net/projects/smplmath/).
:eek Thats so complicated. Is that how to use GDI+? I never checked the performance, but is it had any 2D acceleration? Compared to NW code above, is GDI+ faster?
Quote from: caraveiro on November 23, 2011, 06:22:39 PM
Wow, Just played around BlendPixel... that's what I need...
also found usefull this link to make the elaborate gradient:
http://www.flounder.com/gradientfiller.htm
Thank you!
;)
Quote from: Farabi on November 19, 2011, 04:40:28 AM
Here is the code, NigthWare Optimized it
nwBlendPixel proc pixel:dword,pixel2:dword,percent:dword
; NightWare algo from www.masm32.com
mov eax,percent ; 0 to 100
mov edx,0FFh
mul edx
mov edx,42949673
mul edx ; become 0 to 255 in edx
shl edx,24 ; A,_,_,_
mov eax,pixel ; _,R,G,B read pixel
or eax,edx ; A,R,G,B add alpha
mov edx,pixel2 ; _,R,G,B read pixel2
pxor MM7,MM7 ; MM7 = 0,0,0,0 , 0,0,0,0
movq MM6,QWORD PTR Sprite_Simd_Mask_RVB_unpck_1 ; MM6 = 0,0,0,1 , 0,1,0,1
movd MM1,eax ; MM1 = _,_,_,_ , A,R,G,B (pixel)
movd MM0,edx ; MM0 = _,_,_,_ , A,R,G,B (pixel2)
punpcklbw MM1,MM7 ; MM1 = 0,A,0,R , 0,G,0,B
punpcklbw MM0,MM7 ; MM0 = 0,A,0,R , 0,G,0,B
movq MM2,MM1 ; MM2 = 0,A,0,R , 0,G,0,B
pshufw MM2,MM2,0FFh ; MM2 = 0,A,0,A , 0,A,0,A
movq MM3,QWORD PTR Sprite_Simd_Mask_RVB_unpck_255 ; MM3 = 0,0,0,255 , 0,255,0,255
psubw MM3,MM2 ; MM3 = 0,~A,0,~A , 0,~A,0,~A
paddw MM2,MM6 ; MM2 = 0,A+1,0,A+1 , 0,A+1,0,A+1
paddw MM3,MM6 ; MM3 = 0,~A+1,0,~A+1 , 0,~A+1,0,~A+1
pmullw MM1,MM2 ; MM1 = A*A,R*A , G*A,B*A
pmullw MM0,MM3 ; MM0 = A*0,R*A , G*A,B*A
paddw MM0,MM1 ; MM0 = A*0+A*0,R*A+R*A , G*A+G*A,B*A+B*A
psrlw MM0,8 ; MM0 = 0,A,0,R , 0,G,0,B
packuswb MM0,MM7 ; MM0 = _,_,_,_ , A,R,G,B
movd eax,MM0 ; A,R,G,B new
emms
and eax,000FFFFFFh ; _,R,G,B only keep RGB
ret
nwBlendPixel endp
Try to take 2 pixel from the same coordinate from 2 picture, and the blend it on a new picture. Youll see it.
:lol What was that website talking about? They used 3D notation for 2D function or it is just because I did not read it completely yet? That was funny. I was the firs person in here who said shading as gradient, because it was a gradual color changing, but not that stupid. Or maybe it was really me 6 years ago, you know how stupid I was before right? :lol
Now I understood what the website talking about, he refer to a TRIVERTEX coloring on 3D using his tools, That is not obscure, if you know about the UV mapping and a fTRI function I invented youll see that, this tools is usefull for coloring your vertex.
Quote from: Farabi on November 24, 2011, 10:59:37 AM:eek Thats so complicated. Is that how to use GDI+? I never checked the performance, but is it had any 2D acceleration? Compared to NW code above, is GDI+ faster?
If available, Hardware acceleration is used! Generally it is simple to create gradients with GDI+, but it may be complicated to dimension them meaningfull (the same applies to OpenGL and DirectX).
Also, you can not compare NW's routine with code, which is dynamically creating and blending gradients. I can't see the relationship between NW's code and caraveiro's question, because he claims to use GDI+.
Quote from: qWord on November 23, 2011, 06:43:09 PM
caraveiro,
do you want to use GDI+ or not?
I'm not sure why Farabi has shown these SSEx code, but it is absolutely not needed when using the GDI+.
Oh, now, GDI+ is my New Religion!
qWord, thank you very much!
Amen, Brother!...!
:cheekygreen: