De XBitmap Class

Inleiding

Opmerking:
Dit is versie 2 van de Xbitmap class.
De kleurenkiezer component is vervangen.
Fout onder Delphi-10 is verholpen.

De Xbitmap class voegt nieuwe mogelijkheden toe aan de Bitmap class:
    1. streep-stip lijnen met een pendikte van 1 tot 32 pixels
    2. lijnen met pijlpunten aan begin of einde (16 vormen selecteerbaar)
    3. 4 levels (0..3) diepte bij het tekenen
    4. zeer snelle xdot[x,y] property om punten te tekenen van de geselecteerde pendikte
    5. verbeterde stretchdraw method
    6. clipping rectangle
    7. direct access van pixels in het geheugen met de xpixel[ ] property
    8. floodfill stylen van 8 x 8 of 24 x 24 pixels, 16 stylen selecteerbaar
    9. modification rectangle : de rechthoek waarin tijdens de laatste tekenopdracht veranderingen optraden

Creation en pixelformat.

Zo maak je een XBitmap:
var myxbitmap : TXbitmap;
........
begin
 myxbitmap := TXbitmap.create;
 with myxbitmap do
  begin
   width := 600;
   height := 400;
  end;
.....
Gebruik het pixelformat property niet.
Xbitmap werkt alleen in de pf32bit mode, die automatisch wordt ingesteld met de width of height.

De extra opties van de XBitmap class zijn toegevoegd aan de Bitmap class, niet aan het canvas.

In de pf32bit pixelmode zijn de posities van blauw en rood in de 32 bit integer verwisseld t.o.v. het Windows format:
    Windows vs pf32bit color format
De volgende functie verwisselt het rode- en blauwe veld in een 32 bit integer:
function swapcolor(c : DWORD) : DWORD;
waarin c de kleur is.

Voor de xpencolor en xbrushcolor properties wordt het Windows format gebruikt.
De R en B kleurenvelden worden intern verwissled.
Bij xpixel[ , ] zijn de kleuren in het pf32bit format vanwege de snelheid.

XBitmap verandert pixels rechtstreeks in het geheugen.
Daarvoor wordt eenmalig de pointer naar pixels[0,0] bepaald en dan de pointer naar pixels[0,1]
om het verschil naar de volgende rij te bepalen.
Method xadjust bepaalt dit met de property scanline[ ], bij het instellen van breedte of hoogte.

Als een Xbitmap van een file wordt geladen :
with myxbitmap do
 begin
  loadfromfile(filename);
  xadjust; //restores the pf32bit property
  ...
 end; 
Na een loadfromfile moet xadjust worden aangeroepen om het pf32bit pixelformat en de pointers te herstellen.

Merk op: Pixels in een (x)bitmap bevinden zich in het werkgeheugen en zijn daarom niet zichtbaar.
Om een (x)bitmap zichtbaar te maken moet deze naar het canvas van bijvoorbeeld een paintbox worden gekopieerd.
Gebruik hiervoor de opdracht canvas.draw(x,y,sbm) om de gehele bitmap te kopieren of
canvas.copyrect(dr,scv,sr) method om een deel van de bitmap te kopieren, waarbij:
    x, y : screen coordinaten
    sbm : de source bitmap
    dr : destination rectangle
    scv : de source canvas
    sr : de source rectangle

1. streep - stip lijnen

Lijnen, cirkels en ellipsen kunnen getekend worden als streep - stipppellijnen.
De pendikte kan daarbij varieren van 1 tot 32 pixels.
De dikkere lijnen worden gewoonlijk toegepast voor bitmaps die later naar een printer canvas worden gekopieerd.
Als de printerresolutie horizontaal 2400 pixels bedraagt, dan komt dat neer of een verdrievoudiging van de pendikte.

De property xpenstyle selecteert het streep - stip patroon
    0 : solid
    1..19 dash-dot styles
Figure 1 toont de streep - stip patronen bij een pendikte van 3
    fig.1
Voorbeeld: teken een lijn met style 10, pendikte 3, van (20,40) naar (120,40):
 with myxbitmap do
  begin
   xpenwidth := 3;
   xpenstyle:= 10;
   xline(20,40,120,40);
   ......

2. Pijlen

Lijnen en bogen kunnen aan het begin of einde een pijl hebben.
Er zijn 16 verschillende pijlpunten: 4 breedtes en 4 lengtes gecombineerd.
Fig2. hieronder toont alle pijlpunten bij een pendikte van 2
    fig.2
Het type pijl (of geen pijl) staat in property xarrowcode: (zie fig. 3)
    fig.3
