Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: So Jul 13, 2025 20:16

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Di Feb 22, 2011 12:14 
Offline
DGL Member
Benutzeravatar

Registriert: So Jan 07, 2007 21:26
Beiträge: 130
Wohnort: mal hier mal da mal irgendwo
Hi Leute,

ein sonderbares Problem hält mich jetzt schon seit ca. 2 Wochen auf.
Ich habe via Ressource 2 Bitmaps ("edge00" und "egde11") zur Verfügung. Beide wurden mit Gimp erstellt und mit gleichem Format gespeichert (24 bit R8 G8 B8). An sich sind nur die Farben schwarz(0,0,0), rot(255,0,0), blau(0,0,255) und grün(0,255,0) vorhanden. Dazu kommt dass jeweils nur ein Pixel im gesamten Bild blau ist.

Aus Performance-Gründen arbeite ich mit ScanLine & dem Pixelformat pf24bit:
Code:
  procedure LoadMasks();
  var b: TBitmap;
      p: PScanLine;
      mark: TPoint;
      x,y: Integer;
      function Pixel(const px,py: Integer): PBGR;
      begin
        Result := @p[px+b.Width*(b.Height-(py+1))];
      end;
      function CEqual(const a,b: TBGR): boolean;
      begin
        Result := (a.r=b.r)and(a.g=b.g)and(a.b=b.b);
      end;
  begin;


desweiteren greife ich auf die einzelnen Pixeldaten zu in dem ich den Zeiger auf den Beginn der Bilddaten in einer Variablen speicher und den Index berechne:
Code:
procedure LoadMasks();
  var b: TBitmap;
      p: PScanLine;
      mark: TPoint;
      x,y: Integer;
      function Pixel(const px,py: Integer): PBGR;
      begin
        Result := @p[px+b.Width*(b.Height-(py+1))];
      end;
      function CEqual(const a,b: TBGR): boolean;
      begin
        Result := (a.r=b.r)and(a.g=b.g)and(a.b=b.b);
      end;
  begin


Die Bitmaps lade ich so:
Code:
    b := TBitmap.Create;
    try
      SetLength(MaskLT, 0);
      b.HandleType := bmDIB;
      b.PixelFormat := pf24bit;
      b.LoadFromResourceName(hInstance, 'edge00');
      p := b.ScanLine[b.Height-1];


Dann suche ich nach den Koordinaten von dem blauen Pixel. Und genau da beginnt mein Problem. Bei "edge00" wird er noch gefunden, bei "egde11" aber nicht mehr =/
Hier noch mal der relevante Code zusammenhängend:
Code:
     TMaskPixel = record
       Equal: Boolean;
       X,Y: Integer;
     end;
     TBGR = record
       b,g,r: Byte;
     end;
     PBGR = ^TBGR;
     TScanLine = Array[0..0] of TBGR;
     PScanLine = ^TScanLine;

var  MaskLT, MaskRB: Array of TMaskPixel;

function RGB(r,g,b: Byte):TBGR;overload;
begin
  Result.r := r; Result.g := g; Result.b := b;
end;

  procedure LoadMasks();
  var b: TBitmap;
      p: PScanLine;
      mark: TPoint;
      x,y: Integer;
      function Pixel(const px,py: Integer): PBGR;
      begin
        Result := @p[px+b.Width*(b.Height-(py+1))];
      end;
      function CEqual(const a,b: TBGR): boolean;
      begin
        Result := (a.r=b.r)and(a.g=b.g)and(a.b=b.b);
      end;
  begin
//edge00 mask
    b := TBitmap.Create;
    try
      SetLength(MaskLT, 0);
      b.HandleType := bmDIB;
      b.PixelFormat := pf24bit;
      b.LoadFromResourceName(hInstance, 'edge00');
      p := b.ScanLine[b.Height-1];
      for x := 0 to b.Width-1 do
        for y := 0 to b.Height-1 do
          if CEqual(Pixel(x,y)^,RGB(0,0,255)) then
            mark := Point(x,y);
      for x := 0 to b.Width-1 do
        for y := 0 to b.Height-1 do
          if (CEqual(Pixel(x,y)^,RGB(255,0,0)))or(CEqual(Pixel(x,y)^,RGB(0,255,0))) then
          begin
            SetLength(MaskLT, Length(MaskLT)+1);
            MaskLT[High(MaskLT)].Equal := CEqual(Pixel(x,y)^,RGB(255,0,0));
            MaskLT[High(MaskLT)].X := x-mark.X;
            MaskLT[High(MaskLT)].Y := y-mark.Y;
          end;
    finally
      b.Free;
    end;
   
//edge11 mask
    b := TBitmap.Create;
    try
      SetLength(MaskRB, 0);
      b.HandleType := bmDIB;
      b.PixelFormat := pf24bit;
      b.LoadFromResourceName(hInstance, 'edge11');
      p := b.ScanLine[b.Height-1];
      for x := 0 to b.Width-1 do
        for y := 0 to b.Height-1 do
          if CEqual(Pixel(x,y)^,RGB(0,0,255)) then //ist irgendwie niemals true =|
            mark := Point(x,y);
      for x := 0 to b.Width-1 do
        for y := 0 to b.Height-1 do
          if (CEqual(Pixel(x,y)^,RGB(255,0,0)))or(CEqual(Pixel(x,y)^,RGB(0,255,0))) then
          begin
            SetLength(MaskRB, Length(MaskRB)+1);
            MaskRB[High(MaskRB)].Equal := CEqual(Pixel(x,y)^,RGB(255,0,0));
            MaskRB[High(MaskRB)].X := x-mark.X;
            MaskRB[High(MaskRB)].Y := y-mark.Y;
          end;

    finally
      b.Free;
    end;
  end;


Ich weiß nun echt keine Rat mehr, da ich ja an sich exakt das gleiche bei edge11 wie bei edge00 mache ... :(
Im Anhang sind die Bitmaps die ich als Ressource einbinde:
Code:
edge00 BITMAP "edge00.bmp"
edge11 BITMAP "edge11.bmp"



MfG bubble


Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

_________________
Wenn Worte nichts als Worte sind,
dann müssen's Steine sein!
Solange - bis sie pleite sind - schmeißt Fensterscheiben ein!

- Fidl Kunterbunt -


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Feb 22, 2011 13:21 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Ließ doch mal die ganzen Blauwerte aus und schau nach welcher drinn steht. Vielleicht ist er nicht 255 sondern 254?

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Feb 22, 2011 13:49 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Die Farbwerte stimmen. Aber geh mal deine Indicies durch. Irgendwo da wird der Fehler liegen, es ist auffällig, dass der blaue Punkt bei edge11 an der oberen Kante liegt. Schau mal, ob er erkannt wird, wenn er einen Pixel weiter unten liegt. Wenn ja, prüf mal deine Indicies.

greetings

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Feb 22, 2011 15:36 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Hu Hu. Auch auf die Gefahr hin mich unbeliebt zu machen. Aber du hast zu mindest einen gravierenden Fehler in deinem Code. Dein TBGR beinhaltet 3 Bytes. Das normale Alignment steht aber auf 4. Also wird deine Struktur vom Compiler erweitert. Also muss das Record packed sein. Ich behaupte jetzt auch einfach mal, dass, wenn dein Rot 254 und dein Grün 253 wäre du kein Blau bekommen würdest mit einem Wert von 255.

Was potentiell problematisch ist ist ein Array[0..0]. Falls jemand die Bereichprüfung aktiv hat (sollte immer der Fall sein) knallt der Code dort. Wie ich finde zu recht. Wenn du die Prüfung deaktiv hast verdeckst du eventuell andere richtige Fehler. Zu mindest ist das aber kein guter Stil. Wie ich finde.

Das Setzen des Pixelformates ist sinnlos. Du setzt zwar das Pixelformat. Allerdings liest du anschließend erst das Bild ein. Damit wird das Pixelformat wieder mit dem Format überbügelt welches in dem Bitmap steht. Also erst laden und dann kann es manipuliert werden. Denn das ist es.

Ob die Berechnungen stimmen keine Ahnung. Ich würde es vom Code her wesentlich einfacher gestalten. Denn so etwas sorgt für mehr klarheit und reduziert mögliche Fehler. Hinzu kommt, dass du das Pixel, CEqual und RGB in jeweils einer Methode hast die du 3-4 mal Pro Pixel aufrufst. Du Berechnest also 3-4 mal die Position und musst das dann immer wieder vergleichen. Der Aufruf einer Methode kostet immer Zeit. Auch wenn es nicht viel ist. Bei einem Code der recht oft aufgerufen wird sumiert sich das recht schnell. RGB ist auch so ein Fall. Du erstellt für jedes Pixel jeweils einmal eine Struktur mit immer den gleichen Werten. Da wäre es sinnvoller die Werte zu mindest in Variablen zu sichern. Es sei denn das soll irgendwann wesentlich dynamischer werden. Aber das kann ich so von deinem Code her nicht erkennen.

Ich würde eine Methode machen an die den Namen und das Array übergibst. Das Array muss dabei ein eigener Typ sein und als var übergeben. In der Methode würde ich das Bitmap laden und dann durch die einzelnen Scanlines durchgehen. Die Scanline wäre dann vom Type PRGB. Wenn du diesen mit Inc erhöhst, dann vergrößert der Compiler den Pointer automatisch um die Größe des Records. Also 3.

Als kleine Optimierung kannst du das auch so machen, dass du zu erst durch alle Pixel gehst und dir die absoluten Positionen und die Position des Blauen speicherst. Anschließend gehst du durch die gefundenen Stellen durch und relativierst die Positionen. Gibt natürlich noch viel viel mehr Optimierungsmöglichkeiten. Aber Aufgrund der jetzigen Größe des Posts spare ich mir das.

Code:
type
  TBGR = packed record
    b,g,r: Byte;
  end;
  PBGR = ^TBGR;

  TMask: Array of TMaskPixel;

procedure Blah(Name: String; var Mask: TMask);
var
  pLine: PRGB;
begin
  SetLength(Mask, 0);

  b := TBitmap.Create;
  try
    b.LoadFromResourceName(hInstance, Name);
    b.PixelFormat := pf24bit;

    for y := 0 to b.Height-1 do begin
      pLine := b.ScanLine[y];

      for x := 0 to b.Width-1 do begin
        if (pLine^.B = 255) then
          // Blau merken
          mark := Point(X, Y)
        else
        if (pLine^.R = 255) or (pLine^.G = 255) then
          begin
            // punkt hinzufügen
            SetLength(Mask, Lenght(Mask) +1);
            Mask[High(Mask)] := ...
          end;

        inc(pLine);
      end;
    end;

    for Idx := Low(Mask) to High(Mask) do begin
      Mask[Idx].X := Mask[Idx].X - mark.X;
      Mask[Idx].Y := Mask[Idx].Y - mark.Y;
    end;
  finally
    b.Free;
  end;
end;

var
  MaskLT, MaskRB: TMask

  Blah('edge00'; MaskLT);
  Blah('edge11'; MaskRB);


So könnte das zum Beispiel aussehen. Ist nur ein Vorschlag. Wie du das machst ist deine Sache. Scanline benutze ich deswegen für jede Zeile seperat, da Bitmapzeilen auch 4Byte aligned sind und du deswegen am Ende einer Zeile auch mal 1-3 Byte Spacer haben kannst. In Abhängigkeit zur Breite des Bitmaps. Eventuell solltest du auch noch überprüfen ob überhaupt ein blauer Pixel gefunden wurde. Wenn nicht musst du deinem Code entsprechend auch reagieren und die Ergebnisse ignorieren oder Fehler werfen.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Feb 25, 2011 10:50 
Offline
DGL Member
Benutzeravatar

Registriert: So Jan 07, 2007 21:26
Beiträge: 130
Wohnort: mal hier mal da mal irgendwo
Im Endeffekt lag es daran dass ich das "packed" bei TBGR vergessen hab :oops:
Es hat dann einwandfrei funktioniert, allerdings klingt Lossy's Empfehlung besser so das ich es nun auch so übernommen habe.

Danke für die Hilfe :]

_________________
Wenn Worte nichts als Worte sind,
dann müssen's Steine sein!
Solange - bis sie pleite sind - schmeißt Fensterscheiben ein!

- Fidl Kunterbunt -


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.008s | 14 Queries | GZIP : On ]