Code : Tout sélectionner
;Original code by Papala
;Modifications by Demivec to correct bug of unfreed temp images. Also did some code formatting for improved readability.
DeclareModule patch
Enumeration 1
#Patch_Copy ;Repeat the sprite to the size
#Patch_Stretch ;Stretch the sprite to the size
EndEnumeration
Declare Image(Image, OutputWidth, OutputHeight, Corner, Flag = #Patch_Stretch) ;The imageID to 9Patch, Width & Height to reach, Corner width/height of the 9patch, Flag can be #9Patch_Copy or #9Patch_Stretch
Declare Sprite(Image, OutputWidth, OutputHeight, Corner, Flag = #Patch_Stretch)
EndDeclareModule
Module patch
EnableExplicit
Structure Patch
Sprite.i
OutputWidth.i
OutputHeight.i
Corner.i
Corner2x.i
Horizontal.i
Vertical.i
EndStructure
Enumeration
#OutputType_Image ;create a new image for output
#OutputType_Sprite ;create a new sprite for output
EndEnumeration
Procedure DrawCorner(SourceImage, *data.patch)
Protected TempImage
;Draw the 4 corners of the original image with no modification
;Top left
TempImage = GrabImage(SourceImage, #PB_Any, 0, 0, *data\Corner, *data\Corner)
DrawImage(ImageID(TempImage), 0, 0):
FreeImage(TempImage)
;Top right
TempImage = GrabImage(SourceImage, #PB_Any, ImageWidth(SourceImage) - *data\Corner, 0, *data\Corner, *data\Corner)
DrawImage(ImageID(TempImage), *data\OutputWidth - *data\Corner, 0)
FreeImage(TempImage)
;Bottom left
TempImage = GrabImage(SourceImage, #PB_Any, 0, ImageHeight(SourceImage) - *data\Corner, *data\Corner, *data\Corner)
DrawImage(ImageID(TempImage), 0, *data\OutputHeight - *data\Corner)
FreeImage(TempImage)
;Bottom right
TempImage = GrabImage(SourceImage, #PB_Any, ImageWidth(SourceImage) - *data\Corner, ImageHeight(SourceImage) - *data\Corner, *data\Corner, *data\Corner)
DrawImage(ImageID(TempImage), *data\OutputWidth - *data\Corner, *data\OutputHeight - *data\Corner)
FreeImage(TempImage)
EndProcedure
Procedure Create(SourceImage, *data.patch, flag, Type)
Protected HLoop, VLoop, TempImage, Width, Height, Hresult, VResult
*data\Horizontal = ImageWidth(SourceImage)
*data\Vertical = ImageHeight(SourceImage)
Select Type
Case #OutputType_Sprite: StartDrawing(SpriteOutput(*data\Sprite))
Case #OutputType_Image: StartDrawing(ImageOutput(*data\Sprite))
EndSelect
DrawCorner(SourceImage, *data)
Protected Width_NoCorners = *data\OutputWidth - *data\Corner2x,
Height_NoCorners = *data\OutputHeight - *data\Corner2x
Select flag
Case #Patch_Copy ;Repeat the original image's pattern to the new Width and Height
Width = *data\Horizontal - *data\Corner2x
Height = *data\Vertical - *data\Corner2x
Protected HLoop_max = (Width_NoCorners) / Width,
VLoop_max = (Height_NoCorners) / Height
For HLoop = 0 To HLoop_max
For VLoop = 0 To VLoop_max
Select VLoop
Case 0 ;================================Top horizontal========================
If HLoop <> HLoop_max
TempImage = GrabImage(SourceImage, #PB_Any, *data\Corner, 0, Width, *data\Corner)
Else
TempImage = GrabImage(SourceImage, #PB_Any, *data\Corner, 0, Width_NoCorners - Width * HLoop, *data\Corner)
EndIf
If TempImage
DrawImage(ImageID(TempImage), *data\Corner + Width * HLoop, 0)
FreeImage(TempImage)
EndIf
Case VLoop_max ;=======================Bottom horizontal=========================
Debug "???"
If HLoop <> HLoop_max
TempImage = GrabImage(SourceImage, #PB_Any, *data\Corner, ImageHeight(SourceImage) - *data\Corner, Width, *data\Corner)
Else
TempImage = GrabImage(SourceImage, #PB_Any, *data\Corner, ImageHeight(SourceImage) - *data\Corner, Width_NoCorners - Width * HLoop, *data\Corner)
EndIf
If TempImage
DrawImage(ImageID(TempImage), *data\Corner + Width * HLoop, *data\OutputHeight - *data\Corner)
FreeImage(TempImage)
EndIf
EndSelect
Select HLoop
Case 0 ;===================================Left vertical=================================
If VLoop <> VLoop_max
TempImage = GrabImage(SourceImage, #PB_Any, 0, *data\Corner, *data\Corner, Height)
Else
TempImage = GrabImage(SourceImage, #PB_Any, 0, *data\Corner, *data\Corner, Height_NoCorners - Height * VLoop)
EndIf
If TempImage
DrawImage(ImageID(TempImage), 0, *data\Corner + Height * VLoop)
FreeImage(TempImage)
EndIf
Case HLoop_max ;===============================right vertical=============================
If VLoop <> VLoop_max
TempImage = GrabImage(SourceImage, #PB_Any, ImageWidth(SourceImage) - *data\Corner, *data\Corner, *data\Corner, Height)
Else
TempImage = GrabImage(SourceImage, #PB_Any, ImageWidth(SourceImage) - *data\Corner, *data\Corner, *data\Corner, Height_NoCorners - Height * VLoop)
EndIf
If TempImage
DrawImage(ImageID(TempImage), *data\OutputWidth - *data\Corner, *data\Corner + Height * VLoop)
FreeImage(TempImage)
EndIf
EndSelect
;Repeat middle's patern to fill the new image with
If HLoop <> HLoop_max
Hresult = Width
Else
Hresult = Width_NoCorners - Width * HLoop
EndIf
If VLoop <> VLoop_max
VResult = Height
Else
VResult = Height_NoCorners - Height * VLoop
EndIf
TempImage = GrabImage(SourceImage, #PB_Any, *data\Corner, *data\Corner, Hresult, VResult)
If TempImage
DrawImage(ImageID(TempImage), *data\Corner + Width * HLoop, *data\Corner + Height * VLoop)
FreeImage(TempImage)
EndIf
Next VLoop
Next HLoop
Case #Patch_Stretch ;Stretch the original image to the new Width and Height
;Top horizontal
TempImage = GrabImage(SourceImage, #PB_Any, *data\Corner, 0, ImageWidth(SourceImage) - *data\Corner2x, *data\Corner)
DrawImage(ImageID(TempImage), *data\Corner, 0, Width_NoCorners, *data\Corner)
FreeImage(TempImage)
;Bottom horizontal
TempImage = GrabImage(SourceImage, #PB_Any, *data\Corner, ImageHeight(SourceImage) - *data\Corner, ImageWidth(SourceImage) - *data\Corner2x, *data\Corner)
DrawImage(ImageID(TempImage), *data\Corner, *data\OutputHeight - *data\Corner, Width_NoCorners, *data\Corner)
FreeImage(TempImage)
;Left vertical
TempImage = GrabImage(SourceImage, #PB_Any, 0, *data\Corner, *data\Corner, ImageHeight(SourceImage) - *data\Corner2x)
DrawImage(ImageID(TempImage), 0, *data\Corner, *data\Corner, Height_NoCorners)
FreeImage(TempImage)
;Right vertial
TempImage = GrabImage(SourceImage, #PB_Any, ImageWidth(SourceImage) - *data\Corner, *data\Corner, *data\Corner, ImageHeight(SourceImage) - *data\Corner2x)
DrawImage(ImageID(TempImage), *data\OutputWidth - *data\Corner, *data\Corner, *data\Corner, Height_NoCorners)
FreeImage(TempImage)
;Middle
TempImage = GrabImage(SourceImage, #PB_Any, *data\Corner, *data\Corner, ImageWidth(SourceImage) - *data\Corner2x, ImageHeight(SourceImage) - *data\Corner2x)
DrawImage(ImageID(TempImage), *data\Corner, *data\Corner, Width_NoCorners, Height_NoCorners)
FreeImage(TempImage)
EndSelect
StopDrawing()
EndProcedure
Procedure Image(SourceImage, OutputWidth, OutputHeight, Corner, Flag = #Patch_Stretch)
Protected Patch.patch
Patch\OutputWidth = OutputWidth: Patch\OutputHeight = OutputHeight: Patch\Corner = Corner: Patch\Corner2x = Corner * 2
Patch\Sprite = CreateImage(#PB_Any, OutputWidth, OutputHeight)
If Patch\Sprite
Create(SourceImage, @Patch, Flag, #OutputType_Image)
ProcedureReturn Patch\Sprite
Else
ProcedureReturn #False
EndIf
EndProcedure
Procedure Sprite(SourceImage, OutputWidth, OutputHeight, Corner, Flag = #Patch_Stretch)
Protected Patch.patch
Patch\OutputWidth = OutputWidth: Patch\OutputHeight = OutputHeight: Patch\Corner = Corner: Patch\Corner2x = Corner * 2
Patch\Sprite = CreateSprite(#PB_Any, OutputWidth, OutputHeight, #PB_Sprite_AlphaBlending)
If Patch\Sprite
Create(SourceImage, @Patch, Flag, #OutputType_Sprite)
ProcedureReturn Patch\Sprite
Else
ProcedureReturn #False
EndIf
EndProcedure
EndModule
CompilerIf #PB_Compiler_IsMainFile
InitSprite()
Define Image1, Image2, Sprite1, Sprite2
Image1 = CreateImage(#PB_Any, 20, 20)
StartDrawing(ImageOutput(Image1))
DrawingMode(#PB_2DDrawing_Outlined)
Box(0, 0, 19, 19, $FF0000)
Circle(9, 9, 5, $FFFF00)
Line(4, 1, 6, 1, $00FF00)
Line(10, 1, 6, 1, $0000FF)
StopDrawing()
OpenWindow(0, 0, 0, 100, 200, "9 Patch Sample", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(0), 0, 0, 100, 200)
Image2 = patch::Image(Image1, 60, 60, 4, patch::#Patch_Copy)
Sprite1 = patch::Sprite(Image1, 40, 40, 4)
Sprite2 = patch::Sprite(Image1, 80, 30, 4, patch::#Patch_Copy)
StartDrawing(ScreenOutput())
DrawImage(ImageID(Image1), 10, 0) ;Original image
DrawImage(ImageID(Image2), 10, 30)
StopDrawing()
DisplaySprite(Sprite1, 10, 100)
DisplaySprite(Sprite2, 10, 150)
FlipBuffers()
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
CompilerEndIf
Edit : Comme me l'a fait remarqué Demivec sur le forum anglais, j'oubliai de libérer les images temporaires que je créais, ce qui à long thermes pourrais être pas mal problèmatique.
@Falsam : Lui aussi trouvais que le code manquait un peut d'air, j'spère que cet édit te plairas !