AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi ScanLine anwenden, bzw die Hilfe verstehen
Thema durchsuchen
Ansicht
Themen-Optionen

ScanLine anwenden, bzw die Hilfe verstehen

Ein Thema von tapete · begonnen am 19. Jul 2007 · letzter Beitrag vom 20. Jul 2007
Antwort Antwort
Seite 1 von 2  1 2      
tapete

Registriert seit: 13. Jul 2007
7 Beiträge
 
Turbo Delphi für Win32
 
#1

ScanLine anwenden, bzw die Hilfe verstehen

  Alt 19. Jul 2007, 12:01
Ich habe folgendes Problem. Ich will in einer Bitmap die Farbwerte jedes Pixels auslesen lassen. Das funktioniert auch mittels der Codeteile, die ich in 2 Tutorials gefunden habe. Ich verstehe aber nicht, warum es funktioniert und wie man mit der Hilfe von Delphi, die das ja ermöglichen sollte, alleine darauf kommt.


Also in meinem Programm habe ich einen Typ:
PixArray = Array [1..3] of Byte; in einer Procedure wird ein Zeiger auf einen Speicherbereich vom obigen Typ erstellt:
Delphi-Quellcode:
  var
  p: ^PixArray;

Weiter unten dann das Arbeiten mit ScanLine:

p:= Bild.ScanLine[h];
Mein Problem ist, woher weiß ich, was p für ein "Variablentyp" sein muß, also ein Zeiger auf einen Speicherbereich der Art: Array [1..3] of Byte


In der Hilfe finde ich nur:

Zitat:
TBitmap.ScanLine Eigenschaft

Ermöglicht einen indizierten, zeilenweisen Zugriff auf Pixel.

Klasse
TBitmap

Syntax


[ Delphi] property ScanLine: Pointer read GetScanline;


Beschreibung
ScanLine wird nur bei DIBs (Device Independent Bitmaps) für Bildbearbeitungsprogramme verwendet, die Low-Level-Operationen auf Pixelebene durchführen.

Daraus kann ich das nicht schlußfolgern. Und sich den Code immer aus Tutorials zusammensuchen, ist nicht sehr elegant.

Sorry für möglicherweise vorhandene Dummheit.
  Mit Zitat antworten Zitat
OlafSt

Registriert seit: 2. Mär 2007
Ort: Hamburg
284 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

Re: ScanLine anwenden, bzw die Hilfe verstehen

  Alt 19. Jul 2007, 12:15
Eigentlich ganz simpel

Die Deklaration
P: ^PixArray; macht aus deinem P erstmal einen Pointer. Nichts weiter.
Das Property ScanLine liefert einen Pointer zurück - also paßt das prima zusammen.

Erst, wenn du beginnst, im Code dein P zu dereferenzieren, also z.B. bei
P^[1]:=0; wird die Tatsache, das dein P ein Pointer auf ein PixArray ist, interessant. Denn erst hier muß der Compiler anfangen, Adressen im Speicher zu errechnen.

Bis dahin ist ein Pointer einfach nur ein Pointer.

HTH,

Olaf
  Mit Zitat antworten Zitat
tapete

Registriert seit: 13. Jul 2007
7 Beiträge
 
Turbo Delphi für Win32
 
#3

Re: ScanLine anwenden, bzw die Hilfe verstehen

  Alt 19. Jul 2007, 12:57
Hi Olaf,

Zitat:
Erst, wenn du beginnst, im Code dein P zu dereferenzieren, also z.B. bei
p^[1]:=0;
wird die Tatsache, das dein P ein Pointer auf ein PixArray ist, interessant.


Ok, aber spätestens dann muß ich doch den typ wissen (Array [1..3] of Byte)

Also irgendwie ist mir das suspekt, ich bin da Neuling.


Ein Pointer ist ja eine Adresse auf einen Speicher.

Wenn ich schreibe:

p: ^PixArray Dann ist ja p ein typisierter Pointer vom Typ Array. Wobei ein Array ja praktisch mehrere Pointer zusammengefaßt ist.

Liefert dann
p:= Bild.ScanLine[h];
ein Array aus 3 Speicheradressen zurück, die bei mir in p unter p[1],p[2] und p[3] gespeichert sind?
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#4