Bits 0,1 samen met de pendikte maken de breedte van een pijl.
Bits 2,3 samen met de pendikte maken de lengte van de pijl.

zie het voorbeeld hieronder
    with myxbitmap do
     begin
      xpenwidth := 5;
      xpenstyle := 11;
      xarrowcode := $cf;
      xline(10,40,400,40);
      .............
    
    

3. Levels (0..3)

Elk pixel heeft een level. Level 0 is het hoogste- , level 3 is het laagste level.
De properties xpenlevel en xbrushlevel zetten het level van de pen of de brush.
Regel is, dat een kleur met lager level nooit een pixel met hoger level kan overschrijven.
Het level is gecodeerd in bits 0,1 van de blauwe bits (0..7) , dus bits 0 en 1 van een pf32bit pixel geven het level aan.

Dit is een voorbeeld van het gebruik van kleurenlevels in een tekenprogramma:
    - 3: voor system achtergrond
    - 2: voor achtergrond, die door de gerbruiker is getekend
    - 1: voor rasters
    - 0: voor lijnen, ellipsen enz. die door de gebruiker zijn getekend.
Ook kan met de levels de dominantie van tekst en grafische informatie worden ingesteld.
Het voorbeeld hieronder toont een effect:
    with myxbitmap do
     begin
      xpenwidth := 10;
      xarrowcode := 0;
      xpenstyle := 0;
      xpenlevel := 0;
      xpencolor := $000000;//black
      xline(10,10,400,400);
      xpenlevel := 1;
      xpencolor := $0000ff;//red
      xline(10,400,400,10);
      xpenlevel := 2;
      xpencolor := $00ff00;//green
      xline(10,100,400,100);
      xpenlevel := 3;
      xpencolor := $ff0000;//blue
      xline(100,10,100,400);
      .............
    
De zwarte lijn is het eerst getekend met het hoogste level (0).
De andere kleuren hebben een lager level en kunnen de zwarte lijn dus niet overschrijven.

4. xdot(x,y) method voor snel tekenen van punten

xdot(x,y) tekent een punt op positie (x,y) met de geselecteerde kleur en pendikte.
Deze manier van tekenen is vele malen sneller dan bij gebruik van een ellips.
De figuur hieronder toont een paar punten:
with myxbitmap do
 begin
  xpenwidth := 10;
  xpencolor := $000000;//black
  xdot(40,40);
  xpencolor := $ff0000;//blue
  xpenwidth := 32;
  xdot(100,40);
  .............

5. Verbeterde stretchdraw method

De xstretchdraw method kopieert een source bitmap vergroot of verkleind.
xstretchdraw heeft twee modes:
    fullsource (xstretchmode = smFullSource)
    full destination (xstretchmode = smFullDest)
In fullsource mode wordt het beeld zo aangepast dat het geheel past in de destination rectangle.
Er gaat geen beeld verloren, maar een deel van de destination rectangle is mogelijk niet bedekt.
In full destination mode wordt de destination rectangle geheel bedekt, maar een deel van de
source rectangle wordt mogelijk niet afgebeeld.
var rs,rd : Trect;//source, dest rectangle;
      bm : Tbitmap;	//imported 500*350 
with myxbitmap do
 begin
 .....
  rd := rect(20,20,300,500);
  rs := rect(bm.left,bm.top,bm.width,bm.height);
  //full bitmap
  xstretchmode := smfullsource;
  xstretchrect(rd,bm,rs);
  rd := rect(320,20,600,500);
  xstretchmode := smfulldest;
  xstretchrect(rd,bm,rd);
  .............
links: fullsource, rechts: fulldest...

6. Clipping rectangle

Soms is het handig om het tekenen een lijn of cirkel te beperken tot een vooraf ingestelde rechthoek.
In the xbitmap class heet deze rechthoek xcliprect (type Trect).
Een niet ingestelde xcliprect is zo groot als de gehele bitmap.
Tekenen buiten de xcliprect is niet mogelijk.
Het plaatje hieronder toont een mogelijk effect:
with myxbitmap do
 begin
 .....
  xcliprect := rect(20,20,250,250);
  xpenwidth := 20;
  xpencolor := $000000;
  xline(20,20,400,300);
  xpencolor := $0000ff;
  xellipse(0,100,320,240);
  .............
clipping rectangle example...

7. Snel tekenen van pixels met xpixel[ ]

Het bitmap canvas kent de pixels[x,y] property om individuele pixels te lezen of te schrijven.
Maar dit is een zeer traag proces omdat Windows wordt aangeroepen.
De xpixel[x,y] property is minstens 40 keer sneller, omdat een pixel direct in het geheugen wordt geadresseerd.
Het pf32bit pixelformat wordt gebruikt, dus is soms conversie nodig van of naar het Windows formaat.
Gebruik hiervoor de functie swapcolor(c : DWORD) : DWORD;

8. floodfill stijlen van 8 x 8 of 24 x 24 pixels, 16 stijlen mogelijk

xfloodfill(x,y) vult een gebied met een patroon.
Het gebied moet begrensd zijn door een kleur met level 0.
Hieronder staan de mogelijke patronen
property xfillstyle : byte;//0..15
selecteert het patroon.
xfillmapsize : Txfillmapsize;//selects fms8 or fms24 
selecteert de grootte van een patroon tegeltje.
Gebruik fms8 voor het beeldscherm en fms24 als de bitmap voor een printer canvas bestemd is.

9. modification rectangle.

Bij het tekenen van een lijn, ellips of boog... wordt een beperkt gedeelte van de bitmap gewijzigd.
Om de wijziging zichtbaar te maken hoeft alleen dit gewijzigde gedeelte maar naar een paintbox te worden gekopieerd.
Xmodrect is de rectangle waarbinnen wijzigingen optraden bij de laatste tekenaktie.
Xmodrect is de minimale rectangle die naar de paintbox gekopieerd moet worden.

Soms moeten de rechthoeken van verschillende tekenakties worden samengevoegd.
Gebruik hiervoor de functie unirect:
  r := unirect(r,xmodrect);//combines r and xmodrect
Andere functies voor bewerkingen met rectangles
  function InterRect(var r1,r2 : Trect) : Trect;//common part of rectangles
  function PackRect(x1,y1,x2,y2 : integer) : Trect;//coordinates to rectangle

type definities in Xbitmap

type  PDW = ^DWORD;
      TXFillMapSize = (fms8,fms24);
      TXstretchmode = (smFullSource,smFullDest);

methods in Xbitmap

  Xpixel[x:integer; y:integer]:DWORD;
  XPixPos[x:integer;y:integer]:DWORD;
  Xdot(x,y : integer);
  Xline(x1,y1,x2,y2 : integer);
  Xellipse(x1,y1,x2,y2 : integer);
  Xarc(x1,y1,x2,y2,x3,y3,x4,y4 : integer);
  Xpolygon(var pa : array of Tpoint);
  XfillRect(x1,y1,x2,y2 : integer; r : byte);
  Xfloodfill(x1,y1 : integer);
  XstretchRect(drt : Trect; sbm : TXBitmap;srt : Trect);
  XAdjust;
XpixPos[x,y] leest de pointer naar de locatie van een pixel.

XfillRect tekent een rechthoek met afgeronde hoekpunten met straal r (r=0 voor rechte hoeken) en achtergrondkleur.

properties in Xbitmap

   XpenWidth : byte;
   Xpencolor : DWORD;
   XLineStyle : byte;
   Xbrushcolor : DWORD;
   Xpenlevel : byte;
   Xbrushlevel : byte;
   XFillMapSize : TXFillMapsize;
   XfillStyle : byte;
   XarrowCode : byte;
   XClipRect : Trect;
   XUseBrush : boolean;
   Xstretchmode : TXstretchmode;
   XModRect : Trect;
Xusebrush is true tekent de achtergrondkleur in rechthoeken en ellipsen.

Het Xbitmap project

De programmeertaal is Delphi-3.
Maar de XBitmap class past in elke Delphi versie.
Het project heeft de volgende units:
    unit1: Exerciser. Event trapping, knoppen.
    controlunit: settings,selections, event handling
    xbitmap :de XBitmap class, type definitions en de support procedures
Met de exerciser kunnen de mogelijkheden van de XBitmap class worden getest.
De knoppen behoeven geen toelichting.
Opmerkingen:
1.
De vorm van een veelhoek kan worden veranderd door de muispijl boven een hoekpunt te zetten,
de muisknop in de drukken en het hoekpunt met de muis te verschuiven.
Houd de "shift key" ingedrukt voor positionering per pixel in plaats van stappen van 10 pixels.

2.
De exerciser tekent een afbeelding in het xcliprect. Teken dus eerst het xcliprect voor de afbeelding.
Het xcliprect kan worden veranderd door de muispijl boven een hoekpunt te zetten, zoals bij 1.

eigen componenten

De exerciser gebruikt twee van mijn eigen componenten:
    - davArrayBtn (een array of buttons)
    - colorpicker (een grid met kleurenselectie)

Downloads

Klik hieronder voor het downloaden van: