AGB  ·  Datenschutz  ·  Impressum  







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

BMP ohne TBITMAP anzeigen

Ein Thema von kwhk · begonnen am 3. Nov 2016 · letzter Beitrag vom 5. Nov 2016
Antwort Antwort
Benutzerbild von kwhk
kwhk

Registriert seit: 25. Mär 2009
Ort: Dresden
168 Beiträge
 
Delphi 10.3 Rio
 
#1

BMP ohne TBITMAP anzeigen

  Alt 3. Nov 2016, 16:02
Ich bin dabei, ein schon etwas älteres Programm, das in Assembler vorliegt, in Delphi umzusetzen. Das Programm stammt aus der CGA-Zeit, als es toll war, 4 Farben zur Verfügung zu haben: 0=Schwarz, 1=Cyan, 2=Magenta,3=Weiß. 1 Byte enthielt 4 Pixel zu je 2 Bit. Ich benutze jetzt eine BMP mit 256 Farben, wobei von denen nur die ersten 4 verwendet werden, als Farben 0,1,2,3 mit den o.g. Farbwerten in der Color-Tabelle.
Ich erstelle auf diese Weise aus den Pixel-Mustern des Ausgangsprogrammes intern eine BMP für die ich folgenden RECORD angelegt habe
Code:
Type
  TPixelArr   = Array[1..200,1..320] of Byte;

  ThkBMP = RECORD                           // Länge = 65.078 Bytes
    bmf        : TBitMapFileHeader;        //    14 Bytes +    0
    bmi        : TBitMapInfoHeader;        //    40 Bytes +   14
    bmiColors  : Array[0..255] of RGBQUAD; //  1024 Bytes +   54  Rot, Grün, Blau, Res FARB-PALLETTE
    bmPixelArr : TPixelArr;                // 64000 Bytes + 1078  Pixel
  End; // ThkBMP = RECORD                   //             +65078  ---- Ende = Länge der BMP -----

Var
  hkBMP : ThkBMP;


  lpAnfBmpPic : ^TtagBitmapInfo;
  lpPuBmpPIC : ^TPixelArr;
Wenn ich eine derart erzeugt BMP als Datei ausgebe, entsteht genau die gewünschte Datei :
bELEVBIN.BMP

Vor einiger Zeit habe ich mal ein C++ Programm geschrieben und dort Bilddateien derart angezeigt, dass sie immer in das zugehörige Fenster passen. Der betreffende Code sieht folgendermaßen aus:
Code:
   //   ============< (messagePIC) von WndProcPIC >=====================
    case WM_PAINT: // Fenster neu aufbauen
   //   ================================================================
      SetCursor(LoadCursor(NULL, IDC_WAIT));
      hdcPIC = BeginPaint (hwndPIC, &psPIC) ;

      //--------------------------
      //    PIC-Datei anzeigen
      //--------------------------
      lpAnfBmpPic = HoleAnfBmpPic (lpPuBmpPIC) ; // Anfang der Bild-Daten in BMP-Puffer

      SetStretchBltMode (hdcPIC, STRETCH_HALFTONE) ; // Streckmodus

      //    ------------------------------------------------------------------------
      //         Fensteroptimal
      //    ------------------------------------------------------------------------

      fFaktorX = (float) wXmaxFePIC / (float) wBmpBreite ;
      fFaktorY = (float) wYmaxFePIC / (float) wBmpHoehe;

      if ( fFaktorX < fFaktorY )
      {
       wFenBreiX = (WORD) (fFaktorX * (float) wBmpBreite) -10 ;
       wFenHoehY = (WORD) (fFaktorX * (float) wBmpHoehe ) ;
      }
      else
      {
       wFenBreiX = (WORD) (fFaktorY * (float) wBmpBreite) ;
       wFenHoehY = (WORD) (fFaktorY * (float) wBmpHoehe ) -10 ;
      }

      wFenLiObX = (wXmaxFePIC - wFenBreiX ) >> 1 ;
      wFenLiObY = (wYmaxFePIC - wFenHoehY ) >> 1 ;

      StretchDIBits ( hdcPIC,                     // DIB-Quelle in ZIEL-Fenster angepaßt
                      wFenLiObX,                  // X-Ursprung-Fenster
                      wFenLiObY,                  // Y-Ursprung-Fenster
                      wFenBreiX,                  // Fenster-Breite
                      wFenHoehY,                  // Fenster-Höhe
                      0,                          // X-Ursprung-BMP
                      0,                          // Y-Ursprung-BMP
                      wBmpBreite,                 // X-Breite BMP
                      wBmpHoehe,                  // Y-Höhe  BMP
                      (LPSTR)       lpAnfBmpPic, // Anf Bild-Daten in BMP-Pu
                      (LPBITMAPINFO) lpPuBmpPIC,  // BITMAPINFOHEADER
                      DIB_RGB_COLORS,             // Die Farb-Tab enthält RGB-Werte
                      SRCCOPY ) ;                 // Operation: Quelle => Ziel kopieren

      EndPaint (hwndPIC, &psPIC) ;
      SetCursor (LoadCursor (NULL, IDC_ARROW)) ; // Pfeil-Cursor

      return 0 ;
