I have this code... it uses my fractal code that I just posted in code snippets. I made a modification to it so that it draws to a memblock, makes an image from the memblock, and then saves the image and pastes it on the screen. However, I get this error:
Runtime Error 500 - Unknown image error at line 137
Apparently this is caused by a loose pointer? (aaron miller's second to last post)
The code surrounding the "save image" command is here:
line 135: make image from memblock 2,1
line 136: tstr$="\kochToRight\f"+str$(number1*3-.5,2)+".bmp"
line 137: save image tstr$,2
line 138: paste image 2,0,0
line 139: sync
If I comment out "save image", then I do get an image showing from paste image, but it's nothing like it should be!

This definitely reminds me of a memory leak, especially because there are random patterns. In fact, the only "color" I pass in is rgb(200,200,200) and 000000. There shouldn't be anything but grey and black!
So... can anyone tell me - What is going on?!?! The code i'm using to draw the memblock images is the same code I've used
here, and the original, working, fractal code is
here.
I honestly have no idea what's going on, and I don't think I have errors in my memblock image handling or image creation...
this is the whole code. I don't believe it uses any plugins.
`BaseMotifFractal
`BaseMotifFractal.dba
`======================
`BaseMotifFractal
`BaseMotifFractal.dba
`======================
type vec2
x as float
y as float
invx as integer
invy as integer
endtype
type graphScreen
tl as vec2 `top left corner
br as vec2 `bottom right corner
c as vec2 `location of (0,0) on the screen, or where it should be if its not visible. (in pixels)
PPU as float `Pixels per graph Unit.
endtype
global cmc `Current frame Mouse Click
global lmc `Last frame Mouse Click
global mh `Mouse Held
global ZeroVector as vec2
zeroVector.x=0
zeroVector.y=0
dim graphs(2) as graphScreen
graphs(0).tl=ZeroVector
graphs(0).br.x=screen width()/3-10
graphs(0).br.y=screen height()/2-5
`visible: from 1.1 to -1.1 on the y axis
graphs(0).ppu=screen height()/4.4
`(.5,0) is on the center of the graph area
graphs(0).c.x=(graphs(0).tl.x+graphs(0).br.x-graphs(0).ppu)/2
graphs(0).c.y=(graphs(0).tl.y+graphs(0).br.y)/2
graphs(1).tl.x=0
graphs(1).tl.y=screen height()/2+5
graphs(1).br.x=screen width()/3-10
graphs(1).br.y=screen height()
`visible: from 1.1 to -1.1 on the y axis
graphs(1).ppu=screen height()/4.4
`(.5,0) is on the center of the graph area
graphs(1).c.x=(graphs(1).tl.x+graphs(1).br.x-graphs(1).ppu)/2
graphs(1).c.y=(graphs(1).tl.y+graphs(1).br.y)/2
graphs(2).tl.x=0
graphs(2).tl.y=0
graphs(2).br.x=screen width()
graphs(2).br.y=screen height()
`visible: from 1.1 to -1.1 on the y axis
graphs(2).ppu=400
`(.5,0) is on the center of the graph area
graphs(2).c.x=(graphs(2).tl.x+graphs(2).br.x-graphs(2).ppu)/2
graphs(2).c.y=(graphs(2).tl.y+graphs(2).br.y)/2
global ret as vec2
dim finalCurve(-1) as vec2
dim base(1) as vec2
`--
clearBase()
temp as vec2
lastP as vec2
switch as integer
switch=0
totalIterations as integer
variable1 as float
variable2 as float
variable3 as float
variable4 as integer
whichfractal as integer
whichfractal=1
fractalchanged as integer
fractalchanged=1
previewrenderdepth as integer
variable1=.5
variable2=.5
variable3=.5
variable4=0
totalIterations=5
previewRenderDepth=2
`Q/A changes totalIterations`
`W/S changes variable4 - determines switching by each bit`
`spacebar renders up to depth totalIterations
`E/D changes variable1 - determines height`
`R/F changes variable2 - determines offset`
`T/G changes variable3 - determines width`
`not all of these values are used all of the time.
`z changes the base to a line`
`x changes the base to a triangle``
`c changes the base to a square`
`d changes the base to a regular hexagon`
`up arrow/down arrow switches between fractals`
`p randomizes all variables1-4`
`o zeros all variables 1-4`
`i exits the loop, in case you try to render too much!`
`y/h increases preview render depth.`
`preview render depth is so that you can see how the fractal will look while you're messing with
`the other variables. Normally this should be 2 or 3.
array insert at bottom graphs()
graphs(3).tl.x=0
graphs(3).tl.y=0
graphs(3).br.x=499
graphs(3).br.y=499
graphs(3).ppu=300
`(.5,0) is on the center of the graph area
graphs(3).c.x=(graphs(3).tl.x+graphs(3).br.x-graphs(3).ppu)/2
graphs(3).c.y=(graphs(3).tl.y+graphs(3).br.y)/2
mMake(1,500,500)
number1 as float
make image 2,500,500
for n=0 to 50
mCLS(1,0)
number1=n*.3333333/50.0+1.666667
if number1+.01>.5 then number1=.5
kochGeneralized(0,.5,number1,(number1-.1666667)*0.6339756+.2886748)
fillFinalCurve(3,1/300.0)
drawFractToMemblock(1,3)
make image from memblock 2,1
tstr$="\kochToRight\f"+str$(number1*3-.5,2)+".bmp"
save image tstr$,2
paste image 2,0,0
sync
next n
end
function drawSide(depth as integer)
fillFinalCurve(depth,1.0/(graphs(0).ppu))
drawFract(0)
fillFinalCurve(0,1.0/(graphs(1).ppu))
drawFract(1)
endfunction
function DrawFract(graph as integer)
temp as vec2
lastP as vec2
lastP=finalCurve(0)
for n=1 to array count(finalCurve())
temp=finalCurve(n)
drawLine(lastP,temp,rgb(200,200,200),graph)
`drawThickDot(temp.x,temp.y,rgb(255,0,0),2)
lastP=temp
next n
endfunction
function DrawFractToMemblock(mem as integer,graph as integer)
temp as vec2
lastP as vec2
lastP=finalCurve(0)
for n=1 to array count(finalCurve())
temp=finalCurve(n)
drawLineToMemblock(mem,lastP,temp,rgb(200,200,200),graph)
`drawThickDot(temp.x,temp.y,rgb(255,0,0),2)
lastP=temp
next n
endfunction
function drawLineToMemblock(mem, A as vec2, B as vec2, color as dword,graph)
units_to_pix(A.x,A.y,graph)
x1=ret.x
y1=ret.y
units_to_pix(B.x,B.y,graph)
x2=ret.x
y2=ret.y
mLine(mem,x1,y1,x2,y2,color)
endfunction
function mMake(mem1,width as integer height as integer)
make memblock mem1,(width*height*4)+12
write memblock dword mem1,0,width
write memblock dword mem1,4,height
write memblock dword mem1,8,32
endfunction
function mDot(mem as byte,x as integer, y as integer, color as dword)
if x>0 and y>0 and x<memblock dword(mem,0) and y<memblock dword(mem,4) then write memblock dword mem,((y*memblock dword(mem,0))+x)*4+12,color
endfunction
function mCls(mem as byte, color as dword)
for x=0 to memblock dword(mem,0)
for y=0 to memblock dword(mem,4)
mDot(mem,x,y,color)
next
next
endfunction
function mBox(mem as byte, x1 as integer,y1 as integer, x2 as integer,y2 as integer, color as dword)
for x=x1 to x2
for y=y1 to y2
mDot(mem,x,y,color)
next
next
endfunction
REM =========================
REM x1,y1 = starting point
REM x2,y2 = ending poing
REM thick = line thickness
REM draws a line
function mLine(mem as integer,x1,y1,x2,y2, color as dword)
dx = x2-x1
dy = y2-y1
`dot x1, y1
mDot(mem,x1,y1,color)
if abs(dx) > abs(dy)
m# = (0.0 + dy)/dx
b# = y1 - m#*x1
if dx < 0
dx = -1
else
dx = 1
endif
while x1 <> x2
x1 = x1 + dx
`dot x1, m#*x1+b#
mDot(mem,x1, m#*x1+b# ,color)
endwhile
else
if dy <> 0
m# = (0.0 + dx)/dy
b# = x1 - m#*y1
if dy < 0
dy = -1
else
dy = 1
endif
while y1 <> y2
y1 = y1 + dy
`dot m#*y1+b#, y1
mDot(mem,m#*y1+b#,y1,color)
endwhile
endif
endif
endfunction
function preset1() ` squiggle
undim motif()
dim motif(9) as vec2
for n=0 to array count(motif())
motif(n).invx=1
motif(n).invy=1
next n
`element 0 to 9
motif(0).x=0
motif(9).x=1
for n=1 to 4
motif(n*2).x=n/5.0
motif(n*2-1).x=n/5.0
next n
for n=0 to 4
v#=sin(n*90)*.2
motif(n*2).y=v#
motif(n*2+1).y=v#
next n
`--
`makes a "mySequence" that looks like:
` _
`_| |_ _
` |_|
`^^^coded so weirdly because I didn't want to have 20 lines of BLAH =some lame boring value
`remend
endfunction
function preset2() `koch curve
undim motif()
dim motif(4) as vec2
for n=0 to array count(motif())
motif(n).invx=1
motif(n).invy=1
next n
q as integer
q=0
motif(q).x=0
motif(q).y=0 : inc q
motif(q).x=.33333
motif(q).y=0 : inc q
motif(q).x=.5
motif(q).y=0.288675 : inc q
motif(q).x=.66666
motif(q).y=0 : inc q
motif(q).x=1
motif(q).y=0 : inc q
endfunction
function preset3() `right angle bracket
undim motif()
dim motif(3) as vec2
for n=0 to array count(motif())
motif(n).invx=1
motif(n).invy=1
next n
q as integer
q=0
motif(q).x=0
motif(q).y=0 : inc q
motif(q).x=.5
motif(q).y=.5 : inc q
motif(q).x=1
motif(q).y=0 : inc q
endfunction
function RightAngleSweep(a as integer) `the kind of sweep depends on a
undim motif()
dim motif(2) as vec2
q as integer
q=0
motif(q).x=0
motif(q).y=0 : inc q
motif(q).x=.5
motif(q).y=.5 : inc q
motif(q).x=1
motif(q).y=0 : inc q
for n=0 to array count(motif())-1
if getBit(a,n*2)=1
motif(n).invx=-1
else
motif(n).invx=1
endif
if getBit(a,n*2+1)=1
motif(n).invy=-1
else
motif(n).invy=1
endif
next n
endfunction
function AngleGeneralized(a as integer, offset as float,height as float)
undim motif()
dim motif(2) as vec2
q as integer
q=0
motif(q).x=0
motif(q).y=0 : inc q
motif(q).x=offset
motif(q).y=height : inc q
motif(q).x=1
motif(q).y=0 : inc q
for n=0 to array count(motif())-1
if getBit(a,n*2)=1
motif(n).invx=-1
else
motif(n).invx=1
endif
if getBit(a,n*2+1)=1
motif(n).invy=-1
else
motif(n).invy=1
endif
next n
endfunction
function kochGeneralized(a as integer, offset as float, width as float, height as float)
undim motif()
dim motif(4) as vec2
q as integer
q=0
motif(q).x=0
motif(q).y=0 : inc q
motif(q).x=offset-width
motif(q).y=0 : inc q
motif(q).x=offset
motif(q).y=height : inc q
motif(q).x=offset+width
motif(q).y=0 : inc q
motif(q).x=1
motif(q).y=0 : inc q
for n=0 to array count(motif())-1
if getBit(a,n*2)=1
motif(n).invx=-1
else
motif(n).invx=1
endif
if getBit(a,n*2+1)=1
motif(n).invy=-1
else
motif(n).invy=1
endif
next n
endfunction
function squiggleSweep(a as integer,offset as float, width as float, height as float)
undim motif()
dim motif(4) as vec2
q as integer
q=0
motif(q).x=0
motif(q).y=0 : inc q
motif(q).x=width
motif(q).y=height : inc q
motif(q).x=offset
motif(q).y=-height*.5 : inc q
motif(q).x=1.0-width
motif(q).y=height : inc q
motif(q).x=1
motif(q).y=0 : inc q
for n=0 to array count(motif())-1
if getBit(a,n*2)=1
motif(n).invx=-1
else
motif(n).invx=1
endif
if getBit(a,n*2+1)=1
motif(n).invy=-1
else
motif(n).invy=1
endif
next n
endfunction
function preset4()
undim motif()
dim motif(7) as vec2
q as integer
q=0
motif(q).x=0
motif(q).y=0
motif(q).invx=1
motif(q).invy=-1 : inc q
motif(q).x=1/6.0
motif(q).y=.288675135
motif(q).invx=-1
motif(q).invy=1 : inc q
motif(q).x=1/3.0
motif(q).y=.288675135*2
motif(q).invx=-1
motif(q).invy=1 : inc q
motif(q).x=2/3.0
motif(q).y=.288675135*2
motif(q).invx=-1
motif(q).invy=1 : inc q
motif(q).x=5/6.0
motif(q).y=.288675135
motif(q).invx=-1
motif(q).invy=-1 : inc q
motif(q).x=1/3.0
motif(q).y=0
motif(q).invx=1
motif(q).invy=-1 : inc q
motif(q).x=2/3.0
motif(q).y=0
motif(q).invx=-1
motif(q).invy=1 : inc q
motif(q).x=1
motif(q).y=0
motif(q).invx=1
motif(q).invy=1 : inc q
endfunction
function getBit(a as integer, n as integer)
retvalue as integer
retvalue=(a>>n) && 1
endfunction retvalue
function drawThickDot(x1 as float, y1 as float, color as dword,graph)
units_to_pix(x1,y1,graph)
x1=ret.x
y1=ret.y
for a=-3 to 3
for b=-3 to 3
dot x1+a,y1+b,color
next b
next a
endfunction
`what we're drawing is a *curve*. This curve is an *estimation* of the fractal. You draw
`lines from one point, to the next, to the next, to the next. As such, the last point
`of one transformed motif should be the first point of the next. That's why the first
`point is omitted in the code. It should be at (0,0) anyways.
function fillFinalCurve(its as integer,cutoff as float)
cutoff=cutoff*cutoff
temp as vec2
dim tempArray(-1) as vec2
empty array finalCurve()
for n=0 to array count(base())
array insert at bottom finalCurve()
finalCurve(n)=base(n)
next n
currentIterate as integer
for currentIterate=1 to its `every iteration, bump the information from tempArr to finalCurve, and repeat.
anyNewGeometry as integer
anyNewGeometry=0
`Okay, so for every line segment in finalCurve(), we replace it with the series of line segments
`in motif(), taking into account inverting each one. We then store these line segments in tempArray(),
`then clear finalcurve(), set finalCurve to tempArray, and unlink/clear tempArray.
a as vec2
b as vec2
for n=0 to array count(finalCurve())-1
a=finalCurve(n)
b=finalCurve(n+1)
invx as integer
invy as integer
invx=a.invx
invy=a.invy `inversions are determined by the first point.
a1#=a.x-b.x
b1#=a.y-b.y
if a1#*a1#+b1#*b1#>cutoff `usually cutoff is used to determine if the point is visible or not.
`basically, if the distance between a and b squared is less than cutoff, then we don't create
`new geometry, and instead just copy what we have over.
anyNewGeometry=1
for q=0 to array count(motif())-1
qq=q
if invx=-1
qq=array count(motif())-q
temp.x=1-motif(qq).x
else
temp.x=motif(qq).x
endif
temp.y=motif(qq).y*invy
array insert at bottom tempArray()
transformPointToSegment(temp,a,b)
if invx=-1 then qq=qq-1
ret.invx=motif(qq).invx*invx
ret.invy=motif(qq).invy*invy
tempArray(array count(tempArray()))=ret
next q
else `if the geometry isn't visible/is less than "cutoff"
array insert at bottom tempArray()
tempArray(array count(tempArray()))=a
endif
if keystate(23)=1 then exitfunction
next n
array insert at bottom tempArray()
tempArray(array count(tempArray()))=base(array count(base()))
`^^the last point of the curve is the last point of the base
empty array finalCurve()
for n=0 to array count(tempArray())
array insert at bottom finalCurve()
finalCurve(n)=tempArray(n)
next n
empty array tempArray()
if anyNewGeometry=0 then goto _skip
next
_skip:
undim temparray()
endfunction
function setBaseHex()
undim base()
dim base(6) as vec2
base(0).x=0
base(0).y=0
base(1).x=.25
base(1).y=0.433012702
base(2).x=.75
base(2).y=0.433012702
base(3).x=1
base(3).y=0
base(4).x=.75
base(4).y=-0.433012702
base(5).x=.25
base(5).y=-0.433012702
base(6).x=0
base(6).y=0
for n=0 to 6
base(n).invx=1
base(n).invy=1
next n
endfunction
function setBaseBox()
empty array base()
array insert at bottom base()
array insert at bottom base()
array insert at bottom base()
array insert at bottom base()
array insert at bottom base()
base(0).x=-.5
base(0).y=-.5
base(4)=base(0)
base(1).x=-.5
base(1).y=.5
base(2).x=.5
base(2).y=.5
base(3).x=.5
base(3).y=-.5
for n=0 to 4
base(n).invx=1
base(n).invy=1
base(n).x=base(n).x/2.0+.5
base(n).y=base(n).y/2.0
next n
endfunction
function setBaseTriangle()
empty array base()
array insert at bottom base()
array insert at bottom base()
array insert at bottom base()
array insert at bottom base()
base(0).x=0
base(0).y=-0.288675134
base(3)=base(0)
base(1).x=.5
base(1).y=.5656893
base(2).x=1
base(2).y=-0.288675134
for n=0 to 3
base(n).invx=1
base(n).invy=1
next n
`approximately an equilateral triangle centered at (.5,0), with side length 1.
endfunction
function drawThickBorder(x1,y1,x2,y2,thickness,color as dword)
ink color,color
a=floor(-thickness/2.0)
b=floor(thickness/2.0)
for n=a to b
line x1,y1+n,x2,y1+n
line x1,y2+n,x2,y2+n
line x1+n,y1,x1+n,y2
line x2+n,y1,x2+n,y2
next n
endfunction
function removeBasePoint(n)
if n>0 and n<array count(base())
array delete element base(),n
endif
endfunction
function addBaseSegment(a,P as vec2) `add a point between index a and a+1.
array insert at element base(),a+1
base(a+1)=P
base(a+1).invx=1
base(a+1).invy=1
endfunction
function clearbase()`reset base to the unit segment
empty array base()
array insert at bottom base()
array insert at bottom base()
base(0).x=0
base(0).y=0
base(1).x=1
base(1).y=0
for n=0 to 1
base(0).invx=1
base(0).invy=1
next n
endfunction
function removeMotifPoint(n)
if n>0 and n<array count(motif())
array delete element motif(),n
endif
endfunction
function addMotifSegment(a,P as vec2) `add a point between index a and a+1.
array insert at element motif(),a+1
motif(a+1)=P
motif(a+1).invx=1
motif(a+1).invy=1
endfunction
function clearmotif()`reset mySequence to the unit segment
empty array motif()
array insert at bottom motif()
array insert at bottom motif()
motif(0).x=0
motif(0).y=0
motif(1).x=1
motif(1).y=0
for n=0 to 1
motif(n).invx=1
motif(n).invy=1
next n
endfunction
function drawLine(A as vec2, B as vec2, color as dword,graph)
units_to_pix(A.x,A.y,graph)
x1=ret.x
y1=ret.y
units_to_pix(B.x,B.y,graph)
x2=ret.x
y2=ret.y
ink color,color
`d3d_batch_add_line2d x1,y1,x2,y2
endfunction
function pix_to_units(x,y,graph)
ret.x=(x-graphs(graph).c.x)*1.0/graphs(graph).ppu
ret.y=-(y-graphs(graph).c.y)*1.0/graphs(graph).ppu
endfunction
function units_to_pix(x as float, y as float,graph)
ret.x=x*graphs(graph).ppu+graphs(graph).c.x
ret.y=-y*graphs(graph).ppu+graphs(graph).c.y
endfunction
function transformPointToSegment(pt as vec2, a as vec2, b as vec2)
`where R is a rotation matrix giving a rotation 90 degrees CCW, and A, B, and P are column vectors
`P'=(B-A)*P.x+R*(B-A)*p.y+A
`this transformation scales (P-B) and (P-A) by a factor of ||B-A||, and rotates P by atan2(B-A)
`easier expressed in matrix form by:
` [P.x -P.y]
`P=[P.y P.x]*(B-A) + A
ret.x=pt.x*(b.x-a.x)-pt.y*(b.y-a.y)+a.x
ret.y=pt.y*(b.x-a.x)+pt.x*(b.y-a.y)+a.y
endfunction
`remend
