From: "Samson Fu" Newsgroups: borland.public.delphi.graphics References: <3b0de118$1_1@dnews> <3b0f28e6_2@dnews> Subject: Re: Xor 2 Bitmap. Date: Mon, 28 May 2001 11:26:52 +0800 Lines: 171 X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 5.50.4522.1200 X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4522.1200 NNTP-Posting-Host: 202.69.84.215 Message-ID: <3b11c61e_2@dnews> X-Trace: dnews 991020574 202.69.84.215 (27 May 2001 20:29:34 -0700) Path: dnews Xref: dnews borland.public.delphi.graphics:39239 Thank you! Thank you!! It 8 times faster than Bitblt for Intel CPU. Thank you again! Samson Fu "Matthijs Laan" wrote in message news:Xns90ADB8436752Dmatthijs@127.0.0.1... > According to Samson Fu, > > > "Matthijs Laan" wrote in message > > news:Xns90AC7A1978F4Bmatthijs@127.0.0.1... > >> According to Samson Fu, > >> > >> > I want to Xor 2 Tbitmaps (BMP1 and BMP2), and save the result to > >> > BMP3. It Bitblt the only choice? > >> > > >> > If I use Bitblt, I have to copy BMP1 to BMP3 first and Bitblt BMP2 > >> > and BMP3. (As Bitblt 2 Bitmaps). > > > I want to use it for any pixelformat. Can you kindly give me example to > > use MMX for this case? > > Please don't top-post, thank you. > > Here it is. I haven't done any speed testing, though. > > The formatting might look a little strange, but the general idea is 8 space > TABs. Assembler, you know ;-) > > procedure mmx_xor_bytes(P1, P2, P3: Pointer; bytes: Integer); register; assembler; > { P1 eax > P2 edx > P3 ecx > bytes [ebp+8] } > asm > push ebx > push esi > push edi > mov edi, ecx > mov esi, eax > mov ecx, [ebp+8] > test ecx, ecx > jz @Quit > and ecx, 4294967288 // ecx := bytes - (bytes mod 8) > jz @NoQWORDs > add edx, ecx // Move pointers to the end minus (bytes mod 8) > add esi, ecx > add edi, ecx > shr ecx, 3 // ecx := bytes div 8 (the amount of QWORDs to process) > neg ecx // [Pointer + ecx * 8] now points to the start > @LoopQWORDs: > db $0F,$6F,$04,$CE /// movq mm0, qword ptr [esi + ecx * 8] > db $0F,$EF,$04,$CA /// pxor mm0, qword ptr [edx + ecx * 8] > db $0F,$7F,$04,$CF /// movq qword ptr [edi + ecx * 8], mm0 > inc ecx > jnz @LoopQWORDs > @NoQWORDs: > mov ecx, [ebp+8] > and ecx, $7 // ecx = bytes mod 8 > jz @Quit > xor ebx, ebx > @LoopBYTEs: > mov al, [esi + ebx] // Process the remaining bytes > xor al, [edx + ebx] > mov [edi + ebx], al > inc ebx > cmp ebx, ecx > jnz @LoopBYTEs > @Quit: > pop edi > pop esi > pop ebx > end; > > procedure EMMS; assembler; > asm > db $0F,$77 /// emms > end; > > procedure mmx_xor_bitmaps(Source1, Source2, Dest: TBitmap); > { Probably garbles 16th bit (pf15bit) or 4th byte (pf32bit) } > var bpp, bits, bytes, y: Integer; > begin > if (Source1.Width <> Source2.Width) or (Source1.Height <> Source2.Height) then > raise Exception.Create('mmx_xor_bitmaps: Source bitmaps are not the same size'); > > if Source1.PixelFormat <> Source2.PixelFormat then > raise Exception.Create('mmx_xor_bitmaps: Source bitmaps pixelformats different'); > > case Source1.PixelFormat of > // These behave differently than Windows, > // don't know how exactly how/why > pf1bit: bpp := 1; > pf4bit: bpp := 4; > pf8bit: bpp := 8; > > // These should be the same as Windows > pf15bit: bpp := 16; // They're aligned on WORDs anyway > pf16bit: bpp := 16; > pf24bit: bpp := 24; > pf32bit: bpp := 32; > else > raise Exception.Create('mmx_xor_bitmaps: Pixelformat not supported'); > end; > > bits := Source1.Width * bpp; > bytes := bits div 8; > // if bits mod 8 <> 0 then Inc(bytes); // Hmm... > > Dest.Width := Source1.Width; > Dest.Height := Source1.Height; > Dest.PixelFormat := Source1.PixelFormat; > > Source1.HandleType := bmDIB; // This could be changed back later > Source2.HandleType := bmDIB; > Dest.HandleType := bmDIB; > > for y := 0 to Source1.Height - 1 do > mmx_xor_bytes(Source1.ScanLine[y], Source2.ScanLine[y], Dest.ScanLine[y], bytes); > > EMMS; > end; > > For testing, make a form with 4 TImages, and load two different bitmaps > in Image1 and Image2. Drop another button on the form; and make this the > OnClick handler: > > procedure TForm1.Button1Click(Sender: TObject); > var R: TRect; > var j, k, l: word; > begin > Image1.Picture.Bitmap.PixelFormat := pf32bit; > Image2.Picture.Bitmap.PixelFormat := pf32bit; > R := Rect(0,0,Image1.Picture.Bitmap.Width,Image1.Picture.Bitmap.Height); > Image3.Picture.Bitmap.Canvas.FillRect(R); > Image4.Picture.Bitmap.Canvas.FillRect(R); > Image3.Repaint; > Image4.Repaint; > mmx_xor_bitmaps(Image1.Picture.Bitmap, Image2.Picture.Bitmap, Image3.Picture.Bitmap); > Image3.Repaint; > Image4.Repaint; > Image4.Picture.Bitmap.Width := Image1.Picture.Bitmap.Width; > Image4.Picture.Bitmap.Height := Image1.Picture.Bitmap.Height; > Image4.Picture.Bitmap.PixelFormat := pf32bit; > Image4.Picture.Bitmap.Canvas.Draw(0,0,Image1.Picture.Bitmap); > Image4.Picture.Bitmap.Canvas.CopyMode := cmSrcInvert; > Image4.Picture.Bitmap.Canvas.CopyRect(R, Image2.Picture.Bitmap.Canvas, R); > Image4.Picture.Bitmap.Canvas.CopyMode := cmSrcInvert; > Image4.Picture.Bitmap.Canvas.CopyMode := cmSrcCopy; > Image3.Repaint; > Image4.Repaint; > end; > > Hope this helps, > > Matthijs