Ich möchte in dem Delphi-Programm die einzelnen Spiel-Teile mit den vorhandenen AND/OR-Masken realisieren, dazu dürfen die Farben aber nur 0..3 sein. Wenn ich die BMP in eine TBITMAP bringe, stimmen die Farben nicht mehr, ich kann die Pixel nicht verändern (in meinem RECORD kann ich das problemlos machen), TBITMAP kann ich nicht nutzen. Das kleine 320x200 Bild möchte ich jeweils um den Faktor 3 in ein 960x600 Bild vergrößert anzeigen, das kann StretchDIBits sehr gut und schnell machen.

Mein BMP-RECORD ist genau so aufgebaut, wie in dem C++ Programm. Er ist voll identisch mit der BMP-Datei. Wenn ich unter Delphi 7 die BMP aus dem RECORD mit Hilfe von StretchDIBits anzeigen will, dann bekomme ich immer Umwandlungsfehlermeldungen. Dazu benötige ich eine fachkundige Hilfe.
Code:
    lpAnfBmpPic := @(hkBMP.bmi);
    lpPuBmpPIC := @(hkBMP.bmPixelArr);

    StretchDIBits ( Form1.Handle,  // DIB-Quelle in ZIEL-Fenster angepaßt
                    10,            // X-Ursprung-Fenster
                    10,            // Y-Ursprung-Fenster
                    960,           // Fenster-Breite
                    600,           // Fenster-Höhe
                    0,             // X-Ursprung-BMP
                    0,             // Y-Ursprung-BMP
                    320,           // X-Breite BMP
                    200,           // Y-Höhe  BMP
                    lpAnfBmpPic,   // Anf Bild-Daten in hkBMP+1078
                    lpPuBmpPIC,    // BitMapInfoHeader     <== Hier wird der Fehler angezeigt
                    DIB_RGB_COLORS, // Die Farb-Tab enthält RGB-Werte
                    SRCCOPY ) ;    // Operation: Quelle => Ziel kopieren
[Fehler] Soko1u.pas(301): Die Typen der tatsächlichen und formalen Var-Parameter müssen übereinstimmen
Hartmut

