
FB II Compiler
PG PRO
Debugging
Memory
System
Mathematics
Resources
Disk I/O
Windows
Controls
Menus
Mouse
Keyboard
Text
Fonts
Drawing
Sound
Clipboard
Printing
Communication
ASM
|
DRAWING
Average overlapping colours
The following code uses regions to separate the overlapping and non-overlapping parts of the circles, and unsigned arithmetic to get an average RGB colour for the overlapping region.
COMPILE ,_dimmedvarsOnly
LOCAL FN RGBAverage(src1RGBPtr&,src2RGBPtr&,destRGBPtr&)
DIM red1&,green1&,blue1&,red2&,green2&,blue2&
red1&=src1RGBPtr&.0%
green1&=src1RGBPtr&.2%
blue1&=src1RGBPtr&.4%
red2&=src2RGBPtr&.0%
green2&=src2RGBPtr&.2%
blue2&=src2RGBPtr&.4%
IF red1&<0 THEN red1&=red1&+65536' unsigned
IF green1&<0 THEN green1&=green1&+65536
IF blue1&<0 THEN blue1&=blue1&+65536
IF red2&<0 THEN red2&=red2&+65536
IF green2&<0 THEN green2&=green2&+65536
IF blue2&<0 THEN blue2&=blue2&+65536
destRGBPtr&.0%=(red1&+red2&)>>1' average
destRGBPtr&.2%=(green1&+green2&)>>1
destRGBPtr&.4%=(blue1&+blue2&)>>1
END FN
LOCAL FN OverlapOvals(rect1Ptr&,rgb1Ptr&,rect2Ptr&,rgb2Ptr&)
DIM rgn1&,rgn2&,olapRgn&,avgRGB.6
rgn1&=FN NEWRGN
rgn2&=FN NEWRGN
olapRgn&=FN NEWRGN
CALL OPENRGN
CALL FRAMEOVAL(#rect1Ptr&) ' oval 1
CALL CLOSERGN(rgn1&)
CALL OPENRGN
CALL FRAMEOVAL(#rect2Ptr&) ' oval 2
CALL CLOSERGN(rgn2&)
CALL SECTRGN(rgn1&,rgn2&,olapRgn&)' the overlap
CALL DIFFRGN(rgn1&,olapRgn&,rgn1&)' remove overlap
CALL DIFFRGN(rgn2&,olapRgn&,rgn2&)' remove overlap
CALL RGBFORECOLOR(#rgb1Ptr&)
CALL PAINTRGN(rgn1&) ' oval 1
CALL RGBFORECOLOR(#rgb2Ptr&)
CALL PAINTRGN(rgn2&) ' oval 2
FN RGBAverage(rgb1Ptr&,rgb2Ptr&,@avgRGB)
CALL RGBFORECOLOR(avgRGB)
CALL PAINTRGN(olapRgn&) ' overlap
CALL DISPOSERGN(rgn1&)
CALL DISPOSERGN(rgn2&)
CALL DISPOSERGN(olapRgn&)
END FN
LOCAL FN RandomRGB(destRGBPtr&)
destRGBPtr&.red%=RND(255)*256
destRGBPtr&.green%=RND(255)*256
destRGBPtr&.blue%=RND(255)*256
END FN
DIM rect1.8, rect2.8, myRGB1.6, myRGB2.6, x,y
RANDOMIZE TIMER
WINDOW 1,"Overlap",(0,0)-(630,430)
CALL SETRECT(rect1,10,10,90,90)
CALL SETRECT(rect2,50,10,130,90)
FOR x=0 TO 450 STEP 150
FOR y=0 TO 300 STEP 150
FN RandomRGB(@myRGB1)
FN RandomRGB(@myRGB2)
CALL SETORIGIN(-x,-y)
FN OverlapOvals(@rect1,@myRGB1,@rect2,@myRGB2)
NEXT
NEXT
CALL SETORIGIN(0,0) ' restore QuickDraw origin
DO
HANDLEEVENTS
UNTIL FN BUTTON
Robert Purves
Don't know if this is what you're looking for, but...
'================
CLEAR LOCAL FN drawCircles
DIM cirColor.rgbColor
cirColor.Red = 65535
cirColor.Green = 40000
cirColor.Blue = 40000
'
PEN ,,,_adMin
'Note that there are other pen settings
'that will effect how the colors turn out,
'here's a couple...
'_subPin
'_subOver
CALL RGBFORECOLOR(#@cirColor)
CIRCLE FILL 100,100,50
cirColor.Red = 40000
cirColor.Green = 40000
cirColor.Blue = 65535
CALL RGBFORECOLOR(#@cirColor)
CIRCLE FILL 150,150,50
CALL PENNORMAL
END FN
WINDOW 1
FN drawCircles
DO
HANDLEEVENTS
UNTIL 0
'================
Al Boyd
These are 2 routines from one of my programs that blends 2 colo(u)rs where 2 colo(u)red regions overlap.
CLEAR LOCAL
LOCAL FN AvgRGB(red&, green&, blue&, rgbRed&, rgbGreen&, rgbBlue&)
DIM redRGB, greenRGB, blueRGB
redRGB = red&
greenRGB = green&
blueRGB = blue&
LONG IF redRGB + greenRGB + blueRGB = 0
%rgbRed&,13500
%rgbGreen&,13500
%rgbBlue&,13500
XELSE
%rgbRed&,redRGB
%rgbGreen&,greenRGB
%rgbBlue&,blueRGB
END IF
END FN
CLEAR LOCAL
LOCAL FN AvgPaintRgn(face1, rgn1H&, face2, rgn2H&)
DIM red&, green&, blue&, rgbRed, rgbGreen, rgbBlue, rgnH&
DIM red1&, red2&, green1&, green2&, blue1&, blue2&
rgnH& = FN NEWRGN
CALL SECTRGN(rgn1H&, rgn2H&, rgnH&)
red1& = VAL(UNS$(gColor.red%(face1))) : red2& = VAL(UNS$(gColor.red%(face2)))
red& = (red1& + red2&) / 2&
green1& = VAL(UNS$(gColor.green%(face1))) : green2& VAL(UNS$(gColor.green%(face2)))
green& = (green1& + green2&) / 2&
blue1& = VAL(UNS$(gColor.blue%(face1))) : blue2& VAL(UNS$(gColor.blue%(face2)))
blue& = (blue1& + blue2&) / 2&
FN AvgRGB(red&, green&, blue&, @rgbRed, @rgbGreen, @rgbBlue)
LONG COLOR rgbBlue, rgbGreen, rgbRed
CALL PAINTRGN(rgnH&)
DEF DISPOSEH(rgnH&)
END FN
Charlie Dickman
Here is my slow attempt to mix the colours:
DIM color1.RGBColor
DIM color2.RGBColor
END GLOBALS
CLEAR LOCAL
LOCAL FN initColors
color1.red% = 65535 : color1.green% = 0 : color1.blue% = 0
color2.red% = 65535 : color2.green% = 65535 : color2.blue% = 0
END FN
CLEAR LOCAL
LOCAL FN drawRects
dim h,v
DIM togglingflag,thecolor
DIM myRect1.8
DIM myRect2.8
DIM myRect3.8
CALL SETRECT(myRect1,20,20,100,100)
CALL SETRECT(myRect2,50,20,130,100)
CALL SETRECT(myRect3,50,20,100,100)
CALL RGBFORECOLOR(#@color1) : CALL PAINTRECT(myRect1)
CALL RGBFORECOLOR(#@color2) : CALL PAINTRECT(myRect2)
FOR h = myRect3.left% TO myRect3.right%
togglingflag = NOT(togglingflag)
FOR v = myRect3.top% TO myRect3.bottom%
LONG IF v MOD 2
IF togglingflag THEN thecolor = 1 ELSE thecolor = 2
XELSE
IF togglingflag THEN thecolor = 2 ELSE thecolor = 1
END IF
IF thecolor = 1 THEN CALL SETCPIXEL(h,v,#@color1) ELSE CALL SETCPIXEL(h,v,#@color2)
NEXT
NEXT
END FN
WINDOW 1
FN initColors
FN drawRects
DO
UNTIL FN BUTTON OR LEN(INKEY$)
Alain
Phil Yates asked how to colour the overlapping area of two circles.
The suggestion to use: PEN ,,,_adMin or other constants seems to change the orginal colours too as it combines the existing colour with the new one.
Here's an short example of a function to draw a circle and create a region for it. Then the region handles can be used to calculate the interseting area and simple averaging can determine the colour used to paint the overlapping region. See pages 297-299 in the FBII Handbook for more info re regions and their commands. - Powerful stuff.
'==================
LOCAL FN drawCircle( h,v, r )
DIM rect;8
CALL SETRECT( rect, h-r,v-r, h+r,v+r )
rgn& = FN NEWRGN
LONG IF rgn&
CALL OPENRGN
CALL FRAMEOVAL( rect )
CALL CLOSERGN( rgn& )
END IF
CALL PAINTRGN( rgn& )
END FN = rgn&
'==================
WINDOW 1
DIM c1&, c2&, overlap&
' use your own colours
red1=64000: green1=00000: blue1=00000 ' pure red
red2=00000: green2=00000: blue2=64000 ' pure blue
red3 = (red1+red2)/2 ' calc the average colour
green3 = (green1+green2)/2
blue3 = (blue1+blue2)/2
LONG COLOR blue1,green1,red1
c1& = FN drawCircle( 100,150, 50 )
DELAY 1000
LONG COLOR blue2,green2,red2
c2& = FN drawCircle( 90,100, 70 )
DELAY 1000
overlap& = FN NEWRGN ' note - need to create a region for next instruction.
CALL SECTRGN( c1&, c2&, overlap& )
LONG COLOR blue3,green3,red3
CALL PAINTRGN( overlap& )
DELAY 1000
DO
HANDLEEVENTS
UNTIL 0
'==================
Stu
It's been a long time since I did this but here goes:
There are other color modes in the Mac than just RGB, HSB for example. There are also easy toolbox calls to convert to and from!
In a similar situation i converted to HSB (Hue, Saturation, Brilliance) and averaged only the hue value, keeping Saturation and brilliance at the same levels, then converted back to RGB for display. It gave satisfactory effects.
Jonathan
I've recently started lurking on the FB listserve. I'm not much of a programmer so I'm not likely to contribute much. As a graduate student in cognitive psychology I do know a little bit about color perception.
Color averaging is a little bit tricky. Before you can figure out the algorithm for averaging, you need to decide what the result should look like. If one circle were fully saturated bright red and the other fully saturated bright green do you want the overlap to be dark brown or yellow. Brown (red = 32767, green = 32767, blue = 0) is what you would get if you mixed paints. Yellow (red = 65535, green = 65535, blue = 0) is what you would get if you shown a red and a green spot light together on a white surface.
Leaving aside the matter of mixing light for the moment, think about a standard color wheel which has the full range of bright, saturated hues around the edge with those hues becoming less saturated ("muddier") toward the center of the circle. Gray is at the center. Suppose you wanted to mix two colors on the rim of the color wheel. They are both bright and saturated. Do you want to find the mid-point between those two colors by moving to the mid-point on the rim of the circle (averaging the hues and retaining brightness and saturation) or do you want to find the midpoint of the straight line that connects the two points (averaging hue, reducing saturation, and leaving brightness unchanged). Averaging RGB values will give you a third result: average hues, reduced brightness, and saturation unchanged.
Averaging RGB values may give you exactly what you want. However, I suggest you test the results with the range of mixtures you are likely to use and make sure you are satisfied. You may be looking for a different effect such as averaging hue, saturation, and brightness (which are the dimensions of psychological "color space").
Chuck Schreiber
|