Re: ScanLine anwenden, bzw die Hilfe verstehen

  Alt 19. Jul 2007, 13:10
willst du wissen woher du hättest wissen sollen das man da "array[1..3] of Byte" nehmen muss?
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
tapete

Registriert seit: 13. Jul 2007
7 Beiträge
 
Turbo Delphi für Win32
 
#5

Re: ScanLine anwenden, bzw die Hilfe verstehen

  Alt 19. Jul 2007, 13:13
ja


Und was ScanLine genau zurück gibt. Müssen ja irgendwie mehrere Zeiger sein.

Vielleicht fehlt mir auch irgendwas Grundverständnismäßiges.
  Mit Zitat antworten Zitat
Benutzerbild von inherited
inherited

Registriert seit: 19. Dez 2005
Ort: Rosdorf
2.022 Beiträge
 
Turbo Delphi für Win32
 
#6

Re: ScanLine anwenden, bzw die Hilfe verstehen

  Alt 19. Jul 2007, 13:14
Also, vereinfacht läuft das so ab: das Bild besteht ja aus Pixeln, wobei jedes dieser Pixel aus im normalfall 3 Byte besteht.
Ein Byte jeweils für Rot, Blau und Grünanteil. Und diese Bytes liegen hintereinander im Speicher.
bei einem 3x3-Bild dessen erste Zeile Schwarz ist, die anderen weiß ergibt sich folgendes Speicherbild:

Code:
00,00,00 00,00,00 00,00,00   FF,FF,FF FF,FF,FF FF,FF,FF  FF,FF,FF FF,FF,FF FF,FF,FF
Jetzt hast du ein einmal dein Typ, ein Array [1..3] of Byte, also Platz für genau 3 Byte.
Dann machst du daraus einen Pointer, mit ^Typname und weist der Variable das Ergebnis von Scanline zu, was nichts anderes ist,
als der Anfang dieser oben ersten genannten Bytekette, die erste "Zeile" des Bildes.

Wenn du dann auf p^[1] Zugreifst, bekommst du das erste Byte. Ich weiß jetzt nicht wierum das da drin liegt, entweder ist das der Rot- oder der Blauanteil des ersten Pixels. Mit p^[2] bekommst du den Grünanteil und mit p^[3] das 3. Byte, den übrig bleibenden anteil.
Jetzt musst du den Pointer um eins erhöhen, damit du an die nächsten 3 Bytes kommst, also das nächste Pixel.
Das machst du sooft bis du an das Ende der Zeile angekommen bist. Dann machst du das für die nächste Zeile usw.

Fertig
Nikolai Wyderka

SWIM SWIM HUNGRY!
Neuer Blog: hier!
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#7

Re: ScanLine anwenden, bzw die Hilfe verstehen

  Alt 19. Jul 2007, 13:15
@inherited: Fast richtig, die Zeilen liegen in umgekehrter Reihenfolge im Speicher. Erst die letzte zeile, dann die vorletzte etc.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Benutzerbild von inherited
inherited

Registriert seit: 19. Dez 2005
Ort: Rosdorf
2.022 Beiträge
 
Turbo Delphi für Win32
 
#8

Re: ScanLine anwenden, bzw die Hilfe verstehen

  Alt 19. Jul 2007, 13:17
Hoppala. Das kann sein, Sorry. Darum kümmert sich zum Glück ScanLine
Nikolai Wyderka

SWIM SWIM HUNGRY!
Neuer Blog: hier!
  Mit Zitat antworten Zitat
tapete

Registriert seit: 13. Jul 2007
7 Beiträge
 
Turbo Delphi für Win32
 
#9

Re: ScanLine anwenden, bzw die Hilfe verstehen

  Alt 19. Jul 2007, 13:51
Ah ok, das ist sehr schön, danke.


00,00,00 00,00,00 00,00,00
FF,FF,FF FF,FF,FF FF,FF,FF
FF,FF,FF FF,FF,FF FF,FF,FF <- Zeile 0
_______




