Platforms to show: All Mac Windows Linux Cross-Platform
/Picture/Image effects/imagetransformation
Required plugins for this example: MBS Picture Plugin
You find this example project in your Plugins Download as a Xojo project file within the examples folder: /Picture/Image effects/imagetransformation
This example is the version from Fri, 17th Nov 2016.
Project "imagetransformation.xojo_binary_project"
FileTypes
Filetype text
Filetype special/any
End FileTypes
Class Window1 Inherits Window
Control source Inherits Canvas
ControlInstance source Inherits Canvas
EventHandler Sub DropObject(obj As DragItem, action As Integer)
dim p as picture
dim f as folderItem
do
if obj.pictureAvailable then
p = obj.picture
elseif obj.folderItemavailable then
f = obj.folderItem
p = f.openaspicture
end
LoadPicture p
loop until not obj.NextItem
End EventHandler
EventHandler Sub Open()
me.acceptpictureDrop
me.acceptfileDrop("special/any")
End EventHandler
EventHandler Sub Paint(g As Graphics, areas() As REALbasic.Rect)
if sourcepicture = nil then
g.drawstring "Drag picture here",10,me.height/2
g.drawrect 0,0,me.width,me.height
else
g.drawpicture sourcepicture,0,0,g.Width,g.Height,0,0,sourcepicture.Width,sourcepicture.Height
end
End EventHandler
End Control
Control destination Inherits Canvas
ControlInstance destination Inherits Canvas
EventHandler Function MouseDown(X As Integer, Y As Integer) As Boolean
Dim d as DragItem
if destinationpicture<>nil then
d=New DragItem(self, Me.left,Me.top,Me.width,Me.height)
d.picture=destinationpicture
d.Drag //Allow the drag
end
End EventHandler
EventHandler Sub Paint(g As Graphics, areas() As REALbasic.Rect)
if destinationpicture = nil then
g.drawrect 0,0,me.width,me.height
else
g.drawpicture destinationpicture,0,0,me.width,me.height,0,0,destinationpicture.width,destinationpicture.height
end
End EventHandler
End Control
Control PushButton1 Inherits PushButton
ControlInstance PushButton1 Inherits PushButton
EventHandler Sub Action()
dim m(2,2) as double
dim t as integer
dim p as PictureMatrix3DMBS
// matrix for gray
if CheckPlugin.Value then
p=new PictureMatrix3DMBS
p.Matrix(0,0) = 0.3
p.Matrix(1,0) = 0.59
p.Matrix(2,0) = 0.11
p.Matrix(0,1) = 0.3
p.Matrix(1,1) = 0.59
p.Matrix(2,1) = 0.11
p.Matrix(0,2) = 0.3
p.Matrix(1,2) = 0.59
p.Matrix(2,2) = 0.11
p.SourcePicture=sourcepicture
t=Ticks
call p.run
t=ticks-t
destinationpicture=p.DestinationPicture
else
m(0,0) = 0.3
m(1,0) = 0.59
m(2,0) = 0.11
m(0,1) = 0.3
m(1,1) = 0.59
m(2,1) = 0.11
m(0,2) = 0.3
m(1,2) = 0.59
m(2,2) = 0.11
t=Ticks
destinationpicture = sourcepicture.matrix3d(m,checkdither.value)
t=Ticks-t
end if
destination.refresh
StaticText6.text=str(t)
End EventHandler
End Control
Control StaticText1 Inherits Label
ControlInstance StaticText1 Inherits Label
End Control
Control PushButton2 Inherits PushButton
ControlInstance PushButton2 Inherits PushButton
EventHandler Sub Action()
dim m(2,2) as double
dim t as integer
dim p as PictureMatrix3DMBS
// matrix for sepia
if CheckPlugin.Value then
p=new PictureMatrix3DMBS
p.matrix(0,0) = 0.3 * 255/255
p.matrix(1,0) = 0.59 * 255/255
p.matrix(2,0) = 0.11 * 255/255
p.matrix(0,1) = 0.3 * 168/255
p.matrix(1,1) = 0.59 * 168/255
p.matrix(2,1) = 0.11 * 168/255
p.matrix(0,2) = 0.3 * 60/255
p.matrix(1,2) = 0.59 * 60/255
p.matrix(2,2) = 0.11 * 60/255
p.SourcePicture=sourcepicture
t=Ticks
call p.run
t=ticks-t
destinationpicture=p.DestinationPicture
else
m(0,0) = 0.3 * 255/255
m(1,0) = 0.59 * 255/255
m(2,0) = 0.11 * 255/255
m(0,1) = 0.3 * 168/255
m(1,1) = 0.59 * 168/255
m(2,1) = 0.11 * 168/255
m(0,2) = 0.3 * 60/255
m(1,2) = 0.59 * 60/255
m(2,2) = 0.11 * 60/255
t=ticks
destinationpicture = sourcepicture.matrix3d(m,checkdither.value)
t=Ticks-t
end if
StaticText7.text=str(t)
destination.refresh
End EventHandler
End Control
Control PushButton3 Inherits PushButton
ControlInstance PushButton3 Inherits PushButton
EventHandler Sub Action()
dim m(3,3) as double
dim t as integer
dim p as PictureMatrix3DMBS
// matrix for video component YCbCr
if CheckPlugin.Value then
p=new PictureMatrix3DMBS
p.matrix(0,0) = 0.5
p.matrix(1,0) = -0.42
p.matrix(2,0) = -0.08
p.matrix(0,1) = 0.3
p.matrix(1,1) = 0.59
p.matrix(2,1) = 0.11
p.matrix(0,2) = -0.17
p.matrix(1,2) = -0.33
p.matrix(2,2) = 0.5
p.matrix(0,3) = 0
p.matrix(1,3) = 128
p.matrix(2,3) = 128
p.SourcePicture=sourcepicture
t=Ticks
call p.run
t=ticks-t
destinationpicture=p.DestinationPicture
else
m(0,0) = 0.5
m(1,0) = -0.42
m(2,0) = -0.08
m(0,1) = 0.3
m(1,1) = 0.59
m(2,1) = 0.11
m(0,2) = -0.17
m(1,2) = -0.33
m(2,2) = 0.5
m(0,3) = 0
m(1,3) = 128
m(2,3) = 128
t=ticks
destinationpicture = sourcepicture.matrix3dwithconstants(m,checkdither.value)
t=Ticks-t
end if
StaticText8.text=str(t)
destination.refresh
End EventHandler
End Control
Control StaticText2 Inherits Label
ControlInstance StaticText2 Inherits Label
End Control
Control PushButton4 Inherits PushButton
ControlInstance PushButton4 Inherits PushButton
EventHandler Sub Action()
dim h(2),v(2) as double
dim t as integer
dim p as PictureConvolutionMBS
if CheckPlugin.Value then
p=new PictureConvolutionMBS
p.hor(0) = 0.25
p.hor(1) = 0.5
p.hor(2) = 0.25
p.ver(0) = 0.25
p.ver(1) = 0.5
p.ver(2) = 0.25
p.ValueCount=3
p.SourcePicture=sourcepicture
t=ticks
call p.run(7)
t=ticks-t
destinationpicture=p.destinationpicture
else
// simple blur
h(0) = 0.25
h(1) = 0.5
h(2) = 0.25
v(0) = 0.25
v(1) = 0.5
v(2) = 0.25
t=ticks
destinationpicture = sourcepicture.convolution(h,v,7)
t=ticks-t
end if
StaticText11.text=str(t)
destination.refresh
End EventHandler
End Control
Control PushButton5 Inherits PushButton
ControlInstance PushButton5 Inherits PushButton
EventHandler Sub Action()
dim h(2),v(2) as double
dim t as integer
dim p as PictureConvolutionMBS
// simple sharpen
if CheckPlugin.Value then
p=new PictureConvolutionMBS
p.hor(0) = -0.25
p.hor(1) = 1.5
p.hor(2) = -0.25
p.ver(0) = -0.25
p.ver(1) = 1.5
p.ver(2) = -0.25
p.ValueCount=3
p.SourcePicture=sourcepicture
t=ticks
call p.run(7)
t=ticks-t
destinationpicture=p.destinationpicture
else
h(0) = -0.25
h(1) = 1.5
h(2) = -0.25
v(0) = -0.25
v(1) = 1.5
v(2) = -0.25
t=ticks
destinationpicture = sourcepicture.convolution(h,v,7)
t=ticks-t
end if
StaticText12.text=str(t)
destination.refresh
End EventHandler
End Control
Control PushButton6 Inherits PushButton
ControlInstance PushButton6 Inherits PushButton
EventHandler Sub Action()
dim lut(16,16,16,2) as double
dim r,g,b as integer
dim t as integer
dim surf as rgbSurface
dim p as PictureLut3DMBS
dim x,y as integer
dim lutinput as picture
if CheckPlugin.Value then
p=new PictureLut3DMBS
for r = 0 to 15
for g = 0 to 15
for b = 0 to 15
p.Table(r,g,b,0) = 255 - 17*r
p.Table(r,g,b,1) = 255 - 17*g
p.Table(r,g,b,2) = 255 - 17*b
next
next
next
p.SourcePicture=sourcepicture
t=ticks
call p.Run
t=ticks-t
destinationpicture=p.destinationpicture
else
for r = 0 to 15
for g = 0 to 15
for b = 0 to 15
lut(r,g,b,0) = 255 - 17*r
lut(r,g,b,1) = 255 - 17*g
lut(r,g,b,2) = 255 - 17*b
next
next
next
t=ticks
destinationpicture = sourcepicture.lut3d(lut,checkdither.value)
t=ticks-t
end if
StaticText13.text=str(t)
destination.refresh
End EventHandler
End Control
Control StaticText3 Inherits Label
ControlInstance StaticText3 Inherits Label
End Control
Control PushButton7 Inherits PushButton
ControlInstance PushButton7 Inherits PushButton
EventHandler Sub Action()
dim lut(16,16,16,2) as double
dim r,g,b as integer
dim t as integer
// selective pure red will be changed to blue, very primitive version
dim p as PictureLut3DMBS
if CheckPlugin.Value then
p=new PictureLut3DMBS
for r = 0 to 16
for g = 0 to 16
for b = 0 to 16
if r>g*2 and r>b*2 then
p.table(r,g,b,0) = 15*b
p.table(r,g,b,1) = 15*g
p.table(r,g,b,2) = 15*r
else
p.table(r,g,b,0) = 15*r
p.table(r,g,b,1) = 15*g
p.table(r,g,b,2) = 15*b
end
next
next
next
p.SourcePicture=sourcepicture
t=ticks
call p.run
t=ticks-t
destinationpicture=p.DestinationPicture
else
for r = 0 to 16
for g = 0 to 16
for b = 0 to 16
if r>g*2 and r>b*2 then
LUT(r,g,b,0) = 15*b
LUT(r,g,b,1) = 15*g
LUT(r,g,b,2) = 15*r
else
LUT(r,g,b,0) = 15*r
LUT(r,g,b,1) = 15*g
LUT(r,g,b,2) = 15*b
end
next
next
next
t=ticks
destinationpicture = sourcepicture.lut3d(lut,checkdither.value)
t=ticks-t
end if
StaticText14.text=str(t)
destination.refresh
End EventHandler
End Control
Control StaticText4 Inherits Label
ControlInstance StaticText4 Inherits Label
End Control
Control StaticText5 Inherits Label
ControlInstance StaticText5 Inherits Label
End Control
Control PushButton8 Inherits PushButton
ControlInstance PushButton8 Inherits PushButton
EventHandler Sub Action()
dim p,pattern,src,dest as picture
dim t as integer
// let's do some compositing
p = New Picture(source.width,source.height,32)
p.graphics.forecolor = rgb(0,0,0)
p.graphics.fillrect 0,0,p.width,p.height
p.mask.graphics.clearrect 0,0,p.width,p.height
pattern = New Picture(4*source.width,4*source.height,32)
pattern.mask.graphics.clearrect 0,0,pattern.width,pattern.height
pattern.mask.graphics.forecolor = rgb(0,0,0)
pattern.mask.graphics.textsize = 256
pattern.mask.graphics.drawstring "title",pattern.width/2,pattern.height/2
pattern.mask.graphics.filloval 20, 20, 400, 400
// fill picture
pattern.graphics.forecolor = rgb(255,255,255)
pattern.graphics.fillrect 0,0,pattern.width,pattern.height
p.graphics.drawpicture pattern,0,0,p.width,p.height,0,0,pattern.width,pattern.height
// fill mask
pattern.graphics.forecolor = rgb(0,0,0)
pattern.graphics.fillrect 0,0,pattern.width,pattern.height
p.mask.graphics.drawpicture pattern,0,0,p.width,p.height,0,0,pattern.width,pattern.height
destinationpicture = New Picture (p.width,p.height,32)
destinationpicture.graphics.drawpicture sourcepicture,0,0
sourcepicture.graphics.drawpicture p,0,0
source.refresh
t=ticks
destinationpicture.graphics.drawpicture p.unmultiply,0,0
t=ticks-t
destination.refresh
StaticText15.text=str(t)
End EventHandler
End Control
Control PushButton9 Inherits PushButton
ControlInstance PushButton9 Inherits PushButton
EventHandler Sub Action()
dim m,m2,m3 as memoryBlock
dim x,y as integer
dim offset as integer
dim s,s3 as string
dim surf as rgbSurface
dim t as integer
t=ticks
m = newmemoryBlock(sourcepicture.width*sourcepicture.height*4)
surf = sourcepicture.rgbSurface
for x = 0 to sourcepicture.width-1
for y = 0 to sourcepicture.height-1
m.colorValue(offset,32) = surf.pixel(x,y)
offset = offset + 4
next
next
s = m.stringValue(0,m.size)
m2 = m.RunLengthEncode
msgBox "Compressed " + format(m2.size/m.size,"0%")
m3 = m2.RunLengthDecode
s3 = m3.stringValue(0,m3.size)
if strcomp(s,s3,0) = 0 then
msgbox "Compression-Decompression succeeded"
else
msgbox "Compression-Decompression failed"
end
if destinationpicture = nil then
destinationpicture = New Picture(sourcepicture.width,sourcepicture.height,32)
end
offset = 0
surf = destinationpicture.rgbSurface
for x = 0 to destinationpicture.width-1
for y = 0 to destinationpicture.height-1
surf.pixel(x,y) = m.colorValue(offset,32)
offset = offset + 4
next
next
t=ticks-t
StaticText16.text=str(t)
destination.refresh
End EventHandler
End Control
Control PushButton11 Inherits PushButton
ControlInstance PushButton11 Inherits PushButton
EventHandler Sub Action()
dim m(2,2) as double
dim t as integer
dim p as PictureMatrix3DMBS
// matrix for identity
if CheckPlugin.Value then
p=new PictureMatrix3DMBS
p.matrix(0,0) = 1
p.matrix(1,0) = 0
p.matrix(2,0) = 0
p.matrix(0,1) = 0
p.matrix(1,1) = 1
p.matrix(2,1) = 0
p.matrix(0,2) = 0
p.matrix(1,2) = 0
p.matrix(2,2) = 1
p.SourcePicture=sourcepicture
t=Ticks
call p.run
t=ticks-t
destinationpicture=p.DestinationPicture
else
m(0,0) = 1
m(1,0) = 0
m(2,0) = 0
m(0,1) = 0
m(1,1) = 1
m(2,1) = 0
m(0,2) = 0
m(1,2) = 0
m(2,2) = 1
t=ticks
destinationpicture = sourcepicture.matrix3d(m)
t=Ticks-t
end if
StaticText9.text=str(t)
destination.refresh
End EventHandler
End Control
Control PushButton10 Inherits PushButton
ControlInstance PushButton10 Inherits PushButton
EventHandler Sub Action()
dim m(3,3) as double
dim t as integer
dim p as PictureMatrix3DMBS
// matrix for invert uses
if CheckPlugin.Value then
p=new PictureMatrix3DMBS
p.matrix(0,0) = -1
p.matrix(1,0) = 0
p.matrix(2,0) = 0
p.matrix(0,1) = 0
p.matrix(1,1) = -1
p.matrix(2,1) = 0
p.matrix(0,2) = 0
p.matrix(1,2) = 0
p.matrix(2,2) = -1
p.matrix(0,3) = 255
p.matrix(1,3) = 255
p.matrix(2,3) = 255
p.matrix(3,0) = 0
p.matrix(3,1) = 0
p.matrix(3,2) = 0
p.SourcePicture=sourcepicture
t=Ticks
call p.run
t=ticks-t
destinationpicture=p.DestinationPicture
else
m(0,0) = -1
m(1,0) = 0
m(2,0) = 0
m(0,1) = 0
m(1,1) = -1
m(2,1) = 0
m(0,2) = 0
m(1,2) = 0
m(2,2) = -1
m(0,3) = 255
m(1,3) = 255
m(2,3) = 255
t=ticks
destinationpicture = sourcepicture.matrix3dwithConstants(m,checkdither.value)
t=Ticks-t
end if
StaticText10.text=str(t)
destination.refresh
End EventHandler
End Control
Control StaticText6 Inherits Label
ControlInstance StaticText6 Inherits Label
End Control
Control StaticText7 Inherits Label
ControlInstance StaticText7 Inherits Label
End Control
Control StaticText8 Inherits Label
ControlInstance StaticText8 Inherits Label
End Control
Control StaticText9 Inherits Label
ControlInstance StaticText9 Inherits Label
End Control
Control StaticText10 Inherits Label
ControlInstance StaticText10 Inherits Label
End Control
Control CheckPlugin Inherits CheckBox
ControlInstance CheckPlugin Inherits CheckBox
End Control
Control StaticText11 Inherits Label
ControlInstance StaticText11 Inherits Label
End Control
Control StaticText12 Inherits Label
ControlInstance StaticText12 Inherits Label
End Control
Control StaticText13 Inherits Label
ControlInstance StaticText13 Inherits Label
End Control
Control StaticText14 Inherits Label
ControlInstance StaticText14 Inherits Label
End Control
Control StaticText15 Inherits Label
ControlInstance StaticText15 Inherits Label
End Control
Control StaticText16 Inherits Label
ControlInstance StaticText16 Inherits Label
End Control
Control CheckDither Inherits CheckBox
ControlInstance CheckDither Inherits CheckBox
End Control
EventHandler Sub Open()
LoadPicture toni
End EventHandler
Protected Sub LoadPicture(p as picture)
if p<>nil then
sourcepicture = New Picture(p.width,p.height,32)
sourcepicture.graphics.drawpicture p,0,0,p.width,p.Height,0,0,p.width,p.height
me.refresh
pushButton1.enabled = true
pushButton2.enabled = true
pushButton3.enabled = true
pushButton4.enabled = true
pushButton5.enabled = true
pushButton6.enabled = true
pushButton7.enabled = true
pushButton8.enabled = true
pushButton9.enabled = true
pushbutton10.enabled = true
pushButton11.enabled = true
end
End Sub
Property Protected destinationpicture As picture
Property Protected sourcepicture As picture
End Class
MenuBar MenuBar1
MenuItem UntitledMenu1 = ""
MenuItem FileMenu = "&File"
MenuItem FileQuit = "Quit"
MenuItem EditMenu = "&Edit"
MenuItem EditUndo = "Undo"
MenuItem UntitledMenu0 = "-"
MenuItem EditCut = "Cut"
MenuItem EditCopy = "Copy"
MenuItem EditPaste = "Paste"
MenuItem EditClear = "Clear"
End MenuBar
Class App Inherits Application
End Class
Module ImageTransformations
Function Convolution(extends p as picture, hor() as double, ver() as double, channels as integer) As picture
dim p2, intermediate, result as picture
dim insurf,intermediatesurf, outsurf as rgbSurface
dim x,y,w,h,r2,g2,b2,i,ub,ub2 as integer
dim start, ende as integer
dim c as color
dim r,g,b as Double
if p=nil then
return nil
end if
// verify if picture has an rgbsurface
insurf = p.rgbSurface
if insurf = nil then
p2 = New Picture(p.width,p.height,32)
if p2<>nil then
p2.graphics.drawpicture p,0,0
insurf = p2.rgbSurface
end
end
intermediate = New Picture(p.width,p.height,32)
if intermediate<>nil then
intermediatesurf = intermediate.rgbSurface
end
result = New Picture(p.width,p.height,32)
if result<>nil then
outsurf = result.rgbSurface
end
if insurf = nil or intermediatesurf = nil or outsurf = nil then
return nil
end
w = p.width-1
h = p.height-1
// borders will not be treated. if somebody want to get until the border, he can provide a larger picture.
ub = ubound(hor)
ub2 = ub\2
start = ub2
ende = w - ub2
for x = start to ende
for y = 0 to h
if bitwiseand(channels,1) = 1 then
r = 0
for i = 0 to ub
r = r + insurf.pixel(x-ub2+i,y).red * hor(i)
next
else
r = insurf.pixel(x,y).red
end
if bitwiseand(channels,2) = 2 then
g = 0
for i = 0 to ub
g = g + insurf.pixel(x-ub2+i,y).green * hor(i)
next
else
g = insurf.pixel(x,y).green
end
if bitwiseand(channels,4) = 4 then
b = 0
for i = 0 to ub
b = b + insurf.pixel(x-ub2+i,y).blue * hor(i)
next
else
b = insurf.pixel(x,y).blue
end
intermediatesurf.pixel(x,y) = rgb(r,g,b)
next
next
ub = ubound(ver)
ub2 = ub/2
start = ub2
ende = h - ub2
for x = 0 to w
for y = start to ende
if bitwiseand(channels,1) = 1 then
r = 0
for i = 0 to ub
r = r + intermediatesurf.pixel(x,y-ub2+i).red * ver(i)
next
else
r = intermediatesurf.pixel(x,y).red
end
if bitwiseand(channels,2)= 2 then
g = 0
for i = 0 to ub
g = g + intermediatesurf.pixel(x,y-ub2+i).green * ver(i)
next
else
g = intermediatesurf.pixel(x,y).green
end
if bitwiseand(channels,4)= 4 then
b = 0
for i = 0 to ub
b = b + intermediatesurf.pixel(x,y-ub2+i).blue * ver(i)
next
else
b = intermediatesurf.pixel(x,y).blue
end
outsurf.pixel(x,y) = rgb(r,g,b)
next
next
return result
End Function
Function LUT3d(extends p as picture, lut(,,,) as double, dither as boolean = false) As picture
dim p2, result as picture
dim insurf,outsurf as rgbSurface
dim x,y,r,g,b,w,h,r2,g2,b2 as integer
dim nx,ny,nz,nx1,ny1,nz1,i as integer
dim rrest, grest, brest as double
dim sxyz, fx,fy,fz as double // sxyz neu double!
dim c as color
// expects a LUT(16,16,16,2), eg 17 values in each dimension, which makes even steps from 0..15.30..255
if p=nil then return nil
// verify if picture has an rgbsurface
insurf = p.rgbSurface
if insurf = nil then
p2 = New Picture(p.width,p.height,32)
if p2<>nil then
p2.graphics.drawpicture p,0,0
insurf = p2.rgbSurface
end
end
result = New Picture(p.width,p.height,32)
if result<>nil then
outsurf = result.rgbSurface
end
if insurf = nil or outsurf = nil then
return nil
end
w = p.width-1
h = p.height-1
for y = 0 to h
for x = 0 to w
c = insurf.Pixel(x,y)
r = c.red
g = c.green
b = c.blue
nx = r \ 17
ny = g \ 17
nz = b \ 17
nx1 = min(nx+1,15)
ny1 = min(ny+1,15)
nz1 = min(nz+1,15)
fx = (r mod 17) / 17.0
fy = (g mod 17) / 17.0
fz = (b mod 17) / 17.0
for i = 0 to 2
// tetraeder interpolation.
// would probably be faster if each channel coded and not a for-loop
if (fx > fy) then
if (fy > fz) then
Sxyz = (1.0-fx)* LUT( nx , ny , nz, i ) + (fx-fy)* LUT(nx1, ny , nz, i ) + (fy-fz)* LUT(nx1,ny1, nz, i ) + (fz)* LUT(nx1,ny1,nz1,i)
elseif (fx > fz) then
Sxyz = (1.0-fx)* LUT( nx , ny , nz, i ) + (fx-fz)* LUT(nx1, ny , nz, i ) + (fz-fy)* LUT(nx1, ny ,nz1, i) + (fy)* LUT(nx1,ny1,nz1,i)
else
Sxyz = (1.0-fz)* LUT( nx , ny , nz, i) + (fz-fx)* LUT( nx , ny ,nz1, i) + (fx-fy)* LUT(nx1, ny ,nz1,i)+ (fy)* LUT(nx1,ny1,nz1,i)
end
else
if (fz > fy) then
Sxyz = (1.0-fz)* LUT( nx , ny , nz,i ) + (fz-fy)* LUT( nx , ny ,nz1,i) + (fy-fx)* LUT( nx ,ny1,nz1,i) + (fx)* LUT(nx1,ny1,nz1,i)
elseif (fz > fx) then
Sxyz = (1.0-fy)* LUT( nx , ny , nz,i ) + (fy-fz)* LUT( nx ,ny1, nz ,i) + (fz-fx)* LUT( nx ,ny1,nz1,i) + (fx)* LUT(nx1,ny1,nz1,i)
else
Sxyz = (1.0-fy)* LUT( nx , ny , nz,i ) + (fy-fx)* LUT( nx ,ny1, nz ,i) + (fx-fz)* LUT(nx1,ny1, nz ,i) + (fz)* LUT(nx1,ny1,nz1,i)
end
end
select case i
case 0
if dither then r = r + rrest
r = Sxyz
rrest = Sxyz-r
case 1
if dither then g = g + grest
g = Sxyz
grest = Sxyz-g
case 2
if dither then b = b + brest
b = Sxyz
brest = Sxyz-b
end
next
outsurf.pixel(x,y) = rgb(r,g,b)
next
next
return result
exception err as outofboundsException
msgBox "matrix too small"
End Function
Function Matrix3d(extends p as picture, m(,) as double, dither as boolean = false) As picture
dim p2, result as picture
dim insurf,outsurf as rgbSurface
dim x,y,r,g,b,w,h,r2,g2,b2 as integer
dim rd,gd,bd as double
dim rrest, grest, brest as double
dim c as color
if p=nil then return nil
// verify if picture has an rgbsurface
insurf = p.rgbSurface
if insurf = nil then
p2 = New Picture(p.width,p.height,32)
if p2<>nil then
p2.graphics.drawpicture p,0,0
insurf = p2.rgbSurface
end
end
result = New Picture(p.width,p.height,32)
if result<>nil then
outsurf = result.rgbSurface
end
if insurf = nil or outsurf = nil then
return nil
end
w = p.width-1
h = p.height-1
for x = 0 to w
for y = 0 to h
c = insurf.pixel(x,y)
r = c.red
g = c.green
b = c.blue
rd = m(0,0)*r + m(1,0)*g + m(2,0)*b
gd = m(0,1)*r + m(1,1)*g + m(2,1)*b
bd = m(0,2)*r + m(1,2)*g + m(2,2)*b
if dither then
rd = rd + rrest
r2 = rd
rrest = rd -r2
gd = gd + grest
g2 = gd
grest = gd -g2
bd = bd + brest
b2 = bd
brest = bd -b2
else
r2 = rd
g2 = gd
b2 = bd
end
outsurf.pixel(x,y) = rgb(r2,g2,b2)
next
next
return result
exception err as outofboundsException
msgBox "matrix too small"
End Function
Function Matrix3dwithConstants(extends p as picture, m(,) as double, dither as boolean = false) As picture
dim p2, result as picture
dim insurf,outsurf as rgbSurface
dim x,y,r,g,b,w,h,r2,g2,b2 as integer
dim rd,gd,bd,rrest,grest,brest as double
dim c as color
if p=nil then return nil
// verify if picture has an rgbsurface
insurf = p.rgbSurface
if insurf = nil then
p2 = New Picture(p.width,p.height,32)
if p2<>nil then
p2.graphics.drawpicture p,0,0
insurf = p2.rgbSurface
end
end
result = New Picture(p.width,p.height,32)
if result<>nil then
outsurf = result.rgbSurface
end
if insurf = nil or outsurf = nil then
return nil
end
w = p.width-1
h = p.height-1
for x = 0 to w
for y = 0 to h
c = insurf.pixel(x,y)
r = c.red + m(0,3)
g = c.green + m(1,3)
b = c.blue + m(2,3)
rd = m(0,0)*r + m(1,0)*g + m(2,0)*b + m(3,0)
gd = m(0,1)*r + m(1,1)*g + m(2,1)*b + m(3,1)
bd = m(0,2)*r + m(1,2)*g + m(2,2)*b + m(3,2)
if dither then
rd = rd + rrest
r2 = rd
rrest = rd -r2
gd = gd + grest
g2 = gd
grest = gd -g2
bd = bd + brest
b2 = bd
brest = bd -b2
else
r2 = rd
g2 = gd
b2 = bd
end
outsurf.pixel(x,y) = rgb(r2,g2,b2)
next
next
return result
exception err as outofboundsException
msgBox "matrix too small"
End Function
Function RunLengthDecode(extends m as memoryBlock) As memoryBlock
// must be dynamically resized. we start with 2 times the length
dim i,j as integer
dim count as integer
dim test,b as integer
dim st as string
dim run as boolean
dim moffset, resultoffset as integer
dim result as memoryBlock
dim s as integer
result = newmemoryBlock(m.size*2)
//Loop until you get the number of unpacked bytes you are expecting:
// Read the next source byte into n.
// If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
// Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times.
//Else if n is -128, noop.
// Endloop
//-127 signed char is 129 unsigned char
s = m.size
for i = 0 to s-1
test = m.byte(moffset)
moffset = moffset + 1
if test>=0 and test<=127 then
st = m.stringValue(moffset,test+1)
moffset = moffset + test + 1
if result.size < resultoffset + test + 1 then
result.size = resultoffset + test + 1
end
result.stringValue(resultoffset,test+1) = st
resultoffset = resultoffset + test + 1
elseif test = 128 then
// nop
else
test = test - 256 // make signed
b = m.byte(moffset)
moffset = moffset + 1
if result.size < resultoffset - test + 1 then
result.size = resultoffset - test + 1
end
for j = 1 to -test + 1
result.byte(resultoffset) = b
resultoffset = resultoffset + 1
next
end
i = moffset
next
result.size = resultoffset
return result
End Function
Function RunLengthEncode(extends m as memoryBlock) As memoryBlock
// Decode:
//Loop until you get the number of unpacked bytes you are expecting:
// Read the next source byte into n.
// If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
// Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times.
//Else if n is -128, noop.
// Endloop
//-127 signed char is 129 unsigned char
// worst case: result is 128/127 + 1 byte longer
dim i as integer
dim count as integer
dim test,old,oldold as integer
dim st as string
dim run as boolean
dim moffset, resultoffset as integer
dim result as memoryBlock
dim s as integer
result = newmemoryBlock(m.size*128/127+1)
//test with declare
// this is a toolbox function in mac, but i never got it working.
'dim memIn,memOut as memoryblock
'
'if s = 0 then
'return
'end
'
'memIn = newmemoryBlock(s)
'for i = 0 to s-1
'memin.byte(i) = m.readbyte
'next
'memOut = newmemoryBlock(s+(s+126)/127)
'
'Declare Sub PackBits Lib "InterfaceLib" (srcPtr as Ptr, dstPtr as Ptr, srcBytes as Integer)
'
'PackBits memIn,memOut,s
'
'for i = 0 to s+(s+126)/127-1
'
'next
'
'return
test=-1
old = -1
oldold=-1
count = -1
run = false
st=""
s = m.size
for i = 0 to s-1
test = m.byte(moffset)
moffset = moffset + 1
if run then
if test = old then
count = count -1
if count = 129 then
result.byte(resultoffset) = count
resultoffset = resultoffset + 1
result.byte(resultoffset) = test
resultoffset = resultoffset + 1
run = false
test = -1
count = -1
st = ""
end if
else
result.byte(resultoffset) = count
resultoffset = resultoffset + 1
result.byte(resultoffset) = old
resultoffset = resultoffset + 1
run = false
count = 0
st =chrb(test)
end if
else
if test = old and test = oldold then
if count > 1 then
result.byte(resultoffset) = count-2
resultoffset = resultoffset + 1
result.stringvalue(resultoffset,lenb(st)) = st
resultoffset = resultoffset + lenb(st)
resultoffset = resultoffset - 2 // last 2 bytes are wrong
end if
run = true
count = 254
st =""
else
st = st + chrb(test)
count = count + 1
if count = 127 then
result.byte(resultoffset) = count
resultoffset = resultoffset + 1
result.stringvalue(resultoffset,lenb(st)) = st
resultoffset = resultoffset + lenb(st)
run = false
test = -1
count = -1
st = ""
end if
end if
end if
oldold = old
old = test
next
if count >-1 then
if run then
result.byte(resultoffset) = count
resultoffset = resultoffset + 1
result.byte(resultoffset) = test
resultoffset = resultoffset + 1
else
result.byte(resultoffset) = count
resultoffset = resultoffset + 1
result.stringvalue(resultoffset,lenb(st)) = st
resultoffset = resultoffset + lenb(st)
end if
end if
result.size = resultoffset
return result
End Function
Function Unmultiply(extends p as picture) As picture
dim p2, maskpicture, result as picture
dim insurf,masksurf,outsurf as rgbSurface
dim x,y,r,g,b,m,w,h as integer
dim c as color
if p=nil then return nil
// verify if picture has an rgbsurface
insurf = p.rgbSurface
if insurf = nil then
p2 = New Picture(p.width,p.height,32)
if p2<>nil then
p2.graphics.drawpicture p,0,0
insurf = p2.rgbSurface
end
else
p2 = p
end
maskpicture = p2.mask
masksurf = maskpicture.rgbsurface
result = New Picture(p.width,p.height,32)
if result<>nil then
outsurf = result.rgbSurface
end
if insurf = nil or masksurf = nil or outsurf = nil then
return nil
end
w = p.width-1
h = p.height-1
for x = 0 to w
for y = 0 to h
c = insurf.pixel(x,y)
r = c.red
g = c.green
b = c.blue
m = 255-masksurf.pixel(x,y).green
if m > 0 then
r = r * 255 / m
g = g * 255 / m
b = b * 255 / m
end
outsurf.pixel(x,y) = rgb(r,g,b)
next
next
result.mask.graphics.drawpicture maskpicture,0,0
return result
End Function
Note "About PictureConvolutionMBS"
Class PictureConvolutionMBS
Filter a picture using a custom defined horizontal and vertical convolution.
A conviolution is a filter window applied iteratively over the pixels.
Convolution filtering is a basic image-processing function used for
applications like blurring, sharpening, edge detection and resampling.
The filters are provides to the plugin as arrays of doubles. If the sum of the
values is not 1, then the resulting picture will be darker or brighter.
The border pixels (filtersize/2) will not be processed but return white.
If you need the filter until the border, then you need to provide a larger
picture with either a black border or the last pixel repeated, whatever is
more appropriate for you.
Properties:
- Hor() as double : filter set for horizontal filtering.
- Ver() as double : filter set for vertical filtering
- MaxX ??
- MaxY ??
- MinX ??
- MinY ??
- sourcePicture as Picture
- destinationPicture as Picture
Methods:
- Run : transform the sourcePicture into the destinationPicture
- Close
Note "About PictureLut3dMBS"
Class PictureLut3dMBS
Color correction of a picture using a three-dimensional lookup table.
Lookup tables are used to speed up color corrections of an image.
A three-dimensional lookup table can modelise any correction and even
corrections based on experimental data, where no mathematical model is available.
To be efficient, the lookup table cannot contain all values (17 million),
but only some values in a regular grid. The values are then interpolated.
If you retain the corner values 0 and 255, there is a limited number of possible
grid sizes, all of which must be dividers of 255.
We retain a table with 16*16*16 values which gives a good interpolation while keeping the size of the table small.
Properties:
- Table(15,15,15,2) as Double : look up table. The dimesions define red, green, blue and the channel.
- MaxX ??
- MaxY ??
- MinX ??
- MinY ??
- sourcePicture as Picture
- destinationPicture as Picture
- dither as Boolean : dither rounding errors to avoid stepping artefacts
Methods:
- Run : transform the sourcePicture into the destinationPicture
- Close
Note "About PictureMatrix3DMBS"
Class PictureMatrix3dMBS
Transformation of a picture in the RGB color space.
Each new color is defined as a linear combination of the old color.
This transformation can be used to make a picture gray or tinted or
to transform the picture into another color space like the video component space.
The matrix (0,0) - (2,2) define the multiplication factors.
The vector (0,3) - (2,3) defines the constants added before the multiplication to the source channel.
The vector (3,0) - (3,2) defines the constants added after the multiplication to the source channel.
The value (3,3) is unused.
Red, for example, is calculated using the following formula:
red = Matrix(0,0)*(r+Matrix(0,3)) + Matrix(1,0)*(g+Matrix(1,3)) + Matrix(2,0)*(b+Matrix(2,3)) + Matrix(3,0)
Properties:
- Matrix(3,3) as Double :
- MaxX ??
- MaxY ??
- MinX ??
- MinY ??
- sourcePicture as Picture
- destinationPicture as Picture
- dither as Boolean : dither rounding errors to avoid stepping artefacts
Methods:
- Run : transform the sourcePicture into the destinationPicture
- Close
End Module
ExternalFile toni
End ExternalFile
End Project
See also:
The items on this page are in the following plugins: MBS Picture Plugin.