High quality rotation image for photo
Posted: Mon Aug 22, 2011 8:46 am
High quality rotation image Tips for photo
example angle is float -0.1234567
bi-linear interpolation
and auto triming process
example angle is float -0.1234567
bi-linear interpolation
and auto triming process
Code: Select all
UseJPEGImageDecoder()
#Image = 1
Procedure CopyImageToMemory(ImageNumber.l, Memory.l)
Protected TemporaryDC.l, TemporaryBitmap.BITMAP, TemporaryBitmapInfo.BITMAPINFO
TemporaryDC = CreateDC_("DISPLAY", #Null, #Null, #Null)
GetObject_(ImageID(ImageNumber), SizeOf(BITMAP), TemporaryBitmap.BITMAP)
TemporaryBitmapInfo\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
TemporaryBitmapInfo\bmiHeader\biWidth = TemporaryBitmap\bmWidth
TemporaryBitmapInfo\bmiHeader\biHeight = -TemporaryBitmap\bmHeight
TemporaryBitmapInfo\bmiHeader\biPlanes = 1
TemporaryBitmapInfo\bmiHeader\biBitCount = 32
TemporaryBitmapInfo\bmiHeader\biCompression = #BI_RGB
GetDIBits_(TemporaryDC, ImageID(ImageNumber), 0, TemporaryBitmap\bmHeight, Memory, TemporaryBitmapInfo, #DIB_RGB_COLORS)
DeleteDC_(TemporaryDC)
EndProcedure
Procedure CopyMemoryToImage(Memory.l,ImageNumber.l)
Protected TemporaryDC.l, TemporaryBitmap.BITMAP, TemporaryBitmapInfo.BITMAPINFO
TemporaryDC = CreateDC_("DISPLAY", #Null, #Null, #Null)
GetObject_(ImageID(ImageNumber), SizeOf(BITMAP), TemporaryBitmap.BITMAP)
TemporaryBitmapInfo\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
TemporaryBitmapInfo\bmiHeader\biWidth = TemporaryBitmap\bmWidth
TemporaryBitmapInfo\bmiHeader\biHeight = -TemporaryBitmap\bmHeight
TemporaryBitmapInfo\bmiHeader\biPlanes = 1
TemporaryBitmapInfo\bmiHeader\biBitCount = 32
TemporaryBitmapInfo\bmiHeader\biCompression = #BI_RGB
SetDIBits_(TemporaryDC, ImageID(ImageNumber), 0, TemporaryBitmap\bmHeight, Memory, TemporaryBitmapInfo, #DIB_RGB_COLORS)
DeleteDC_(TemporaryDC)
EndProcedure
Procedure Rotation_Image_Angle(image.l, angle.f)
Protected MemorySizeOrigin.l, *MemoryOrigin, *MemoryCopy
Protected theta.f, vcos.f, vsin.f, dx.f, dy.f
Protected W.l, H.l, cx.l, cy.l, x.l, Y.l, ncx.l, ncy.l,nx.l, ny.l, zStep.b, zxm.l
Protected zx1.l, zy1.l, zx2.l, zy2.l, zw.l, zh.l,zx3.l, zy3.l, zx4.l, zy4.l, zxS.l, zyS.l, zxE.l, zyE.l, nw.l, nh.l
Protected Origindata_R0.l, Origindata_R1.l, Origindata_R2.l, Origindata_R3.l, Origindata_R4.l
Protected Origindata_G0.l, Origindata_G1.l, Origindata_G2.l, Origindata_G3.l, Origindata_G4.l
Protected Origindata_B0.l, Origindata_B1.l, Origindata_B2.l, Origindata_B3.l, Origindata_B4.l
; Input initialize
W = ImageWidth(image)
H = ImageHeight(image)
cx = Int(W/2)
cy = Int(H/2)
theta = angle*(-1) * #PI /180
vcos = Cos(theta)
vsin = Sin(theta)
; Output initialize
nw = Int(W * Abs(vcos) + H * Abs(vsin))
nh = Int(W * Abs(vsin) + H * Abs(vcos))
ncx = Int((nw) / 2)
ncy = Int((nh)/ 2)
MemorySizeOrigin = (W*H << 2)
*MemoryOrigin = AllocateMemory(MemorySizeOrigin)
MemorySizeOrigin = (nw*nh << 2)
*MemoryCopy = AllocateMemory(MemorySizeOrigin)
CopyImageToMemory(image, *MemoryOrigin)
; 1st Pass Auto Triming
For ny = 0 To nh-1
For nx=0 To nw-1
dx = ((nx-ncx)*vcos - (ny-ncy)*vsin)+cx
dy = ((nx-ncx)*vsin + (ny-ncy)*vcos)+cy
x = Int(dx)
Y = Int(dy)
If dx>=0 And dx<(W-1) And dy>=0 And dy<(H-1)
dx= dx - x
dy = dy - Y
Origin = (ny * nw + nx) << 2
PokeL(*MemoryCopy + Origin, 1)
EndIf
Next
Next
If angle> 0
For ny=0 To nh-1
For nx=0 To nw-1
Origin = (ny * nw + nx) << 2
If PeekL(*MemoryCopy + Origin)=1
zx1 = nx : zy1 =ny
Break 2
EndIf
Next
Next
For nx=(nw-1) To 0 Step -1
For ny=0 To nh-1
Origin = (ny * nw + nx) << 2
If PeekL(*MemoryCopy + Origin)=1
zx2 = nx : zy2 =ny
Break 2
EndIf
Next
Next
;
For nx=0 To (nw-1)
For ny=(nh-1) To 0 Step -1
Origin = (ny * nw + nx) << 2
If PeekL(*MemoryCopy + Origin)=1
zx3 = nx : zy3 =ny
Break 2
EndIf
Next
Next
;
For ny=(nh-1) To 0 Step -1
For nx=(nw-1) To 0 Step -1
Origin = (ny * nw + nx) << 2
If PeekL(*MemoryCopy + Origin)=1
zx4 = nx : zy4 =ny
Break 2
EndIf
Next
Next
;
zxS = zx1 : zyS = zy2 : zxE=zx4 : zyE=zy3
Else
For nx=0 To nw-1
For ny=0 To nh-1
Origin = (ny * nw + nx) << 2
If PeekL(*MemoryCopy + Origin)=1
zx1 = nx : zy1 =ny
Break 2
EndIf
Next
Next
;
For ny=0 To nh-1
For nx=(nw-1) To 0 Step -1
Origin = (ny * nw + nx) << 2
If PeekL(*MemoryCopy + Origin)=1
zx2 = nx : zy2 =ny
Break 2
EndIf
Next
Next
;
For ny=(nh-1) To 0 Step -1
For nx=0 To nw-1
Origin = (ny * nw + nx) << 2
If PeekL(*MemoryCopy + Origin)=1
zx3 = nx : zy3 =ny
Break 2
EndIf
Next
Next
;
For nx=(nw-1) To 0 Step -1
For ny=(nh-1) To 0 Step -1
Origin = (ny * nw + nx) << 2
If PeekL(*MemoryCopy + Origin)=1
zx4 = nx : zy4 =ny
Break 2
EndIf
Next
Next
;
zxS = zx3 : zyS = zy1 : zxE=zx2 : zyE=zy4
EndIf
zw = zxE-zxS : zh = zyE-zyS
; 2nd Pass Triming rotation image
For ny = zyS To zyE
For nx=zxS To zxE
dx = ((nx-ncx)*vcos - (ny-ncy)*vsin)+cx
dy = ((nx-ncx)*vsin + (ny-ncy)*vcos)+cy
x = Int(dx)
Y = Int(dy)
If dx>=0 And dx<(W-1) And dy>=0 And dy<(H-1)
dx= dx - x
dy = dy - Y
Origin = (Y* W + x) << 2
Origindata_B1 = PeekL(*MemoryOrigin + Origin) & $0000FF
Origindata_G1 = (PeekL(*MemoryOrigin + Origin) & $00FF00) >> 8
Origindata_R1 = (PeekL(*MemoryOrigin + Origin) & $FF0000) >> 16
Origin = (Y * W + x+1) << 2
Origindata_B2 = PeekL(*MemoryOrigin + Origin) & $0000FF
Origindata_G2 = (PeekL(*MemoryOrigin + Origin) & $00FF00) >> 8
Origindata_R2 = (PeekL(*MemoryOrigin + Origin) & $FF0000) >> 16
Origin = ((Y+1) * W + x) << 2
Origindata_B3 = PeekL(*MemoryOrigin + Origin) & $0000FF
Origindata_G3 = (PeekL(*MemoryOrigin + Origin) & $00FF00) >> 8
Origindata_R3 = (PeekL(*MemoryOrigin + Origin) & $FF0000) >> 16
Origin = ((Y+1) * W + x+1) << 2
Origindata_B4 = PeekL(*MemoryOrigin + Origin) & $0000FF
Origindata_G4 = (PeekL(*MemoryOrigin + Origin) & $00FF00) >> 8
Origindata_R4 = (PeekL(*MemoryOrigin + Origin) & $FF0000) >> 16
Origin = ((ny-zyS) * zw + (nx-zxS)) << 2
Origindata_R0 = Round((1-dy)*((1-dx)*Origindata_R1+ dx*Origindata_R2)+dy*((1-dx)*Origindata_R3+dx*Origindata_R4) ,#PB_Round_Nearest)
Origindata_G0 = Round((1-dy)*((1-dx)*Origindata_G1+ dx*Origindata_G2)+dy*((1-dx)*Origindata_G3+dx*Origindata_G4) ,#PB_Round_Nearest)
Origindata_B0 = Round((1-dy)*((1-dx)*Origindata_B1+ dx*Origindata_B2)+dy*((1-dx)*Origindata_B3+dx*Origindata_B4) ,#PB_Round_Nearest)
If Origindata_R0>255
Origindata_R0 = 255
EndIf
If Origindata_G0>255
Origindata_G0 = 255
EndIf
If Origindata_B0>255
Origindata_B0 = 255
EndIf
Origindata_G0 = (Origindata_G0 << 8) & $00FF00
Origindata_R0 = (Origindata_R0 << 16) & $FF0000
PokeL(*MemoryCopy + Origin, Origindata_R0 | Origindata_G0 | Origindata_B0 )
EndIf
Next
Next
ResizeImage(image, zw, zh)
CopyMemoryToImage(*MemoryCopy, image)
FreeMemory(*MemoryOrigin)
FreeMemory(*MemoryCopy)
EndProcedure
; Main
Filename.s = OpenFileRequester("Image load", "*.*", "*.*",0)
LoadImage(#Image, Filename)
Rotation_Image_Angle(#Image, -0.1234567)
SaveImage(#Image, Filename+".bmp", #PB_ImagePlugin_BMP)