Re: Vector Lib: Rotate: Lost Pixels
Posted: Tue Mar 30, 2021 12:37 pm
Interesting 

http://www.purebasic.com
https://www.purebasic.fr/english/
Code: Select all
; RotateLeft90() and RotateRight90()
; Based on code by Ligatur and hjbremer
; https://www.purebasic.fr/german/viewtopic.php?f=16&t=18695
; Improved by Lord to overcome the limits for PlgBlt_()
; https://www.purebasic.fr/english/viewtopic.php?f=13&t=48002
EnableExplicit
Enumeration
#MainWindow
EndEnumeration
Enumeration
#ScrollArea
#Canvas
EndEnumeration
Enumeration
#Img1
#Img2
#Img3
EndEnumeration
Enumeration
#Open
#Left
#Right
EndEnumeration
EnumerationBinary 128
#BS128
#BS256
#BS512
#BS1024
#BS2048
EndEnumeration
#BlockSize=#BS512; A BlockSize of 512x512 turned out to be the fastest way to rotate a big image
Define Event, Quit=#False
UseGIFImageDecoder()
UseJPEG2000ImageDecoder()
UseJPEGImageDecoder()
UsePNGImageDecoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()
Procedure RotateLeft90()
Protected iw, ih, x, y, dc
iw=ImageWidth(#Img1):ih=ImageHeight(#Img1)
If CreateImage(#Img2, ih, iw)
Dim p.point(2)
For y=0 To ih Step #BlockSize
For x=0 To iw Step #BlockSize
If GrabImage(#Img1, #Img3, x, y, #BlockSize, #BlockSize)
p(0)\x=0
p(0)\y=#BlockSize
p(1)\x=0
p(1)\y=0
p(2)\x=#BlockSize
p(2)\y=#BlockSize
dc = StartDrawing(ImageOutput(#Img3))
If dc
PlgBlt_(dc, p(), dc, 0, 0, #BlockSize, #BlockSize, 0, 0, 0)
EndIf
StopDrawing()
If StartDrawing(ImageOutput(#Img2))
DrawImage(ImageID(#Img3), y, iw-x-#BlockSize)
StopDrawing()
EndIf
EndIf
Next
Next
CopyImage(#Img2, #Img1)
EndIf
EndProcedure
Procedure RotateRight90()
Protected iw, ih, x, y, dc
iw=ImageWidth(#Img1):ih=ImageHeight(#Img1)
If CreateImage(#Img2, ih, iw)
Dim p.point(2)
For y=0 To ih Step #BlockSize
For x=0 To iw Step #BlockSize
If GrabImage(#Img1, #Img3, x, y, #BlockSize, #BlockSize)
p(0)\x=#BlockSize
p(0)\y=0
p(1)\x=#BlockSize
p(1)\y=#BlockSize
p(2)\x=0
p(2)\y=0
dc = StartDrawing(ImageOutput(#Img3))
If dc
PlgBlt_(dc,p(),dc,0,0,#BlockSize,#BlockSize,0,0,0)
StopDrawing()
EndIf
If StartDrawing(ImageOutput(#Img2))
DrawImage(ImageID(#Img3), ih-y-#BlockSize, x)
StopDrawing()
EndIf
EndIf
Next
Next
CopyImage(#Img2, #Img1)
EndIf
EndProcedure
Procedure OpenImage()
Protected I1W, I1H
Protected Img.s
Img=OpenFileRequester("SELECT IMAGE","","All supported formats|*.*;*.bmp;*.gif; *.jpg; *.jpeg;*.png;*.tif;*.tiff;*.tga|TGA image (*.tga)|*.tga|TIF image (*.tif)|*.tif|TIFF image (*.tiff)|*.tiff|PNG image (*.png)|*.png|BMP image (*.bmp)|*.bmp|JPEG image (*.jpg;*.jpeg)|*.jpg;*.jpeg|GIF image (*.gif)|*.gif",0)
If Img
If LoadImage(#Img1, Img)
I1W=ImageWidth(#Img1)
I1H=ImageHeight(#Img1)
SetGadgetAttribute(#ScrollArea, #PB_ScrollArea_InnerWidth, I1W)
SetGadgetAttribute(#ScrollArea, #PB_ScrollArea_InnerHeight, I1H)
ResizeGadget(#Canvas, #PB_Ignore, #PB_Ignore, I1W, I1H)
SetGadgetAttribute(#Canvas, #PB_Canvas_Image, ImageID(#Img1))
EndIf
EndIf
EndProcedure
Procedure Rotate()
Protected EventMenu
EventMenu=EventMenu()
Select EventMenu
Case #Open
OpenImage()
Case #Left
RotateLeft90()
Case #Right
RotateRight90()
EndSelect
If IsImage(#Img1)
SetGadgetAttribute(#ScrollArea, #PB_ScrollArea_InnerWidth, ImageWidth(#Img1))
SetGadgetAttribute(#ScrollArea, #PB_ScrollArea_InnerHeight, ImageHeight(#Img1))
ResizeGadget(#Canvas, #PB_Ignore, #PB_Ignore, ImageWidth(#Img1), ImageHeight(#Img1))
SetGadgetAttribute(#Canvas, #PB_Canvas_Image, ImageID(#Img1))
EndIf
EndProcedure
Procedure myResize()
ResizeGadget(#ScrollArea, #PB_Ignore, #PB_Ignore, WindowWidth(#MainWindow), WindowHeight(#MainWindow))
EndProcedure
OpenWindow(#MainWindow, 10, 10, 1024, 768, "Rotate90 test: [CTRL][O] select image, [L] rotate left, [R] rotate right", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
ScrollAreaGadget(#ScrollArea, 0, 0, WindowWidth(#MainWindow), WindowHeight(#MainWindow), 0, 0)
CanvasGadget(#Canvas, 0, 0, 0, 0)
CloseGadgetList()
AddKeyboardShortcut(#MainWindow, #PB_Shortcut_Control|#PB_Shortcut_O, #Open)
AddKeyboardShortcut(#MainWindow, #PB_Shortcut_L, #left)
AddKeyboardShortcut(#MainWindow, #PB_Shortcut_R, #Right)
BindEvent(#PB_Event_Menu, @Rotate(), #MainWindow)
BindEvent(#PB_Event_SizeWindow, @myResize(), #MainWindow)
Repeat
Event=WaitWindowEvent()
Select Event
Case #PB_Event_CloseWindow
Quit=#True
EndSelect
Until Quit=#True