Also ScanLine[0] gibt mir die Adresse von dem mit ______ unterstrichenen Speicher wieder, der 3 Byte beträgt. Um an das Pixel rechts davon zu kommen, erhöhe ich die Adresse einfach um 1.

Mit

Delphi-Quellcode:
type
PixArray = Array [1..3] of Byte;
difiniere ich einen Typ, der aus 3 Elementen besteht zu jeweils einem Byte

mit
  p: ^PixArray; difiniere ich p als ein Array, das 3 Speicheradressen zu Speichern von jeweils einem Byte aufnehmen kann.


das folgende ist mir aber noch nicht so ganz verständlich
    p:= xBMPImage.ScanLine[0];
Wenn ScanLine[0] die Adresse von dem oben _____ unterstrichenen Speicher liefert, dann muß das bei der Zuweisung p:= ... diese Adresse ja in 3 Adressen unterteilt werden.


Praktisch liefert ScandLine die Adresse von:
FF,FF,FF

und bei p:=..
wird diese in die Adressen von FF, FF und FF unterteilt. Kann man sich das so vorstellen?
  Mit Zitat antworten Zitat
OlafSt

Registriert seit: 2. Mär 2007
Ort: Hamburg
284 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#10

Re: ScanLine anwenden, bzw die Hilfe verstehen

  Alt 19. Jul 2007, 13:54
Erklärt nur alles dem TE nicht, was es mit dem Pointer auf sich hat und warum das alles Zuweisungskompatibel ist...

Im Endeffekt wird die Frage "ist mein P ein Pointer oder ein ^PixArray" erst zu Laufzeit interessant. Pointer unter sich sind allesamt Zuweisungskompatibel, denn eigentlich speichern sie alle NUR ADRESSEN. Daraus folgt: Pointer sind nur "indirekte" Variablen - ich hoffe, du verstehst, was ich meine...

Führst du also ein
P:=Img.Scanline[h]; aus, dann wird in P nur eine Adresse gespeichert. Mehr nicht. Aber: Dein P "zeigt" jetzt auf ein Stück Speicher.

Erst, wenn du mit dem P anfängst "zu arbeiten", wird es interessant, das das kein normaler Pointer ist, sondern ein typisierter Pointer.

Mit der Zeile
i:=P^[1]; muß Delphi anfangen, dein P wie ein Array zu behandeln. Das Stück Speicher, auf das dein P nun zeigt, wird erst jetzt als ein PixArray interpretiert

Ich bin sicher, irgendwo findet sich hier ein Tutorial zum Thema Zeiger/Pointer. Hat man das mit den Pointern begriffen, erkennt man die ungeheuer Mächtigkeit von Zeigern - aber auch die ziemlich gräßlichen Nebenwirkungen, die Zeiger haben können. Ein Beispiel (P sei wieder ein ^PixArray):

Delphi-Quellcode:
P:=Pointer(2);
P^[1]:=37;
Das ist absolut gültiger Code. Den wird Delphi auch klaglos übersetzen. Schließlich weist du einem Pointer einen anderen Pointer zu (das P bekommt also die Adresse 2 als Inhalt). Und dann greift du auf das erste Byte zu, auf das P zeigt. Nichts schlimmes also.

Läßt man das laufen, bekommt man was an die Ohren (Schutzverletzung an Adresse [bla], Schreiben von Adresse $00000002)

Pointer gehören nicht umsonst zum am meisten gefürchteten Konstrukt in Coderkreisen, denn zahllose Einsteiger verstehen das Konzept erst nach einer Weile - und etliche raffen es nie.

Noch ein Tip: Wenn du im Code mit Zeigern arbeitest, dann benutze das Dach zum dereferenzieren. Ich weiß, das Delphi das nicht benötigt (war mal anders). Aber es hilft ungemein bei der Fehlersuche, wenn man sieht, das man nicht den Zeiger beschreibt, sondern das, auf das er zeigt Spätestens, wenn man sich irgendwann mal mit C beschäftigt und dort praktisch sekündlich über Zeiger stolpert und sie dereferenzieren muß, freut man sich über diese Angewohnheit

[Edit]Hab ein Tutorial gefunden:
Zeiger-Tutorial
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:56 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz