AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

BitMap zeichnen per API

Ein Thema von sintronic86 · begonnen am 27. Nov 2012 · letzter Beitrag vom 5. Dez 2012
Antwort Antwort
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#1

AW: BitMap zeichnen per API

  Alt 27. Nov 2012, 14:32
Du hast 3 Farbkanäle, die jeweils 1 Byte belegen, sprich 1 Farbpunkt belegt 3*1 = 3 Bytes.. Für jeden Farbpunkt pro Scanline musst du 3 Bytes kopieren. Dh. Breite * 3 kommt da rein.

Weiters ist mir persönlich aufgefallen, dass, wenn du die Scanlines ein einziges mal beim setzen der Dimensionen holst bzw zwischenpufferst, das ganze viel schneller läuft, als wenn du es jedes mal per Bitmap.Scanline[i] ne abfragst. Ich glaub der holt sich dann den jeweiligen Pointer per API Befehle, was unnötig ist!
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
sintronic86

Registriert seit: 7. Dez 2009
Ort: Barsinghausen
90 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

AW: BitMap zeichnen per API

  Alt 27. Nov 2012, 14:41
@Aphton:
Ok, Breite mal 3: macht Sinn. Aber das würde doch an dem Problem nichts ändern, das ich nicht einfach sagen kann:

TmpALine := OLEVARIANT[I]

da ich damit ja die erste Spalte, statt Zeile anspreche.
Aber davon abgesehen, bekomme ich bei diesem Zugriff auch eine Fehlermeldung:

---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt XXXXXXX.exe ist eine Exception der Klasse EVariantBadIndexError mit der Meldung 'Variante oder sicheres Array-Index außerhalb des gültigen Bereichs' aufgetreten.
---------------------------
Anhalten Fortsetzen Hilfe
---------------------------


Diese kann ich mir aber nicht erklären, da der Zugriff im selben Moment auf OLEVARIANT[I,0] einen
gültigen Wert herausgiebt!

Ich bin echt am verzweifeln. Habe jetzt ein wenig mit BitBlt herumgespielt, und bekomme es hin,
von einem Image in eine Paintbox zu kopieren. Allerdings wüsste ich nicht, wie ich dort mein OleVariant unterbringen kann.
Björn
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.490 Beiträge
 
Delphi 12 Athens
 
#3

AW: BitMap zeichnen per API

  Alt 27. Nov 2012, 16:18
Irgendwie ist der Code seltsam, warum läuft deine I-Schleife gegen Null?
Im Array ist zu jedem Pixel nur ein Byte aufgezeichnet (Graustufen vermutlich).
Du baust daraus ein TmpRGB, verwendest danach aber nur das unteren Byte von TmpRGB.
Dieses wird für jeden Farbkanal einzeln geschrieben (BGR, Pixelformat pf24Bit).

Das geht auch einfacher:
Delphi-Quellcode:
var
  TmpLine: PByte;
  TmpByte: Byte;

for I := 0 to BILDHÖHE - 1 do
begin
  TmpLine := BITMAP.ScanLine[I];

  for J := 0 to BILDBREITE - 1 do
  begin
    TmpByte := OLEVARIANT[I, J]; // Grau
    TmpLine^ := TmpByte; // Blau
    Inc(TmpLine);
    TmpLine^ := TmpByte; // Gruen
    Inc(TmpLine);
    TmpLine^ := TmpByte; // Rot
    Inc(TmpLine);
  end;
end;
Ist das noch nicht schnell genug, wirds komplizierter:
- Pixelformat der Bitmap auf 256Farben mit Palette umgestellt
- Palette mit 256 Graustufen erstellen und für die Bitmap auswählen
- mit SafeArrayLock() und SafeArrayAccessData() einen Pointer auf die Daten des Variant besorgen
- die Daten direkt in die Bitmap kopieren
- mit SafeArrayUnaccessData() und SafeArrayUnlock() den Variant wieder entsperren
  Mit Zitat antworten Zitat
nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#4

AW: BitMap zeichnen per API

  Alt 27. Nov 2012, 17:02
Irgendwie ist der Code seltsam, warum läuft deine I-Schleife gegen Null?
Werden BMPs nicht kopfüber gespeichert?
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.688 Beiträge
 
Delphi 2007 Enterprise
 
#5

AW: BitMap zeichnen per API

  Alt 27. Nov 2012, 20:33
Fast immer. Fast! Windows bot da irgend einen Weg heruaszufinden, wie es denn nun wirklich hinterlegt ist (ich weiss leider echt nicht mehr was das genau war, aber es stand im MSDN (nicht in den Kommentaren)), aber es gibt wohl ganz selten mal den Fall, dass dem nicht so ist. Ob und wann genau das eintritt stand dort leider nicht, und mir sind bisher auch noch keine "richtig-falsch-herumen" Bitmaps begegnet. Das aber nur am Rande
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.490 Beiträge
 
Delphi 12 Athens
 
#6

AW: BitMap zeichnen per API

  Alt 28. Nov 2012, 08:21
In welcher Reihenfolge die Bildzeilen im Speicher liegen, wird nicht dadurch beeinflusst, in welcher Reihenfolge ich diese kopiere.
Sowohl auf das Variantarray als auch auf ScanLine wird mit dem Index "I" zugegriffen.
Um das Bild vertikal zu spiegeln müsste genau einer der Zugriffe auf "BILDHÖHE - 1 - I" umgestellt werden.

ScanLine berücksichtigt bereits die Ausrichtung der Bilddaten im Speicher.
Scanline[0] ist immer die oberste Zeile, auch wenn diese im Speicher an letzter Stelle liegt.
Die Ole-Schnittstelle legt die Daten vermutlich in der richtigen Reihenfolge im Array ablegt.
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#7

AW: BitMap zeichnen per API

  Alt 28. Nov 2012, 09:35
Eine Möglichkeit könnte ich mir so vorstellen:


Delphi-Quellcode:
var
  theBitmapBitArray: array of dword; // das array vom OleVariant

procedure TForm ...;
var
  theBitmap: HBITMAP;
  pBmpBits: Pointer;
  bi: BITMAPINFO;

  bmpWidth: integer;
  bmpHeight: integer;

begin
  bmpWidth := 320;
  bmpHeight := 240;

  setlength(theBitmapBitArray, bmpWidth * bmpHeight);

  // ----------------------------------------------------------- //

  ZeroMemory(@bi, sizeof(BITMAPINFO));
  with bi.bmiHeader do
  begin
    biSize := sizeof(BITMAPINFOHEADER);
    biWidth := bmpWidth;
    biHeight := -bmpHeight;
    biCompression := BI_RGB;
    biBitCount := 32;
    biPlanes := 1;
    biXPelsPerMeter := 0;
    biYPelsPerMeter := 0;
    biClrUsed := 0;
    biClrImportant := 0;
  end;

  theBitmap := CreateDIBSection(0, bi, DIB_RGB_COLORS, pBmpBits, 0, 0);

  pBmpBits := @theBitmapBitArray[0];

  SetDIBits(0, theBitmap, 0, bi.bmiHeader.biHeight * -1, pBmpBits, bi, DIB_RGB_COLORS);

  image1.Picture.Bitmap.Handle := theBitmap;
  image1.Refresh;
end;
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser

Geändert von turboPASCAL (28. Nov 2012 um 09:52 Uhr)
  Mit Zitat antworten Zitat
sintronic86

Registriert seit: 7. Dez 2009
Ort: Barsinghausen
90 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#8

AW: BitMap zeichnen per API

  Alt 5. Dez 2012, 12:12
Vielen Dank für die vielen Antworten.

Da ich aber auf dem "Zu-Fuss"-Weg nicht wirklich weitergekommen bin, habe ich mich einmal mit der Funktion StretchDIBits() genauer auseinander gesetzt.
Und siehe da: Es funktioniert.

Code:
  if FCanDraw then
  begin
    TmpBitMap       := TBitmap.Create;
    TmpBitMap.Width := FWidth_Cam;
    TmpBitMap.Height := FHeight_Cam;


    test2 := AOleVariant;

    SetStretchBltMode(TmpBitMap.Canvas.Handle, COLORONCOLOR);
    StretchDIBits(TmpBitMap.Canvas.Handle,
                  0,
                  0,
                  FWidth_Cam,
                  FHeight_Cam,
                  0,
                  0,
                  FWidth_Cam,
                  FHeight_Cam,
                  test2,
                  TmpBI,
                  DIB_RGB_COLORS,
                  SRCCOPY);



    AImage.Picture.Assign(TmpBitMap);
    TmpBitMap.Free;
  end
  else
  begin
    AImage.Picture.Assign(NIL);
  end;
Björn
  Mit Zitat antworten Zitat
Antwort Antwort

 

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 08:53 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz