PureBasic Forum
http://forums.purebasic.com/english/

9 Patch
http://forums.purebasic.com/english/viewtopic.php?f=12&t=71266
Page 1 of 1

Author:  Papala [ Tue Aug 21, 2018 5:21 pm ]
Post subject:  9 Patch

I needed one (pretty basic but enouth for what i need) so if it can be usefull fore someone...
Code:
DeclareModule patch
  #Patch_Copy = 1 ;Repeat the sprite to the size
  #Patch_Stretch = 2 ;Stretch the sprite to the size
  Declare Image(Image,Width,Height,Corner,Flag = #Patch_Stretch) ;The imageID to 9Patch, Width & Height to reach, Corner width/heigh of the 9patch, Flag can be #9Patch_Copy or #9Patch_Stretch
  Declare Sprite(Image,Width,Height,Corner,Flag = #Patch_Stretch)
EndDeclareModule

Module patch
  EnableExplicit 
  Structure Patch
    Sprite.i
    Width.i
    Height.i
    Corner.i
    Horizontal.i
    Vertical.i
  EndStructure
  Declare Create(Image,*data.patch,flag,Type)
  Declare DrawCorner(Image,*data.patch)
 
  Procedure Image(Image,Width,Height,Corner,Flag = #Patch_Stretch)
    Protected Patch.patch
    Patch\Width = Width : Patch\Height = Height : Patch\Corner = Corner
    Patch\Sprite = CreateImage(#PB_Any,Width,Height)
    If Patch\Sprite
      Create(Image,@Patch,Flag,0)
      ProcedureReturn Patch\Sprite
    Else
      ProcedureReturn #False
    EndIf
  EndProcedure
 
  Procedure Sprite(Image,Width,Height,Corner,Flag = #Patch_Stretch)
    Protected Patch.patch
    Patch\Width = Width : Patch\Height = Height : Patch\Corner = Corner
    Patch\Sprite = CreateSprite(#PB_Any,Width,Height,#PB_Sprite_AlphaBlending)
    If Patch\Sprite
      Create(Image,@Patch,Flag,1)
      ProcedureReturn Patch\Sprite
    Else
      ProcedureReturn #False
    EndIf
  EndProcedure

  Procedure Create(Image,*data.patch,flag,Type)
    Protected HLoop=1, VLoop=1, TempImage, Width, Heigt, Hresult, VResult
    *data\Horizontal = ImageWidth(Image)
    *data\Vertical = ImageHeight(Image)
    If Type
      StartDrawing(SpriteOutput(*data\Sprite))
    Else
      StartDrawing(ImageOutput(*data\Sprite))
    EndIf
    DrawCorner(Image,*data)
    Select flag
      Case #Patch_Copy ;Repeat the original image's patern to the new Width and Height
        width = ImageWidth(Image)-*data\Corner*2
        Heigt = ImageHeight(Image)-*data\Corner*2
        For HLoop = 0 To  (*data\Width - *data\Corner*2) / Width
          For VLoop = 0 To (*data\Height - *data\Corner*2) / Heigt
            Select VLoop
              Case 0 ;================================Top horizontal========================
                If HLoop - (*data\Width - *data\Corner*2) / Width
                  TempImage = GrabImage(Image,#PB_Any,*data\Corner,0,Width,*data\Corner)
                Else
                  TempImage = GrabImage(Image,#PB_Any,*data\Corner,0,*data\Width -*data\Corner*2 - Width * HLoop,*data\Corner)
                EndIf
                If TempImage
                  DrawImage(ImageID(TempImage),*data\Corner+Width*HLoop,0)
                EndIf
              Case (*data\Height - *data\Corner*2) / Width ;=======================Bottom horizontal=========================
                If HLoop - (*data\Width - *data\Corner*2) / Width
                  TempImage = GrabImage(Image,#PB_Any,*data\Corner,ImageHeight(Image)-*data\Corner,Width,*data\Corner)
                Else
                  TempImage = GrabImage(Image,#PB_Any,*data\Corner,ImageHeight(Image)-*data\Corner,*data\Width -*data\Corner*2 - Width * HLoop,*data\Corner)
                EndIf
                If TempImage
                  DrawImage(ImageID(TempImage),*data\Corner+Width*HLoop,*data\Height-*data\Corner)     
                EndIf
            EndSelect
            Select HLoop
              Case 0 ;===================================Left vertical=================================
                If VLoop - (*data\Height - *data\Corner*2) / Heigt
                  TempImage = GrabImage(Image,#PB_Any,0,*data\Corner,*data\Corner,Heigt)
                Else
                  TempImage = GrabImage(Image,#PB_Any,0,*data\Corner,*data\Corner,*data\Height -*data\Corner*2 - Heigt * VLoop)
                EndIf
                If TempImage
                  DrawImage(ImageID(TempImage),0,*data\Corner+Heigt*VLoop) 
                EndIf
              Case (*data\Width - *data\Corner*2) / Width ;===============================right vertical=============================
                If VLoop - (*data\Height - *data\Corner*2) / Heigt
                  TempImage = GrabImage(Image,#PB_Any,ImageWidth(Image)-*data\Corner,*data\Corner,*data\Corner,Heigt)
                Else
                  TempImage = GrabImage(Image,#PB_Any,ImageWidth(Image)-*data\Corner,*data\Corner,*data\Corner,*data\Height -*data\Corner*2 - Heigt * VLoop)
                EndIf
                If TempImage
                  DrawImage(ImageID(TempImage),*data\Width-*data\Corner,*data\Corner+Heigt*VLoop)   
                EndIf
            EndSelect
            ;Repeat middle's patern to fill the new image with
            If HLoop - (*data\Width - *data\Corner*2) / Width
              Hresult = Width
            Else
              Hresult = *data\Width -*data\Corner*2 - Width * HLoop
            EndIf
            If VLoop - (*data\Height - *data\Corner*2) / Heigt
              VResult = Heigt
            Else
              VResult = *data\Height -*data\Corner*2 - Heigt * VLoop
            EndIf
            TempImage = GrabImage(Image,#PB_Any,*data\Corner,*data\Corner,Hresult,VResult)
            If TempImage
              DrawImage(ImageID(TempImage),*data\Corner+Width*HLoop,*data\Corner+Heigt*VLoop)
            EndIf
          Next VLoop
        Next HLoop
       
      Case #Patch_Stretch ;Stretch the original image to the new Width and Height
        TempImage = GrabImage(Image,#PB_Any,*data\Corner,0,ImageWidth(Image)-*data\Corner*2,*data\Corner) ;Top horizontal
        DrawImage(ImageID(TempImage),*data\Corner,0,*data\Width-*data\Corner*2,*data\Corner)
        TempImage = GrabImage(Image,#PB_Any,*data\Corner,ImageHeight(Image)-*data\Corner,ImageWidth(Image)-*data\Corner*2,*data\Corner) ;Bottom horizontal
        DrawImage(ImageID(TempImage),*data\Corner,*data\Height-*data\Corner,*data\Width-*data\Corner*2,*data\Corner)
        TempImage = GrabImage(Image,#PB_Any,0,*data\Corner,*data\Corner,ImageHeight(Image)-*data\Corner*2) ;Left vertical
        DrawImage(ImageID(TempImage),0,*data\Corner,*data\Corner,*data\Height-*data\Corner*2)
        TempImage = GrabImage(Image,#PB_Any,ImageWidth(Image)-*data\Corner,*data\Corner,*data\Corner,ImageHeight(Image)-*data\Corner*2) ;Right vertial
        DrawImage(ImageID(TempImage),*data\Width-*data\Corner,*data\Corner,*data\Corner,*data\Height-*data\Corner*2)
        TempImage = GrabImage(Image,#PB_Any,*data\Corner,*data\Corner,ImageWidth(Image)-*data\Corner*2,ImageHeight(Image)-*data\Corner*2) ;Middle
        DrawImage(ImageID(TempImage),*data\Corner,*data\Corner,*data\Width-*data\Corner*2,*data\Height-*data\Corner*2)
    EndSelect
    StopDrawing()
  EndProcedure
 
  Procedure DrawCorner(Image,*data.patch)
    Protected TempImage
    ;Draw the 4 corners of the original image with no modification
    TempImage = GrabImage(Image,#PB_Any,0,0,*data\Corner,*data\Corner) ;Top left
    DrawImage(ImageID(TempImage),0,0)
    TempImage = GrabImage(Image,#PB_Any,ImageWidth(Image)-*data\Corner,0,*data\Corner,*data\Corner) ;Top right
    DrawImage(ImageID(TempImage),*data\Width-*data\Corner,0)
    TempImage = GrabImage(Image,#PB_Any,0,ImageHeight(Image)-*data\Corner,*data\Corner,*data\Corner) ;Bottom left
    DrawImage(ImageID(TempImage),0,*data\Height-*data\Corner)
    TempImage = GrabImage(Image,#PB_Any,ImageWidth(Image)-*data\Corner,ImageHeight(Image)-*data\Corner,*data\Corner,*data\Corner) ;Bottom right
    DrawImage(ImageID(TempImage),*data\Width-*data\Corner,*data\Height-*data\Corner)
  EndProcedure
 
EndModule
  CompilerIf #PB_Compiler_IsMainFile
    InitSprite()
    Global 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

Author:  Demivec [ Wed Aug 22, 2018 1:41 am ]
Post subject:  Re: 9 Patch

Thanks for the code. I noticed a bug that will cause many problems if left uncorrected. Temporary images are not freed. With your sample code that displays 4 images, 90 temporary images are left unfreed.

I made corrections to the code to remove this bug and in the process did some simple formatting changes and some slight enhancements that were mostly for readability.

Here is the new code:

Code:
;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 HLoop_max ;=======================Bottom horizontal=========================
                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 VLoop_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

Author:  Papala [ Wed Aug 22, 2018 7:29 am ]
Post subject:  Re: 9 Patch

Demivec wrote:
Temporary images are not freed. With your sample code that displays 4 images, 90 temporary images are left unfreed.

Wow how can i forgot about that.. Thx a lot for this fix Demivec ! Thank for the enhancements too :wink:

My turn to fix a bug in your code :
Code:
;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


(Bug fix :"Select VLoop : Case 0 : Case HLoopMax" ===> "Select VLoop : Case 0 : Case VLoopMax")

Author:  Demivec [ Thu Aug 23, 2018 4:15 am ]
Post subject:  Re: 9 Patch

Papala wrote:
My turn to fix a bug in your code


Thanks for catching that. :)

Page 1 of 1 All times are UTC + 1 hour
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/