The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: caraveiro on November 18, 2011, 10:59:45 PM

Title: Glass and blend efect
Post by: caraveiro on November 18, 2011, 10:59:45 PM
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
Title: Re: Glass and blend efect
Post by: qWord on November 19, 2011, 01:53:53 AM
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)
Title: Re: Glass and blend efect
Post by: caraveiro on November 19, 2011, 02:47:19 AM
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!
Title: Re: Glass and blend efect
Post by: qWord on November 19, 2011, 03:02:11 AM
The flow for a 'normal' window application:

...
Invoke GdiplusStartup,addr dToken,addr GdipSI,0
...
<window creation>
...
<message loop>
...
invoke GdiplusShutdown,dToken
invoke ExitProcess,0
Title: Re: Glass and blend efect
Post by: Farabi on November 19, 2011, 04:26:38 AM
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)
Title: Re: Glass and blend efect
Post by: 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.
Title: Re: Glass and blend efect
Post by: 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.
Title: Re: Glass and blend efect
Post by: 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+.
Title: Re: Glass and blend efect
Post by: 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/).

Title: Re: Glass and blend efect
Post by: daydreamer on November 23, 2011, 09:02:03 PM
here is an example how you can blend with right textures
Title: Re: Glass and blend efect
Post by: Farabi on November 24, 2011, 10:59:37 AM
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?
Title: Re: Glass and blend efect
Post by: Farabi on November 24, 2011, 11:28:26 AM
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
Title: Re: Glass and blend efect
Post by: Farabi on November 24, 2011, 11:33:44 AM
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.
Title: Re: Glass and blend efect
Post by: qWord on November 24, 2011, 02:28:17 PM
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+.
Title: Re: Glass and blend efect
Post by: caraveiro on November 29, 2011, 07:21:13 PM
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: