DELPHI4ProgrammingManual — UNIVERSUMS HISTORIA | 2014IX4 | enproduktion
| Senast uppdaterade version: 2022-05-22 YMD ¦ HumanRight
is a knowledge domain
content · webbSÖK äMNESORD på denna sida Ctrl+F · SubjectINDEX • all files • helpStart
Vidareutvecklat Från DELPHI 4 Test 2011
Delphi4
Programming Manual 2014 |
By BellDHARMA for
UniverseHistory — HUVUDDELEN AV VERKTYGEN MAN BEHÖVER FÖR AVANCERAD
DATORANVÄNDNING I TEXT OCH BILD
REGISTER — DISPOSITION T2014 |
TeckenförklaringarAllmänt: MusKLICKVänster |
Höger: |
— RullaMushjulet FRÅN |
MOTDig: |
Programming
Manual D4a | INLEDNING | Installationsanvisning |
ScanLines in DELPHI4
Se även allmän rubricerande
beskrivning till ScanLines i
huvuddokumentet
— ScanLines i DEPLHI4 innehåller av allt att döma en
(grym) BUGG — (nästan) i princip omöjlig att upptäcka vid enstaka programtest.
Jag upptäckte den nyligen (först efter 15 års nära daglig intensiv användning)
och då bara i rent förbigående. Se utförligt i ScanLineERROR16|64.
Felet yttrar sig i ett AccessViolation-avbrott (enda som händer är att
funktionen inte utförs samt en liten rödkryss-dialog som upplyser).
— Felet är bara kritiskt för ScanLineKod av typen ROTERAbild90°
och VändBildHorisontellt — inte VändVertikalt. För att kringgå felet måste
typen TMemoryStream användas i de fallen — eller att en extra xy-pixelrad i
originalet måste offras (resulterar i en tom rad i slutbilden) för att slippa
ifrån avbrottet.
— Ytterligare en observerad DELPHI4-spärr finns i
bildbehandlingen: TESTA FÖRST Operationer på bilder med större bildyta än
bildskärmen om sådan kod är aktuell: I mitt observerade fall gavs
AccessViolation-avbrott — och som kunde hävas om man i ForTo-Looparna för yx
drar ifrån en extra pixel i bredd och höjd. Det hävde avbrottet.
Nedan följer en inledande övningsgenomgång som visar hur
TMemoryStream kan användas (mycket mera effektivt) alternativt till ScanLines.
— FÖRDELEN MED TMemoryStream före Scanlines är att
TMemoryStream innehåller EN ENDA LÅNG POSTADRESSGATA MED HELA BILDENS DATAMÄNGD
TILLGÄNGLIG — vårt enda huvudbry är att hitta Sättet att adressera de
periodiskt återkommande bildradslängderna.
— ScanLine-metoden bygger på en förprogrammerad subrutin
som redan har delat upp bilddatat i motsvarande bildrader. För att nå olika
höjdrader — Scanlines — måste en ny ScanLine läsas in för varje sådan rad, och
vilket i vissa fall — med intensiva FÅTALIGA radpixels med många
höjdinläsningar — leder till att ScanLine-metoden blir LÅNGSAM.
— TMemoryStream har ingen sådan nackdel.
Test, övnings och analysprocedur för TMemoryStream i
DELPHI4:
ÖVNINGSOBJEKT:
— En svart kvadrat
100×100p (FillRect ritar 99×99p).
ÖVNINGSÄNDAMÅL:
— Att navigera i datorminnesblocket för en RGB-TBitMap för
att kunna skriva snabb, effektiv kod i speciell bildhantering — därför att
ScanLineMetoden i DELPHI4 IBLAND blir ytterst omständlig, och TAR ONÖDIGT LÅNG
TID. Exempel följer.
Programuppgiften
förutsätter detaljerad information om BMP-filens datastruktur. Information om
den delen finns på webben. För min egen del använder jag en äldre bokreferens
(Tom Swan, Windows File Formats). Vi förutsätter här full insyn. Översikten
nedan FÖR TBitMapInfoHeader min sammanställning.
Elementär flytbildsteknik — grundexempel i DELPHI4
Efter Inside WINDOWS FILE FORMATS s57, Tom
Swan, Sams Publishing 1993
|
15-18 4 1.DWORD biSize:
...................... Longint; 19-22 4 2.LONG biWidth: ................... Longint; 23-26 4 3.LONG biHeight:
.................. Longint; 27-28 2 4.WORD biPlanes:
................. Word; 29-30 2 5.WORD biBitCount:
.............. Word; 31-34 4 6.DWORD biCompression:
...... Longint; 35-38 4 7.DWORD biSizeImage:
........... Longint; 39-42 4 8.LONG biXPelsPerMeter:
.... Longint; 43-46 4 9.LONG biYPelsPerMeter:
.... Longint; 47-50 4 10.DWORD biClrUsed: ................ Longint; 51-54 4 11.DWORD biClrImportant: ........ Longint; |
RGB-formatets datalängd — formen oven samma
som via DELPHI4:s TMemoryStream.
— Pixeldatats offsetadress
är 54. DataPekaren ska ställas på P + 54 för att få bildens första
pixel (B-värdet i första färggruppen BGR#).
Testprogrammet till
resultatfiguren (Project1¦2009|Unit5|TestBMPmemory):
Procedure TestBMPmemory;
var
B:
TBitMap;
P,iP,Pa,Pb: PChar;
A:
Byte;
TM:
TMemoryStream;
W,H,x,I:
Integer;
XS,YS,R,y:
Integer;
iX,jX,kX,
Sx,Ex:
Integer;
v:
Real;
begin with Form1 do begin
TM:= TMemoryStream.Create;
B:= TBitMap.Create;
try
{SpecialRutin,
etablerar bitmap:ens dimensioner:}
BitMapRect(Rect(0,0,100,100),B);
B.PixelFormat:= pf32bit;
B.Canvas.Brush.Color:= 0;
B.Canvas.FillRect(ClientRect);
{SPARA TILL MemoryStreamen så att vi kan
göra ändringar därifrån:}
B.SaveToStream(TM);
{TILLDELA MemoryStreamen en AdressPekare
- som är vårt HuvudTransportMedel i
ändringarna:}
P:=
TM.Memory;
//P:= @TM;|Inte samma. @TM pekar på
adressen till Variabeln TM.
{LÄSNINGfrån|Vi läser in en byte från
TM-kroppen
|Kontroll visar full BMP-struktur:}
{De bägge första byten är BM|Hela
BMP-strukturen används.}
{SKRIVNINGtill|Vi gör en ändring för att
kolla om det fungerar
|G i första bildpixelns BGR:}
// Byte((P+54+1)^):= 255;
{KLARGÖRANDE
TEST|Svart100×100p|Testpunkt=Röd:}
H:= B.Height;
W:= B.Width;
{FÖRSTA
BYTEN FÖRSTA RADEN¦TestaRÖD|0=B|1=G|2=R|FörstaTM-Byten längst ner Vänster:}
x:= 0;
Byte((P+54+ 4*x+0)^):= 0;
Byte((P+54+ 4*x+1)^):= 0;
Byte((P+54+ 4*x+2)^):= 255;
{SISTA
BYTEN FÖRSTA MINNESRADEN:}
x:= W -1;
Byte((P+54+ 4*x+0)^):= 0;
Byte((P+54+ 4*x+1)^):= 0;
Byte((P+54+ 4*x+2)^):= 255;
{FÖRSTA
BYTEN ANDRA|01|MINNESRADEN|nW=1:a|RAD(n+1):}
x:= (W);
Byte((P+54+ 4*x+0)^):= 0;
Byte((P+54+ 4*x+1)^):= 0;
Byte((P+54+ 4*x+2)^):= 255;
{SISTA
BYTEN ANDRA MINNESRADEN:}
x:= 2*(W)-1;
Byte((P+54+ 4*x+0)^):= 0;
Byte((P+54+ 4*x+1)^):= 0;
Byte((P+54+ 4*x+2)^):= 255;
{SISTA
BYTEN SISTA MINNESRADEN:}
x:= (H)*(W)-1;
Byte((P+54+ 4*x+0)^):= 0;
Byte((P+54+ 4*x+1)^):= 0;
Byte((P+54+ 4*x+2)^):= 255;
{FÖRSTA
BYTEN SISTA MINNESRADEN:}
x:= (H-1)*(W);
Byte((P+54+ 4*x+0)^):= 0;
Byte((P+54+ 4*x+1)^):= 0;
Byte((P+54+ 4*x+2)^):= 255;
{ALLA
RÖDA|012=BGR|LeftBottom-RightTop:}
{ for x:= 0 to (W)*(H)-1 do
begin
Byte((P+54+ 4*x+0)^):= 0;
Byte((P+54+ 4*x+1)^):= 0;
Byte((P+54+ 4*x+2)^):= 255;
end;
{}
{FYLL
RAD (ScanLineNr y=)10 |räknatLeftTop| MED VIOLETT:}
for
x:= (H-1-10)*W to (H-10)*(W)-1 do
begin
Byte((P+54+ 4*x+0)^):= 255;
Byte((P+54+ 4*x+1)^):= 0;
Byte((P+54+ 4*x+2)^):= 255;
end;
{PREFIXxSIN:
y/R= sin; R=y/sin; y = Rsin; x = Rcos: PREFIXxCOS:
RITA VIOLETT CIRKEL MED RADIEN 40p från
mitten:}
XS:= W div 2;
YS:= H div 2; R:= 40;
for
I:= 0 to 360 do begin
v:= I/180*pi;
y:= Round(YS -
R*cos(v));
x:= Round(XS +
R*sin(v));
x:= x + (H-1-y)*W;
Byte((P+54+ 4*x+0)^):= 255;
Byte((P+54+ 4*x+1)^):= 0;
Byte((P+54+ 4*x+2)^):= 255;
end;
{Riten
ovan med xy¦R¦cos¦sin börjar längst upp på cirkeln;
Med xy¦R¦sin¦cos ritas cirkeln från reguljära
nollpunkten på x-axeln.}
{RITA
UT TRE PIXELS BÖRJAN RAD (ScanLineNr y=5 |räknatLeftTop| MED
GULT[RGB(255,255,0)] GRÖNT[RGB(0,255,0)]
VITT[RGB(255,255,255)]:}
{Vi
skriver nu koden regelrätt efter R G B -följden 2 1 0 :}
Sx:= (H-1-5)*W;
for x:=
Sx to
Sx + 2 do
begin
iX:= x - Sx;
case
iX of
0: begin
Byte((P+54+ 4*x+2)^):= 255;
Byte((P+54+ 4*x+1)^):= 255;
Byte((P+54+ 4*x+0)^):= 0;
end;
1: begin
Byte((P+54+ 4*x+2)^):= 0;
Byte((P+54+ 4*x+1)^):= 255;
Byte((P+54+ 4*x+0)^):= 0;
end;
2: begin
Byte((P+54+ 4*x+2)^):= 255;
Byte((P+54+ 4*x+1)^):= 255;
Byte((P+54+ 4*x+0)^):= 255;
end;
end;{endCase}
end;{endForX}
{KOPIERA
OVANSTÅENDE TILL SAMMA RAD5 SLUTET MEN I OMVÄND ORDNING:
—
Rutinen radvis för FlipHorizontal: — Ex=Radslutet — jX=»W-x»:}
Ex:= (H-5)*(W)-1;
iP:= P+54;
for
x:= Sx to Sx + 2 do
begin
jX:= 4*(Ex + Sx - x);
kX:= 4*x;
Pb:= iP+jX;
Pa:= iP+kX;
Byte((Pb +2)^):= Byte((Pa +2)^);
Byte((Pb +1)^):= Byte((Pa +1)^);
Byte((Pb +0)^):= Byte((Pa +0)^);
end;{endFor}
{VÅRT
ENDA PROBLEM: att hitta ENKLA BESKRIVANDE beteckningar.}
{Förberedelse
för RotationsAlgoritmen för successiva 90°-steg:}
{RITA
TRE RADER (GultGröntVitt) MED 10 PIXELS I VARJE från LeftTop=0:}
for
y:= 0 to 2 do begin
Sx:= (H-1-y)*W;
Ex:= Sx + 10;
for
x:= Sx to Ex do
begin
case
y of
0: begin
Byte((P+54+ 4*x+2)^):= 255;
Byte((P+54+ 4*x+1)^):= 255;
Byte((P+54+ 4*x+0)^):= 0;
end;
1: begin
Byte((P+54+ 4*x+2)^):= 0;
Byte((P+54+ 4*x+1)^):= 255;
Byte((P+54+ 4*x+0)^):= 0;
end;
2: begin
Byte((P+54+ 4*x+2)^):= 255;
Byte((P+54+ 4*x+1)^):= 255;
Byte((P+54+ 4*x+0)^):= 255;
end;
end;{endCaseY}
end;{endForX}
end;{endForY}
{ x:= (H-1-0)*W;
Byte((P+54+ 4*(H-1-50)*W +2)^):=
Byte((P+54+ 4*x+2)^);
Byte((P+54+ 4*(H-1-50)*W +1)^):=
Byte((P+54+ 4*x+1)^);
Byte((P+54+ 4*(H-1-50)*W +0)^):=
Byte((P+54+ 4*x+0)^);
{KOPIERA
ÖVER ovanstående tre rader roterat +90° från LeftTopRADy=50|x=012:}
{FÖRSTA
BYTEN RAD y|LeftTop -> P =(H-1-y)*(W)|yMAX = H-1 :}
{
Källpixel 0 1 2 3 .. På Rad 0 ska kopieras till
Målpixel 0 På Rad 50 49 48 47 ..
Källpixel 0 1 2 3 .. På Rad 1 ska kopieras till
Målpixel 1 På Rad 50 49 48 47 ..
Källpixel 0 1 2 3 .. På Rad 2 ska kopieras till
Målpixel 2 På Rad 50 49 48 47 ..
Första Byten på LeftTopRADy = (H-1-y )*W ¦
Första Byten på LeftTopRADy=50 =
(H-1-50)*W ¦
Första Byten på LeftTopRADy=49 =
(H-1-49)*W ¦
Första Byten på LeftTopRADy=48 =
(H-1-48)*W ¦ ...
:
Heltalsvärdena för x 0123.. är x
minus x-Startvärdet (Sx=(H-1-y)*W):
iX = x - Sx = 0 1 2 3 ...
:
+iX eftersom TMemoryStream räknar
upp då vi räknar ner mot LeftTopY=0:
:
Första Byten på LeftTopRADy=50 =
(4*0)+4*(H-1-50+|iX=0)*W ¦
Första Byten på LeftTopRADy=49 =
(4*0)+4*(H-1-50+|iX=1)*W ¦
Första Byten på LeftTopRADy=48 =
(4*0)+4*(H-1-50+|iX=2)*W ¦ ...
:
Byte((P+54+ (4*0)+4*(H-1-50+iX)*W
+2)^):= Byte((P+54+ 4*x+2)^);
Byte((P+54+ (4*0)+4*(H-1-50+iX)*W
+1)^):= Byte((P+54+ 4*x+1)^);
Byte((P+54+ (4*0)+4*(H-1-50+iX)*W
+0)^):= Byte((P+54+ 4*x+0)^);
:
Andra Byten på LeftTopRADy=50 = (4*1)+4*(H-1-50+|iX=0)*W ¦
Andra Byten på LeftTopRADy=49 = (4*1)+4*(H-1-50+|iX=1)*W ¦
Andra Byten på LeftTopRADy=48 = (4*1)+4*(H-1-50+|iX=2)*W ¦ ...
:
Byte((P+54+ (4*1)+4*(H-1-50+iX)*W +2)^):= Byte((P+54+ 4*x+2)^);
Byte((P+54+ (4*1)+4*(H-1-50+iX)*W
+1)^):= Byte((P+54+ 4*x+1)^);
Byte((P+54+ (4*1)+4*(H-1-50+iX)*W
+0)^):= Byte((P+54+ 4*x+0)^);
:
Tredje Byten på LeftTopRADy=50 =
(4*2)+4*(H-1-50+|iX=0)*W ¦
Tredje Byten på LeftTopRADy=49 =
(4*2)+4*(H-1-50+|iX=1)*W ¦
Tredje Byten på LeftTopRADy=48 =
(4*2)+4*(H-1-50+|iX=2)*W ¦ ...
:
Byte((P+54+ (4*2)+4*(H-1-50+iX)*W
+2)^):= Byte((P+54+ 4*x+2)^);
Byte((P+54+ (4*2)+4*(H-1-50+iX)*W
+1)^):= Byte((P+54+ 4*x+1)^);
Byte((P+54+ (4*2)+4*(H-1-50+iX)*W
+0)^):= Byte((P+54+ 4*x+0)^);
:
Första Andra Tredje byten på
LeftTopMålRADerna (50 49 ...) motsvarar
alltså källpixlarnas Käll-y-radVärden räknat LeftTop:
SUMMAtot :}
{ for y:= 0 to 2 do begin
Sx:= (H-1-y)*W;
Ex:= Sx + 10;
for x:= Sx to Ex do begin
iX:= x - Sx;
Byte((P+54+(4*y)+ 4*(H-1-50+iX)*W
+2)^):= Byte((P+54+ 4*x+2)^);
Byte((P+54+(4*y)+ 4*(H-1-50+iX)*W
+1)^):= Byte((P+54+ 4*x+1)^);
Byte((P+54+(4*y)+ 4*(H-1-50+iX)*W
+0)^):= Byte((P+54+ 4*x+0)^);
end;
end;
{Ovanstående
kan förkortas|Förenklas(förMaxSnabbhet):}
Pa:= P+54 + 0*4*W*(H-1-50);
for
y:= 0 to 2 do begin
Sx:= (H-1-y)*W;
Ex:= Sx + 10;
for
x:= Sx to Ex do begin
iX:= 4*(y + W*(x-Sx));
Pb:= P+54 + 4*x;
iP:= Pa + iX;
Byte((iP +2)^):= Byte((Pb +2)^);
Byte((iP +1)^):= Byte((Pb +1)^);
Byte((iP +0)^):= Byte((Pb +0)^);
end;
end;
{(0*4.. placerar kopian i bildens
botten)
(P+54+(4*y)+ 4*(H-1-50+iX)*W :
= (P+54+(4*y)+ 4WH-4W-4W50+4WiX) ¦
= (P+54+ 4WH-4W-4W50 + 4*y + 4WiX) ¦
= (P+54+ 4W(H-1-50) + 4*y + 4WiX) ¦
= (aP + 4*(y + W*iX)) ¦
= (aP + 4*y + wiX4) ¦ iX:= wiX4 = 4*W*(x-Sx) ¦ aP = P+54 + 4W(H-1-50) |
}
{Tas MålPixlarna nerifrån BildBotten — som
blir ordningen vid reguljär
90°-rotation — bortfaller 4*W*(H-1-50) i Pa
via Offset y=H-1
som ger det rena Pa = P+54.
— Har vi två skilda bildrektanglar, blir
Målområdets W ovan i
iX:= 4*(y + W*(x-Sx)) lika med H. Se vidare
T2014 (och P2). 16Sep2014.}
{Samma som hela BMP-strukturen|Med
BitMapInfoheader.}
{UPPDATERA ÄNDRINGARNA TILL den
ursprungliga bitmap:en|B:}
{Börjar från MinnesPekarensPosition -
funkar inte om annat än från 0:}
TM.Position:= 0;
{UPPDATERAR ÄNDRINGARNA:}
B.LoadFromStream(TM);
{SPARAR KOPIA FÖR MANUELL KOLL:}
B.SaveToFile('AAAb.BMP');
{SPARAR KOPIA FÖR MANUELL KOLL:}
TM.SaveToFile('AAA.BMP');
{OK|Bilden ritas också ut som ovan:}
Image1.Canvas.Draw(0,0,B);
finally
B.Free;
TM.Free;
end;
Label1C(Char(A));
end;{endWithForm1}
end;{endTestBMPmemory}
Label1 skriver ut ”B”. Se början av kodblocket [SLref1].
Exempel på TMemoryStream för
Rotera90° och VändHorisontellt
Exemplet nedan visar huvudkoden i TMemorystream för
bildrotation o steg om 90 grader samt VändHorisontellt:
case Key of
Ord('H'): begin {FLIP HORIZONTAL ..............:}
for y:= 0 to H-1 do begin
Sx:=
(H-1-y)*W;
Ex:= Sx + W-1;
for x:= Sx to Ex do begin
iP:= Pb +
54 + 4*(Ex + Sx - x);
P:= Pa + 54 + 4*x;
Byte((iP
+2)^):= Byte((P +2)^);
Byte((iP
+1)^):= Byte((P +1)^);
Byte((iP
+0)^):= Byte((P +0)^);
end;{endForX}
end;{endForY}
end;{endFlipHorizontal
...............}
Ord('R'): begin {ROTATE 90°
...................:}
1 for y:= 0 to H-1 do begin
2 Sx:=
(H-1-y)*W;
3 Ex:= Sx + W-1;
4 for x:= Sx to Ex do begin
5 iP:= Pb + 54 + 4*(y + H*(x-Sx));
6 P:= Pa + 54 + 4*x;
7 Byte((iP +2)^):= Byte((P +2)^);
8 Byte((iP +1)^):= Byte((P +1)^);
9 Byte((iP
+0)^):= Byte((P +0)^);
10 end;{endForX}
11 end;{endForY}
end;{endRotate90°
....................}
end;{endInCase2HR|Execute}
I jämförelse med motsvarande ScanLine-ForTo-xy-block, är
ovanstående 11-radiga TMemoryStreamBlock endast 2 rader längre: motsvarande
ScanlineBlock kräver endast 9 rader (men kan i vissa fall bli något långsammare
beroende på intensiteten i ScanLine-laddningar).
Rotationen 90° med ScanLines i DELPHI4 — 9 rader till
jämförelse:
1 for
y:=0 to H-t do begin
2 Pa:= A.ScanLine[y];
3 for x:=0
to
W-t do begin
4 Pb:= B.ScanLine[W-x];
{AccessViolationAvbrottet 16|64Felet stannar här:}
5 Pb[4*y+2]:= Pa[4*x+2];
6 Pb[4*y+1]:= Pa[4*x+1];
7 Pb[4*y+0]:= Pa[4*x+0];
8 end;{endForX}
9 end;{endForY}
— Se ovan mera utförligt från ScanLineERROR16|64.
DELPHI4Test2011
ämnesrubriker
innehåll
Föregående:
DELPHI4Test2011.htm — huvuddokument — HJÄLPDOKUMENT FÖR
DELPHI4Test2011
referenser
Senast uppdaterade version: 2022-05-22.
*END.
Stavningskontrollerat 2011-06-08.
*
DELPHI4Test2014MANUAL ·
√
τ π ħ ε UNICODE — ofta använda tecken i
matematiskt-tekniskt-naturvetenskapliga beskrivningar
σ
ρ ν ν π τ γ λ η ≠ √ ħ
ω → ∞ ≡
Ω
Φ Ψ Σ Π Ξ Λ Θ Δ
α
β γ δ ε λ θ κ π ρ τ φ
ϕ σ ω ϖ ∏ √ ∑ ∂ ∆ ∫
≤ ≈ ≥ ˂ ˃ ˂ ˃ ← ↑
→ ∞ ↓
ϑ
ζ ξ
Pilsymboler, direkt via tangentbordet: Alt+24 ↑; Alt+25
↓; Alt+26 →; Alt+27 ←; Alt+22 ▬
Alt+23
↨ — även Alt+18 ↕; Alt+29 ↔
DELPHI4Test2011.htm
Senast uppdaterade version: 22 maj
2022 | 12:57:44 | 2022-05-22. [GMT+1]Solar[GMT+2]Industry
Vidareutvecklat Från DELPHI 4 Test 2011 —
DELPHI4Test2011ref.htm#AnvändningSupportInstallation
T2014Reg — HUVUDDELEN AV
VERKTYGEN MAN BEHÖVER FÖR AVANCERAD DATORANVÄNDNING I TEXT OCH BILD ¦ Jan2022
*