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;