A demo of working with sprites

Published on by Yousfi Benameur


In short: Icon Sprites are a means of combining multiple images into a single image file for use for ex. on a website, to help with performance.
Sprite may seem like a bit of a misnomer considering that you're create a large image as opposed to working with many small ones (as a film pellicule).
To summarize: the term "sprites" comes from a technique in computer graphics, most often used in video games. The idea was that the computer could fetch a graphic into memory, and then only display parts of that image at a time, which was faster than having to continually fetch new images. The sprite was the big combined graphic.
(CSS) Sprites is pretty much the exact same theory: get the image once, and shift it around and only display parts of it. This reduces the overhead of having to fetch multiple images.
VFP can might use this technic as well also as demonstrated below !
of course this needs to the gdiplusX library otherwise vfp cannot extract such icons a large image(maybe with APIs but that needs big effort).
using gdiplusX and the function fromScreen can capture any portion of the form(handle hwnd).this library can extract the icons from the sprite or as reverse combine icons to a sprite easily.I used it strongly in captures (see previous posts).can use these capture technics to get any zone of a sprite as image.

its also a method to protect resources.
note: the surroundered red rectangles are for the operation progress and to see the exact area to capture with each icon.


Click on code to select [then copy] -click outside to deselect


*1*
*A test of working with a large set of icons as sprite (one image with all icons needed by any application)
*system.app must lives preferably in source folder.
*the first icon is relative positionned to x=0,y=0 and all icons have same width & height.

publi yform
yform=newObject("sprite")
yform.show
read events
retu
*
DEFINE CLASS sprite AS form
BorderStyle = 0
Height = 450
Width = 921
ShowWindow = 2
AutoCenter = .T.
Caption = "Form1"
TitleBar = 1
BackColor = RGB(0,0,0)
Name = "Form1"

ADD OBJECT image1 AS image WITH ;
Picture = "ysprite_icons1.png", ;
Height = 37, ;
Left = 0, ;
Top = 0, ;
Width = 630, ;
Name = "Image1"

ADD OBJECT command1 AS commandbutton WITH ;
Top = 8, ;
Left = 648, ;
Height = 27, ;
Width = 84, ;
FontBold = .T., ;
Caption = "Extract pngs", ;
MousePointer = 15, ;
SpecialEffect = 2, ;
BackColor = RGB(128,255,0), ;
Name = "Command1"

ADD OBJECT image2 AS image WITH ;
Picture = "sprite_icons.png", ;
Height = 310, ;
Left = 0, ;
Top = 96, ;
Width = 630, ;
Name = "Image2"

ADD OBJECT command2 AS commandbutton WITH ;
Top = 214, ;
Left = 648, ;
Height = 27, ;
Width = 84, ;
FontBold = .T., ;
Caption = "Extract PNGs", ;
MousePointer = 15, ;
SpecialEffect = 2, ;
BackColor = RGB(128,255,0), ;
Name = "Command2"

ADD OBJECT command3 AS commandbutton WITH ;
AutoSize = .T., ;
Top = 148, ;
Left = 828, ;
Height = 44, ;
Width = 47, ;
FontBold = .T., ;
FontSize = 16, ;
Caption = "?", ;
MousePointer = 15, ;
Style = 0, ;
SpecialEffect = 2, ;
ForeColor = RGB(0,255,0), ;
BackColor = RGB(255,128,64), ;
Name = "Command3"


ADD OBJECT label0 AS label WITH ;
AutoSize = .T., ;
FontBold = .T., ;
FontSize = 20, ;
BackStyle = 0, ;
Caption = "-", ;
Height = 35, ;
Left = 890-20, ;
MousePointer = 15, ;
Top = -2, ;
Width = 20, ;
ForeColor = RGB(255,0,0), ;
Name = "Label0"

ADD OBJECT label1 AS label WITH ;
AutoSize = .T., ;
FontBold = .T., ;
FontSize = 20, ;
BackStyle = 0, ;
Caption = "X", ;
Height = 35, ;
Left = 890, ;
MousePointer = 15, ;
Top = 2, ;
Width = 20, ;
ForeColor = RGB(255,0,0), ;
Name = "Label1"

ADD OBJECT label2 AS label with ;
AutoSize = .T.,;
FontName = "Segoe Script",;
FontSize = 32,;
WordWrap = .T.,;
BackStyle = 0,;
Caption = "Sprite Icons",;
Height = 138,;
Left = 768,;
Top = 245,;
Width = 140,;
ForeColor = RGB(0,255,0),;
Name = "Label2"


ADD OBJECT image3 AS image WITH ;
Picture = home(1)+"graphics\icons\win95\explorer.ico", ;
Height = 32, ;
Left = 840, ;
MousePointer = 15, ;
Top = 205, ;
Width = 32, ;
Name = "Image3"

PROCEDURE Destroy
m.yrep=null
release m.yrep
clea events
ENDPROC

PROCEDURE Load
do locfile('system.app')
declare integer Sleep in kernel32 integer  &&finally not used
_screen.windowstate=1
ENDPROC

PROCEDURE KeyPress
LPARAMETERS nKeyCode, nShiftAltCtrl
if nkeycode=27
thisform.release
endi
ENDPROC

PROCEDURE MouseDown
LPARAMETERS nButton, nShift, nXCoord, nYCoord
*DECLARE INTEGER GetFocus IN WIN32API
lnHandle = THISFORM.HWND    &&getFocus() for (<=)vfp6
param1 = 274
param2 = 0xF012
DECLARE INTEGER ReleaseCapture IN WIN32API
DECLARE INTEGER SendMessage IN WIN32API INTEGER, INTEGER, INTEGER, INTEGER
bb=ReleaseCapture()
bb=SendMessage(lnHandle, param1, param2,0)
ENDPROC

PROCEDURE Init
publi m.yrep
m.yrep=addbs(justpath(sys(16,1)))
set defa to (yrep)
thisform.titlebar=0
ENDPROC

PROCEDURE command1.Click
if ! directory(m.yrep+"images")
md (m.yrep+"images")
endi
thisform.forecolor=255
local x,y,w,h
with thisform.image1
x0=.left
y=.top
w=.width
h=.height
endwith

w0=30
h0=h

Local loCaptureBmp As xfcBitmap
With _Screen.System.Drawing
Local loCapture As xfcBitmap
*LPARAMETERS tHWnd, tiX, tiY, tiWidth, tiHeight, [tlEnsureVisible]
i=1
for x=x0 to w-w0 step w0
loCapture = .Bitmap.Fromscreen(thisform.hwnd,x,y,w0,h0) &&capture zone desktop (hwnd=0)
loCapture.makeTransparent(.color.black)  && black color to make transparent
thisform.box(x,y,x+w0,y+h0)
*Sleep(100)
Local m.lcdest
m.lcdest=m.yrep+"images\"+trans(i)+".png"
*!*		Do Case
*!*		   Case Upper(Thisform.ext)=="PNG"
loCapture.Save(m.lcdest,.imaging.imageformat.PNG)
*!*		   Case Upper(Thisform.ext)=="JPG"
*!*			  loCapture.Save(m.lcdest,.imaging.imageformat.JPEG)
*!*		   Case Upper(Thisform.ext)=="BMP"
*!*			  loCapture.Save(m.lcdest,.imaging.imageformat.BMP)
*!*		   Case Upper(Thisform.ext)=="GIF"
*!*			  loCapture.Save(m.lcdest,.imaging.imageformat.GIF)
*!*		Endcase
i=i+1
endfor
endwith

local m.oo
m.oo=m.yrep+"images"
run/n explorer &oo
ENDPROC

PROCEDURE command2.Click
if ! directory(m.yrep+"images")
md (m.yrep+"images")
endi

local x,y,w,h
with thisform.image2
x0=.left
y=.top
w=.width
h=.height
endwith

w0=30
h0=31
thisform.forecolor=255
Local loCaptureBmp As xfcBitmap
With _Screen.System.Drawing
Local loCapture As xfcBitmap
*LPARAMETERS tHWnd, tiX, tiY, tiWidth, tiHeight, [tlEnsureVisible]
i=1
for j=1 to 10
for x=x0 to w-w0 step w0
loCapture = .Bitmap.Fromscreen(thisform.hwnd,x,y,w0,h0) &&capture zone desktop (hwnd=0)
loCapture.makeTransparent(.color.black)
thisform.box(x,y,x+w0,y+h0)
*Sleep(100)
Local m.lcdest
m.lcdest=m.yrep+"images\"+trans(i)+".png"
*!*		Do Case  &&can us ethe appropriated image format below
*!*		   Case Upper(Thisform.ext)=="PNG"
loCapture.Save(m.lcdest,.imaging.imageformat.PNG)
*!*		   Case Upper(Thisform.ext)=="JPG"
*!*			  loCapture.Save(m.lcdest,.imaging.imageformat.JPEG)
*!*		   Case Upper(Thisform.ext)=="BMP"
*!*			  loCapture.Save(m.lcdest,.imaging.imageformat.BMP)
*!*		   Case Upper(Thisform.ext)=="GIF"
*!*			  loCapture.Save(m.lcdest,.imaging.imageformat.GIF)
*!*		Endcase
i=i+1
endfor

