Einzelnen Beitrag anzeigen

McDaTob

Registriert seit: 9. Jan 2005
29 Beiträge
 
#1

Problem mit BITMAPINFO bezüglich des ColorTables

  Alt 20. Feb 2006, 19:30
Hallo,
ich programmiere gerade einen Editor für (vorerst nur) Cursor-Dateien.
Um einen Cursor aus einer Datei zu laden habe ich in meiner Klasse TCursorFile
eine Prodcedure "LoadCursor" definiert. Die Procedure soll dazu dienen, den
Cursor aus der Datei zu laden und anschließend die XOR- und die AND-Maske
in zwei getrennte Bitmaps zur weiteren Bearbeitung zu speichern.
Mein Problem liegt in der procedure SetDIBits. Diese erwartet als Parameter
ein BITMAPINFO record, welcher wie folgt deklariert ist:
Delphi-Quellcode:
  tagBITMAPINFO = packed record
    bmiHeader: TBitmapInfoHeader;
    bmiColors: array[0..0] of TRGBQuad;
  end;
Der BITMAPINFOHEADER kann ganz normal aus der Datei gelesen werden.
Wenn das ColorTable jedoch mehr als einen Eintrag hat, kann ich dieses record
nicht verwenden, weil bmiColors kein dynamisches ist (sondern array[0..0]).
Wie soll man denn dann in einem BITMAPINFO record ein ColorTable unterbringen,
das mehr als einen Eintrag hat?
Habe in meinem Code vorerst ein dynamisches Array vom Typ RGBQUAD als ColorTable definiert,
das dann mittels SetLength auf die richtige Größe gebracht wird. Aber dieses kann ich ja
nicht an SetDIBits übergeben. Ich hoffe mein Problem wird deutlich.

Hier der Code:
Delphi-Quellcode:
type
  TCursorDirEntry = record
    Width : byte;
    Height : byte;
    ColorCount : byte;
    Reserved : byte;
    XHotSpot : word;
    YHotSpot : word;
    BytesInRes : cardinal;
    ImageOffset : cardinal;
  end;

type
  TCursorDir = record
    Reserved : word;
    cdType : word;
    Count : word;
    Entries : array of TCursorDirEntry;
  end;

type
  TCursorImage = record
    XORHeader : BITMAPINFOHEADER;
    ANDHeader : BITMAPINFOHEADER;
    ColorTable : array of RGBQUAD;
    XORDIB : pointer;
    ANDDIB : pointer;
  end;

...

procedure TCursorFile.LoadCursor;
var
  i, j : integer;
  BitmapInfoHeaderOffset : integer;
  BitmapInfoHeaderSize : integer;
  ColorCount : integer;
  XORBmp : TBitmap;
  ANDBmp : TBitmap;
begin
  FileSeek(FFile,0,soFromBeginning);
  FileRead(FFile,FCursorDir.Reserved,SizeOf(word));
  FileRead(FFile,FCursorDir.cdType,SizeOf(word));
  FileRead(FFile,FCursorDir.Count,SizeOf(word)); // CursorDir laden
  SetLength(FCursorDir.Entries,FCursorDir.Count);
  for i := 0 to FCursorDir.Count - 1 do // CursorDirEntries laden
    FileRead(FFile,FCursorDir.Entries[i],SizeOf(TCursorDirEntry));
  SetLength(FCursorImages,FCursorDir.Count);
  for i := 0 to FCursorDir.Count - 1 do // CursorImagesLaden
  begin
    BitmapInfoHeaderOffset := FCursorDir.Entries[i].ImageOffset; // Offset des Image
    FileSeek(FFile,BitmapInfoHeaderOffset,soFromBeginning);
    FileRead(FFile,BitmapInfoHeaderSize,SizeOf(cardinal)); // SizeOf(BITMAPINFOHEADER)
    FileSeek(FFile,BitmapInfoHeaderOffset,soFromBeginning);
    FileRead(FFile,FCursorImages[i].XORHeader,BitmapInfoHeaderSize); // Header auslesen
    if FCursorImages[i].XORHeader.biBitCount = 24 then
    begin
      ColorCount := 0;
    end
    else
    begin
      if FCursorImages[i].XORHeader.biClrUsed = 0 then
      begin
        ColorCount := 1 shl FCursorImages[i].XORHeader.biBitCount; // 2^BitCount
      end
      else
      begin
        ColorCount := FCursorImages[i].XORHeader.biClrUsed;
      end;
    end; // Anzahl Farben im ColorTable festlegen
    SetLength(FCursorImages[i].ColorTable,ColorCount);
    for j := 0 to ColorCount - 1 do // ColorTable auslesen
      FileRead(FFile,FCursorImages[i].ColorTable,SizeOf(RGBQUAD));

    // Höhe von (XOR + AND) halbieren
    FCursorImages[i].XORHeader.biHeight := FCursorImages[i].XORHeader.biHeight div 2;
    // biImageSize des XOR-Header neu berechnen
    FCursorImages[i].XORHeader.biSizeImage := GetImageSize(FCursorImages[i].XORHeader.biWidth,FCursorImages[i].XORHeader.biHeight,FCursorImages[i].XORHeader.biBitCount);
    // XOR-DIBits in den Speicher laden
    GetMem(FCursorImages[i].XORDIB,FCursorImages[i].XORHeader.biSizeImage);
    FileRead(FFile,FCursorImages[i].XORDIB^,FCursorImages[i].XORHeader.biSizeImage);

    // AND-Header mit Daten des XOR-Header füllen
    FCursorImages[i].ANDHeader := FCursorImages[i].XORHeader;
    // biImageSize des AND-Header neu berechnen, 1 Bit
    FCursorImages[i].ANDHeader.biSizeImage := GetImageSize(FCursorImages[i].ANDHeader.biWidth,FCursorImages[i].ANDHeader.biHeight,1);
    // AND-DIBits in den Speicher laden
    GetMem(FCursorImages[i].ANDDIB,FCursorImages[i].ANDHeader.biSizeImage);
    FileRead(FFile,FCursorImages[i].ANDDIB^,FCursorImages[i].ANDHeader.biSizeImage);


    XORBmp := TBitmap.Create;
    XORBmp.Width := FCursorImages[i].XORHeader.biWidth;
    XORBmp.Height := FCursorImages[i].XORHeader.biHeight;

    case FCursorImages[i].XORHeader.biBitCount of
       1 : XORBmp.PixelFormat := pf1bit;
       4 : XORBmp.PixelFormat := pf4bit;
       8 : XORBmp.PixelFormat := pf8bit;
      else XORBmp.PixelFormat := pf24bit;
    end;

// SetDIBits(XORBmp.Canvas.Handle,XORBmp.Handle,0,FCursorImages[i].XORHeader.biHeight,FCursorImages[i].XORDIB,FCursorImages[i].XORHeader,DIB_RGB_COLORS);

// XORBmp.SaveToFile('test.bmp');
    XORBmp.Free;
  end;
end;
  Mit Zitat antworten Zitat