From: "Danny Thorpe" Newsgroups: borland.public.delphi.graphics References: <3f426cc3@newsgroups.borland.com> Subject: Re: Bilinear Interpolation +Scanline Date: Tue, 19 Aug 2003 14:29:18 -0700 Lines: 102 Organization: Borland Software Corp X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2800.1158 X-MIMEOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 NNTP-Posting-Host: 10.143.11.236 Message-ID: <3f429630$1@newsgroups.borland.com> X-Trace: newsgroups.borland.com 1061328432 10.143.11.236 (19 Aug 2003 14:27:12 -0700) Path: newsgroups.borland.com!not-for-mail Xref: newsgroups.borland.com borland.public.delphi.graphics:60585 "Josh Samuels" wrote in message news:3f426cc3@newsgroups.borland.com... > Is there any quicker method of doing Bilinear Interpolation with Bitmap > Scanline, my method seems a little slow, need it faster... > You've got a lot of floating point code and memory access that is repeated in each pixel calculation. Use a pixel pointer instead of recalculating and refetching from the array over and over again. Something like this: north := @row2[x]; west := @row3[round(x-flInterpDist)]; east := @row3[round(x+flInterpDist)]; south := @row4[x]; rgbtred := round( (north.rgbtred + west.rgbtred + east.rgbtred + south.rgbtred)/4); rgbtgreen := round( (north.rgbtgreen + west.rgbtgreen + east.rgbtgreen + south.rgbtgreen)/4); rgbtblue := round( (north.rgbtblue + west.rgbtblue + east.rgbtblue + south.rgbtblue)/4); Consider carefully whether you really need floating point division for these calculations. Since you're immediately rounding the result back to an integer, it would appear that integer division would suffice, and that would be about 20 times faster than floating point division. If you really need the result rounded up, then add 3 before dividing: north := @row2[x]; west := @row3[round(x-flInterpDist)]; east := @row3[round(x+flInterpDist)]; south := @row4[x]; rgbtred := (north.rgbtred + west.rgbtred + east.rgbtred + south.rgbtred + 3) div 4; rgbtgreen := (north.rgbtgreen + west.rgbtgreen + east.rgbtgreen + south.rgbtgreen + 3) div 4; rgbtblue := (north.rgbtblue + west.rgbtblue + east.rgbtblue + south.rgbtblue + 3) div 4; Since flInterpDist will be constant for a given interpolation operation, the distance between the north,south,east, and west pointers will be constant as well. You could do the whole thing with one pointer and integer offsets: Outside of the interpolation loop: (untested: signs might be backwards) northoffs = Integer(@row3[x]) - Integer(@row2[x]); southoffs = Integer(@row3[x]) - Integer(@row4[x]); westoffs = Integer(@row3[x]) - Integer(@row3[round(x-flInterpDist)]); eastoffs = Integer(@row3[x]) - Integer(@row3[round(x+flInterpDist)]); pixelspacing = Integer(@row3[2]) - Integer(@row3[1]); Inside the interpolation loop: for x := 1 to scanlines do begin p = @row[x]; while p < endofscanline do begin rgbtred := (PRGB(p + northoffs).rgbtred + PRGB(p + westoffs).rgbtred + PRGB(p + eastoffs).rgbtred + PRGB(p + southoffs).rgbtred + 3) div 4; { etc ... } Inc(Integer(p), pixelspacing); end; end; This would be particularly effective if the offsets were known constants at compile time. Or, just keep the four pointers and increment them all by pixelspacing to eliminate the array index calculation while traversing each scanline. You should also try to avoid calling bitmap.scanline[] as much as possible, because the scanline property has to flush the GDI pipeline to ensure that any outstanding GDI operations are finished before returning the pixel pointer to you. That's not cheap. The best way to iterate over the scanlines of a bitmap is to calculate the difference between the start of two scanlines: scanlineIncrement := bitmap.scanlines[1] - bitmap.scanlines[0]; You can then start a byte pointer P := bitmap.scanlines[0]; and move to the next scanline by incrementing P: Inc(P, scanlineIncrement); The beauty of this technique is that it takes all the variations in bitmap memory layout into account in one trivial subtration: scanlineIncrement takes into account interpixel padding, interscanline padding, and top-down or bottom-up bitmap memory layouts. -Danny