Geändert von kwhk ( 3. Nov 2016 um 16:11 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#2

AW: BMP ohne TBITMAP anzeigen

  Alt 3. Nov 2016, 16:23
tja ein Window Handle ist nun mal nicht gleich HDC (handle zum Destination Device Context).
Siehe Form1.Handle
Sollte wohl Form1.Canvas.Handle sein. (oder über API = GetDC(Form1.Handle))

Es steht doch dahinter..
Zitat:
lpPuBmpPIC, // BitMapInfoHeader
Ist denn lpPuBmpPIC der pointer auf den BitMapInfoHeader? Denke mal nicht..
Du kannst für den Typ BITMAPINFO keinen Pointer auf ein PixelArray übergeben.
Wenn dann "@bmi" vorrausgesetzt bmi ist als tagBITMAPINFO definiert.

gruss

Geändert von EWeiss ( 3. Nov 2016 um 16:39 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von kwhk
kwhk

Registriert seit: 25. Mär 2009
Ort: Dresden
168 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: BMP ohne TBITMAP anzeigen

  Alt 3. Nov 2016, 16:55
Danke für die Antwort.
Bei den Zuweisungen der beiden Pointer habe ich offenbar etwas verwechselt. Ich habe es nun ausgetauscht, weiterhin kommt der Umwandlungsfehler. Jetzt sieht es so aus
Code:
    lpAnfBmpPic := @(hkBMP.bmPixelArr);
    lpPuBmpPIC := @(hkBMP.bmi);
{}
    StretchDIBits ( Form1.Canvas.Handle,      // DIB-Quelle in ZIEL-Fenster angepaßt
                    10,                // X-Ursprung-Fenster
                    10,                // Y-Ursprung-Fenster
                    960,               // Fenster-Breite
                    600,               // Fenster-Höhe
                    0,                 // X-Ursprung-BMP
                    0,                 // Y-Ursprung-BMP
                    320,               // X-Breite BMP
                    200,               // Y-Höhe  BMP
                    lpAnfBmpPic,       // Anf Bild-Daten in hkBMP+1078
                    lpPuBmpPIC,        // BitMapInfoHeader
                    DIB_RGB_COLORS,    // Die Farb-Tab enthält RGB-Werte
                    SRCCOPY ) ;        // Operation: Quelle => Ziel kopieren
Code:
tagBITMAPINFO = packed record
     bmiHeader: TBitmapInfoHeader;
     bmiColors: array[0..0] of TRGBQuad;
   end;
tagBITMAPINFO habe ich bewusst nicht benutzt, weil durch das darin enthaltene bmiColors-Array der Record um 4 Bytes zu lang war.
Ein Zeiger auf TBitMapInfoHeader ist adressmäßig identisch mit einem Zeiger auf tagBitMapInfo. In meinem Record kommen nach dem BitmapInfoHeader ja sofort die Colors für 256 Farben.
Hartmut
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#4

AW: BMP ohne TBITMAP anzeigen

  Alt 3. Nov 2016, 17:04
Zitat:
Ich habe es nun ausgetauscht, weiterhin kommt der Umwandlungsfehler.
ich hoffe das du auch die Definition von

lpPuBmpPIC : ^TPixelArr;

geändert hast.
Zitat:
tagBITMAPINFO habe ich bewusst nicht benutzt
Sehr seltsam denn ich kann sehen das du es verwendest in deinem Record..
bmi : TBitMapInfoHeader; // 40 Bytes + 14
StretchDIBits

gruss

Geändert von EWeiss ( 3. Nov 2016 um 17:14 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von kwhk
kwhk

Registriert seit: 25. Mär 2009
Ort: Dresden
168 Beiträge
 
Delphi 10.3 Rio
 
#5

AW: BMP ohne TBITMAP anzeigen

  Alt 3. Nov 2016, 17:32
Nochmals DANKE.
Ich habe alles nochmal durchgesehen und die Verwechselungen beseitigt. Jetzt funktioniert es.
Hier noch einmal der berichtigte Code. ich habe nach dem tagBitmapInfo nur noch die Colors 1..255 definiert, weil [0,0] bereits in tagBitmapInfo enthalten ist.
Code:
  TPixelArr   = Array[1..200,1..320] of Byte;

  ThkBMP = RECORD // Länge = 65.078 Bytes
    bmf        : TBitMapFileHeader;        //    14 Bytes +    0
    bminfo     : tagBitmapInfo;            //    44 Bytes +   14
    bmiColors2  : Array[1..255] of RGBQUAD; //  1020 Bytes +   58   Rot, Grüm, Blau FARB-PALLETTE
    bmPixelArr : TPixelArr;                // 64000 Bytes + 1078  Pixel
  End; // ThkBMP = RECORD                   //             +65078  ---- Ende der BMP -----

Var
  hkBMP : ThkBMP;
Die Pointer-Variablen habe ich weggelassen und stattdessen die Angaben direkt eingetragen
Code:
    StretchDIBits ( Form1.Canvas.Handle, // DIB-Quelle in ZIEL-Fenster angepaßt
                    10,                 // X-Ursprung-Fenster
                    10,                 // Y-Ursprung-Fenster
                    960,                // Fenster-Breite
                    600,                // Fenster-Höhe
                    0,                  // X-Ursprung-BMP
                    0,                  // Y-Ursprung-BMP
                    320,                // X-Breite BMP
                    200,                // Y-Höhe  BMP
                    @(hkBMP.bmPixelArr), // Anf Bild-Daten in hkBMP+1078
                    hkBMP.bminfo,       // tagBitMapInfo
                    DIB_RGB_COLORS,     // Die Farb-Tab enthält RGB-Werte
                    SRCCOPY ) ;         // Operation: Quelle => Ziel kopieren
Ich hoffe, ich darf noch eine Zusatzfrage stellen...

Gibt es eine Möglichkeit, Farbcodes direkt in Bmp.Canvas.Pixels einzutragen, wenn man statt einem RECORD, wie ich es gemacht habe, TBITMAP verwendet und kann man auch auf die Einträge in der Colortabelle Einfluss nehmen ?
Ich habe das versucht, es gibt keinen Fehler, aber in der erzeugten BMP stehen nicht die von mir gewünschten Farbeinträge, sondern nahezu alles ist 0.
Code:
Procedure MakeBMP2;
  Var
    Bmp : TBitmap;
    yZei, xSpa, i : Integer;
    by : Byte;
    H : HPalette;
    P : PLogPalette;
  Begin
    Bmp := TBitmap.Create;
    Bmp.Width := 320;
    Bmp.Height := 200;
    Bmp.PixelFormat := pf8bit;

    GetMem(P, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 255));

    P.palVersion := $300;
    P.palNumEntries := 256;

    for i := 0 to 255 do
      Begin
        P.palPalEntry[i].peFlags := 0;
        Case i of
          0: Begin
               P.palPalEntry[i].peBlue    := $00; // 0 = Schwarz
               P.palPalEntry[i].peGreen   := $00;
               P.palPalEntry[i].peRed     := $00;
             End;
          1: Begin
               P.palPalEntry[i].peBlue    := $FF; // 1 = CYAN
               P.palPalEntry[i].peGreen   := $FF;
               P.palPalEntry[i].peRed     := $00;
             End;
          2: Begin
               P.palPalEntry[i].peBlue    := $FF; // 2 = Magenta
               P.palPalEntry[i].peGreen   := $00;
               P.palPalEntry[i].peRed     := $FF;
             End;
          3: Begin
               P.palPalEntry[i].peBlue    := $FF; // 3 = Weiss
               P.palPalEntry[i].peGreen   := $FF;
               P.palPalEntry[i].peRed     := $FF;
             End;
          else
             Begin
               P.palPalEntry[i].peRed  := 0;
               P.palPalEntry[i].peGreen := 0;
               P.palPalEntry[i].peBlue := 0;
             End;
        End; // Case
      End;

    H := CreatePalette(P^);

    if H <> 0 then
      Bmp.Palette := H;

    for yZei := 1 to 200 do
      Begin
        for xSpa := 1 to 320 do
          Begin
            by := ELEVBINarr[yZei,xSpa];
            Bmp.Canvas.Pixels[xSpa-1,yZei-1] := by;
          End; // for xSpa
      End; // for yZei

    Bmp.SaveToFile(DsnBMP2);

    FreeMem(P);
  End;
Hartmut

Geändert von kwhk ( 3. Nov 2016 um 17:51 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#6

AW: BMP ohne TBITMAP anzeigen

  Alt 5. Nov 2016, 12:10
lade dir mal mein Projekt
Dort findest du eine Unit Palette..

Verfolge einfach mal wie die Palette initialisiert wird.
Danach sollten deine Fragen eigentlich beantwortet sein.

Nebenbei!
Für neue Fragen sind neue Threads allemal besser als zusätzliche Fragen anzuhängen..
Meistens liest das dann keiner mehr.

gruss
  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 06:18 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