On Wednesday, October 9, 2002, at 06:24 PM, Russ Pagel wrote: > > From the standpoint of speed I've always changed loops like this to > move > math out of loops whenever possible. > > You can move the "baseAddr1 + (yy * myRowBytes1)" part out of the xx > loop so it'll only do the math once when yy changes. Also just to be > picky the "left = 0" is getting executed every time through the yy loop > as well. > > The following should be somewhat faster for the 8 bit version > > left = 0 // Execute once only > FOR yy=0 TO pictRect.bottom - 1 > myOffset=baseAddr1 + (yy * myRowBytes1) // Execute only when yy > changes > FOR xx=0 TO pictRect.right - 1 > Pixel1 = myOffset + (xx*4) // Yep, that is a pixel. > long if Pixel1.1`` = rA and Pixel1.2`` = gA and Pixel1.3`` = bA > Pixel1.1`` = rB > Pixel2.2`` = gB > Pixel3.3`` = bB > end if > NEXT xx > NEXT yy > > Maybe someone else can answer: Could the "long if" compare function > above be made faster by somehow loading Pixel1 as a long, ANDing off > the > last byte and doing a single compare (if) to a long constant? Yes, you can do just that, as illustrated below. This squeezes a few more nanoseconds by 'strength reduction' (no multiplications in the loops, only additions/subtractions), and by using register variables for the inner loop. '----------------- register on // return handle to new picture, with color change for each pixel // whose RGB components are identical with the special color 'seek' local mode local fn ColorizePictH( pictH as ^^Picture, seek as ^RGBColor,¬ repl as ^RGBColor ) // next 5 vars are register in PPC dim as long x, y, seekPixel, replPixel dim as Ptr addr dim as long rowBytes dim as Ptr rowAddr, tempGW, @ currGW dim as Rect r dim as Handle @ currDev, pictH2 dim pmHandle as ^^PixMap dim as OSErr err pictH2 = _nil // default if error long if pictH r = pictH..picFrame OffsetRect( r, -r.left, -r.top ) // make a GWorld, the same size as the picture err = fn NewGWorld( tempGW, 32, r, 0, 0, 0 ) long if ( err == _noErr ) GetGWorld( currGW, currDev ) // save current SetGWorld( tempGW, 0 ) picture , pictH // draw in GWorld pmHandle = fn GetGWorldPixMap( tempGW ) rowBytes = pmHandle..rowBytes and 0x3fff rowAddr = fn GetPixbaseAddr( pmHandle ) // construct 32-bit pixels from RGBColors seekPixel = ((seek.red and 0xff00) << 8) + ¬ (seek.green and 0xff00) + (seek.blue >> 8) replPixel = ((repl.red and 0xff00) << 8) + ¬ (repl.green and 0xff00) + (repl.blue >> 8) // test each pixel y = r.bottom - 1 while ( y ) addr = rowAddr x = r.right - 1 while ( x ) if ( addr.nil& == seekPixel ) then addr.nil& = replPixel x-- addr += 4 wend rowAddr += rowBytes y-- wend pictH2 = usr GetPict( r ) // make new picture SetGWorld( currGW, currDev ) // restore DisposeGWorld( tempGW ) // prevent memory leak end if end if end fn = pictH2 // Main program '~'1 dim as Handle pictH, pictH2 dim as Rect r dim as RGBColor seekRGB, replaceRGB dim as long j SetRect( r, 0, 0, 600, 400 ) window 1, "Color Convert", @r, _docNoGrow text _geneva, 24 picture on // make demo picture EraseRect( r ) pen 2, 2 for j = 1 to 50 if maybe then color _zRed else color _zBlack plot rnd( r.right ), rnd( r.bottom ) to rnd( r.right ), rnd( r.bottom ) next print @(1,1) "Click mouse to convert black to blue" picture off , pictH picture , pictH do HandleEvents until fn Button // seek color black seekRGB.red = 0 seekRGB.green = 0 seekRGB.blue = 0 // replacement color blue replaceRGB.red = 0 replaceRGB.green = 20000 replaceRGB.blue = 65535 pictH2 = fn ColorizePictH( pictH, seekRGB, replaceRGB ) long if ( pictH2 ) picture , pictH2 // draw new picture xelse stop "ColorizePictH failed" end if do HandleEvents until 0 '----------------- Robert P.