Re: Drawing Pixels with NSBezierPath
Re: Drawing Pixels with NSBezierPath
- Subject: Re: Drawing Pixels with NSBezierPath
- From: "b.bum" <email@hidden>
- Date: Sun, 4 Jul 2004 00:38:50 -0700
On Jul 3, 2004, at 11:48 PM, Chris Hanson wrote:
Hi all. The program I am writing requires a view to be drawn with
every pixel being a different color.
If you need pixels, you should be using an NSBitmapImageRep for your
drawing rather than an NSBezierPath. This will let you work directly
with a pixel buffer you can manipulate and then draw to the screen.
Chris is absolutely correct, but there is another alternative that may
prove to more appropriate and/or efficient, depending on needs. You
will find that repeatedly drawing into a bitmap and subsequently
compositing to the screen is actually quite slow.
NSRectFillList() with 1x1 rects is extremely efficient at getting lists
of pixels to the screen. I would suggest that you reorder the pixels
by color -- to some degree -- prior to passing to NSRectFillList() as
it will be more efficient than the variant that takes an array of
colors.
There are likely even more efficient variants in CoreGraphics and via
Open GL. I haven't had the need to explore such optimizations.
b.bum
From a post I sent earlier in the year:
The drawing code (I use an NSBitmapImageRep to cache the previous
iterations. Once rendered once, the rendering is captured into an
NSBIR):
def drawRect_(self, aRect):
if self.backingStore:
self.backingStore.draw()
else:
self.eraseView_(aRect)
for pointArray, rectCount, color in self.pointsCountsAndColors:
color.set()
NSRectFillList(pointArray, len(pointArray) / 4)
self.pointsCountsAndColors = []
self.backingStore =
NSBitmapImageRep.alloc().initWithFocusedViewRect_(self.bounds())
Where pointArray is filled by:
def hopalong(a=30.0, b=1.0, c=0.9, iterations=1000000, numColors=1000,
scale=10.0, xoffset=150, yoffset=150):
x = 0.0
y = 0.0
colors = genColors(numColors)
colorIter = iterations / len(colors)
while 1:
for i in range(len(colors)):
points = array.array('f', [0.0,0.0,1.0,1.0] * colorIter)
for j in range(colorIter):
if x < 0:
temp = y + math.sqrt(abs(b * x - c))
else:
temp = y - math.sqrt(abs(b * x - c))
y = a - x
x = temp
points[j*4] = xoffset + (scale * x)
points[(j*4) + 1] = yoffset + (scale * y)
yield (colors[i], points)
Specifically, this line:
points = array.array('f', [0.0,0.0,1.0,1.0] * colorIter)
Creates an array of floating point numbers with the pattern
[0,0,1,1,0,0,1,1,0,0,1,1]. colorIter is just the number of points
that should be rendered in the current color. Since NSRectFillList()
takes an array of NSRect structures as an NSRect*, you can effectively
just create a an array of floats and initialize 'em in linear, 4 float
chunks where each set of 4 floats is one rectangle.
In the above case, I create the array of 1x1 rects all located at 0,0
and then walk the array and set the x,y coord of each individual rect:
points[j*4] = xoffset + (scale * x)
points[(j*4) + 1] = yoffset + (scale * y)
Translation to ObjC is left as an exercise to the reader. Another
excercise, yield() is very cool. Very, very cool. The same can sort
of be done with enumerators, but not quite.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.