y=y+31
endfor
endwith

local m.oo
m.oo=m.yrep+"images"
run/n explorer &oo
ENDPROC


PROCEDURE command3.Click
local m.myvar
text to m.myvar noshow
In short: Icon Sprites are a means of combining multiple images into a single image file for use for ex. on a website, to help with performance.
Sprite may seem like a bit of a misnomer considering that you're create a large image as opposed to working with many small ones.
To summarize: the term "sprites" comes from a technique in computer graphics, most often used in video games. The idea was that the computer could fetch a graphic into memory, and then only display parts of that image at a time, which was faster than having to continually fetch new images. The sprite was the big combined graphic.
(CSS) Sprites is pretty much the exact same theory: get the image once, and shift it around and only display parts of it. This reduces the overhead of having to fetch multiple images.
VFP can might use this technic as well also as demonstarted below !
using gdiplusX and the function fromScreen can capture any portion of the form(handle hwnd).this library can extract the
icons from the sprite or as reverse combine icons to a sprite easily.
its also a method to protect resources.
note: the surroundered red rectangles are for the operation progress and to see the exact area to capture with each icon.
endtext

#define MB_ICONINFORMATION 0x00000040
#define MB_OK 0x00000000
#define MB_APPLMODAL 0x00000000
#define  MB_DEFBUTTON1 0x00000000



DECLARE INTEGER MessageBox IN user32 As MessageBoxA;
INTEGER hwnd,;
STRING  lpText,;
STRING  lpCaption,;
INTEGER wType

*buttons
#define MB_ABORTRETRYIGNORE 0x00000002
#define MB_CANCELTRYCONTINUE 0x00000006
#define MB_HELP 0x00004000

#define MB_OKCANCEL 0x00000001
#define MB_RETRYCANCEL 0x00000005
#define MB_YESNO  0x00000004
#define MB_YESNOCANCEL 0x00000003

*Icons
#define  MB_ICONEXCLAMATION 0x00000030
#define MB_ICONWARNING 0x00000030

#define MB_ICONASTERISK 0x00000040
#define MB_ICONQUESTION 0x00000020
#define MB_ICONSTOP 0x00000010
#define MB_ICONERROR 0x00000010
#define MB_ICONHAND  0x00000010

*To indicate the default button, specify one of the following values.

#define MB_DEFBUTTON2 0x00000100
#define MB_DEFBUTTON3 0x00000200
#define MB_DEFBUTTON4 0x00000300

*To indicate the modality of the dialog box, specify one of the following values.

#define MB_SYSTEMMODAL 0x00001000
#define MB_TASKMODAL 0x00002000

*To specify other options, use one or more of the following values.
#define MB_DEFAULT_DESKTOP_ONLY 0x00020000
#define MB_RIGHT 0x00080000
#define MB_RTLREADING  0x00100000
#define MB_SETFOREGROUND  0x00010000
#define MB_TOPMOST  0x00040000
#define MB_SERVICE_NOTIFICATION 0x00200000

*Return code
#define IDABORT 3
#define IDCANCEL 2
#define IDCONTINUE 11
#define IDIGNORE 5
#define IDNO 7
#define IDOK 1
#define IDRETRY 4
#define IDTRYAGAIN 10
#define IDYES 6

MessageBoxA(_vfp.hwnd,m.myvar,"Working with sprites",MB_APPLMODAL+MB_OK +MB_ICONINFORMATION +MB_DEFBUTTON1 )	
*messagebox(m.myvar,0+32)
ENDPROC

PROCEDURE label0.Click
thisform.windowstate=1
ENDPROC

PROCEDURE label1.Click
thisform.release
ENDPROC

PROCEDURE image3.Click
local m.oo
m.oo=m.yrep+"images"
run/n explorer &oo
ENDPROC

ENDDEFINE
*
*-- EndDefine: sprite


A demo of working with sprites
A demo of working with sprites

Click on code to select [then copy] -click outside to deselect


*2*
*this code shows how to build programmatly a sprite from a big resource as shell32.dll
*this code dont use any physical image extracted but uses the pictureVAl image property to display icons directly on form
*PictureVal Specifies a character string expression or object that represents an image.
*If eExpression is a string expression, it must be a valid expression that GDI+ can use to render an image.
*the form is scrollable
*snippi,gtool is fired to capture the sprite area as png for ex.
*try this code on this usefull test: c:\windows\system32\shell32.dll

Clea Resources
Clea All
Publi m.yrep
m.yrep=Addbs(Justpath(Sys(16,1)))
Set Defa To (yrep)
Do Locfile('system.app','app',"where is system.app of gdiplusX project ? ")

Publi yform
yform=Newobject("ysprite")
yform.Show
Read Events
Retu
*
Define Class ysprite As Form
Top = 15
Left = 88
Height = 561
Width = 843
ShowWindow = 2
ScrollBars = 2
ShowTips = .T.
backcolor=rgb(254,254,254)
Caption = "icons extract"
Name = "Form1"

Procedure yextract

Local  i,lnindex
Local loicon As xfcicon
Local lobmp As xfcbitmap

i = 0
With _Screen.System.drawing
Do While .T.
loicon = .Icon.extractassociatedicon(Thisform.filename, i)
If Isnull(loicon)
Exit
Endif
lobmp = loicon.tobitmap()
Try
oo=Eval("thisform.img"+Trans(i))
oo.PictureVal = lobmp.getpictureval (.imaging.imageformat.png)   &&m.ytype
oo.ToolTipText=Trans(i)
Catch
Endtry
Wait Window "E x t r a c t i n g   i c o n s  ......"+trans(i) At  Srows()/2,Scols()/2-20 Nowait
i = i + 1
Enddo
Endwith
lnindex=i
Wait Clea
Wait Clea
Thisform.Caption=Trans(lnindex+1)+"  icons  extracted from "+Allt(Thisform.filename)

With  Thisform
For i=lnindex To .ControlCount
Try
.RemoveObject(.Controls(i).Name)
Catch
Endtry
Endfor
Endwith
_screen.windowstate=1
run/n snippingtool
Endproc

Procedure Init
Thisform.AddProperty("filename","")
Local  lnindex
Local loicon As xfcicon
Local lobmp As xfcbitmap
With Thisform
.filename =addbs(getenv('windir'))+"system32\shell32.dll"    &&Getfile("exe;ico;dll","") && _vfp.servername
If Empty(.filename)
Return .F.
Endi
Endwith

i = 0  && icon index
With _Screen.System.drawing
Do While .T.
loicon = .Icon.extractassociatedicon(Thisform.filename, i)
If Isnull(loicon)
Exit
Endif

i = i + 1
Enddo
Endwith
lnindex=i
Local delta
m.delta=7

With Thisform
j=0
For i=1 To lnindex
.AddObject("img"+Trans(i),"image")
m.oo=Eval(".img"+Trans(i))
With m.oo
If j=0
.Left=10
.Top=10
Else
.Left=Eval(".parent.img"+Trans(i-1)+".left")+Eval(".parent.img"+Trans(i-1)+".width")+m.delta
.Top =Eval(".parent.img"+Trans(i-1)+".top")
Endi

.Width=25
.Height=25
.Stretch=2
.ToolTipText=.PictureVal
.Name="img"+Trans(i)
.Visible=.T.
j=j+1
If j>20  &&20 images per row
.Left=10
.Top=Eval('.parent.img'+Trans(i-1)+".top")+Eval(".parent.img"+Trans(i-1)+".height")+m.delta
j=1
Endi
*bindevent(m.oo,"rightclick",thisform,"my")  &&can add a procedure my to save image as.....here .
Endwith
Endfor
Endwith
Thisform.yextract()
Endproc

Procedure destroy
m.yrep=null
release m.yrep
clea events
endproc

Enddefine
*
*-- EndDefine: ysprite


A demo of working with spritesA demo of working with sprites
A demo of working with sprites

*Important:All Codes above are tested on VFP9SP2 & windows 10 pro.

To be informed of the latest articles, subscribe:
Comment on this post