MMDIB.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:37k
- {========================================================================}
- {= (c) 1995-98 SwiftSoft Ronald Dittrich =}
- {========================================================================}
- {= All Rights Reserved =}
- {========================================================================}
- {= D 01099 Dresden = Tel.: +0351-8012255 =}
- {= Loewenstr.7a = info@swiftsoft.de =}
- {========================================================================}
- {= Actual versions on http://www.swiftsoft.de/mmtools.html =}
- {========================================================================}
- {= This code is for reference purposes only and may not be copied or =}
- {= distributed in any format electronic or otherwise except one copy =}
- {= for backup purposes. =}
- {= =}
- {= No Delphi Component Kit or Component individually or in a collection=}
- {= subclassed or otherwise from the code in this unit, or associated =}
- {= .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed =}
- {= without express permission from SwiftSoft. =}
- {= =}
- {= For more licence informations please refer to the associated =}
- {= HelpFile. =}
- {========================================================================}
- {= $Date: 20.01.1998 - 18:00:00 $ =}
- {========================================================================}
- unit MMDIB;
- {$I COMPILER.INC}
- interface
- uses
- {$IFDEF WIN32}
- Windows,
- {$ELSE}
- WinProcs,
- WinTypes,
- {$ENDIF}
- SysUtils,
- MMSystem,
- MMUtils;
- const
- {$IFDEF CBUILDER3} {$EXTERNALSYM BFT_ICON } {$ENDIF}
- BFT_ICON = $4349; { 'IC' }
- {$IFDEF CBUILDER3} {$EXTERNALSYM BFT_BITMAP } {$ENDIF}
- BFT_BITMAP = $4d42; { 'BM' }
- {$IFDEF CBUILDER3} {$EXTERNALSYM BFT_CURSOR } {$ENDIF}
- BFT_CURSOR = $5450; { 'PT' }
- {$IFDEF CBUILDER3} {$EXTERNALSYM BI_BITFIELDS } {$ENDIF}
- BI_BITFIELDS = 3;
- {$IFDEF CBUILDER3} {$EXTERNALSYM HALFTONE } {$ENDIF}
- HALFTONE = COLORONCOLOR;
- { flags for _lseek }
- {$IFDEF CBUILDER3} {$EXTERNALSYM SEEK_CUR } {$ENDIF}
- SEEK_CUR = 1;
- {$IFDEF CBUILDER3} {$EXTERNALSYM SEEK_END } {$ENDIF}
- SEEK_END = 2;
- {$IFDEF CBUILDER3} {$EXTERNALSYM SEEK_SET } {$ENDIF}
- SEEK_SET = 0;
- { flags for orientation }
- TOPDOWN = -1;
- BOTTOMUP = 1;
- type
- PRGBQUAD = ^TRGBQUAD;
- PDIB = PBitmapInfoHeader;
- HDIB = THandle;
- (************************************************************************)
- procedure ClearSystemPalette;
- function CreateSystemColorPalette: PLogPalette;
- function LoadPalette(FName: string): PLOGPALETTE;
- function SavePalette(FName: string; pLogPal: PLOGPALETTE): Boolean;
- (************************************************************************)
- function DIB_Create(bits, orientation, width, height: integer; AllocBits: Boolean): PDIB;
- function DIB_ReadBitmapInfo(fh: THandle): PDIB;
- function DIB_OpenFile(szFile: PChar): PDIB;
- function DIB_SetUsage(pbi: PDIB; hPal: HPALETTE; wUsage: UINT): Boolean;
- procedure DIB_MapToPalette(var pbi: PDIB; hpal: HPALETTE);
- procedure DIB_Display(pbi: PDIB; DC: HDC; aRect: TRect);
- function DIB_BitmapToDIB(Handle: HBitmap; Palette: HPalette;
- Bits, Orientation: integer): PDIB;
- procedure DIB_DIBToBitmap(pbi: PDIB; var Bitmap: HBitmap;
- var Pal: HPalette);
- (************************************************************************)
- function IsWinDIB(pbi: PBITMAPINFOHEADER): Boolean;
- function HandleFrom_DIB(lpbi: PDIB): THandle;
- function DIB_FromHandle(h: THandle): PDIB;
- procedure DIB_Free(lpbi: PDIB);
- function DIB_Width(lpbi: PDIB): integer;
- function DIB_Height(lpbi: PDIB): integer;
- function DIB_BitCount(lpbi: PDIB): integer;
- function DIB_Compression(lpbi: PDIB): Longint;
- function DIB_NumColors(lpbi: PDIB): Longint;
- function DIB_WidthBytesN(lpbi: PDIB; n: integer): Longint;
- function DIB_WidthBytes(lpbi: PDIB): Longint;
- function DIB_BISize(lpbi: PDIB): integer;
- function DIB_SizeImage(lpbi: PDIB): Longint;
- function DIB_Size(lpbi: PDIB): Longint;
- function DIB_PaletteSize(lpbi: PDIB): DWORD;
- function DIB_FlipY(lpbi: PDIB; y: integer): integer;
- function DIB_Colors(lpbi: PDIB): PRGBQUAD;
- function DIB_Ptr(lpbi: PDIB): Pointer;
- function DIB_XYN(lpbi: PDIB; pb: Pointer; x,y,n: integer): Pointer;
- function DIB_XY(lpbi: PDIB;x,y: integer): Pointer;
- function DIB_Info(pDIB: PDIB): PBitmapInfo;
- implementation
- {$IFNDEF WIN32}
- function _hread(hFile: THANDLE; lpBuffer: Pointer; lBytes: Longint): Longint;
- Far; external 'KERNEL' name '_hread';
- {$ENDIF}
- (************************************************************************)
- function IsWinDIB(pbi: PDIB): Boolean;
- begin
- if (pbi^.biSize <> sizeof(TBITMAPINFOHEADER)) then
- Result := False
- else
- Result := True;
- end;
- (************************************************************************)
- function HandleFrom_DIB(lpbi: PDIB): THandle;
- begin
- {$IFDEF WIN32}
- Result := GlobalHandle(lpbi);
- {$ELSE}
- Result := GlobalHandle(SELECTOROF(lpbi));
- {$ENDIF}
- end;
- (************************************************************************)
- function DIB_FromHandle(h: THandle): PDIB;
- begin
- Result := GlobalLock(h);
- end;
- (************************************************************************)
- procedure DIB_Free(lpbi: PDIB);
- begin
- if (lpbi <> nil) then GlobalFreePtr(lpbi);
- end;
- (************************************************************************)
- function WIDTHBYTES(i: Longint): Longint;
- begin
- Result := ((i+31) and not 31) div 8; { DWORD aligned ! }
- end;
- (************************************************************************)
- function DIB_Width(lpbi: PDIB): integer;
- begin
- Result := lpbi^.biWidth;
- end;
- (************************************************************************)
- function DIB_Height(lpbi: PDIB): integer;
- begin
- Result := lpbi^.biHeight;
- end;
- (************************************************************************)
- function DIB_BitCount(lpbi: PDIB): integer;
- begin
- if IsWinDIB(lpbi) then
- Result := lpbi^.biBitCount
- else
- Result := PBitmapCoreHeader(lpbi)^.bcBitCount;
- end;
- (************************************************************************)
- function DIB_Compression(lpbi: PDIB): Longint;
- begin
- Result := lpbi^.biCompression;
- end;
- (************************************************************************)
- function DIB_NumColors(lpbi: PDIB): Longint;
- begin
- if (lpbi^.biClrUsed = 0) and (lpbi^.biBitCount <= 8) then
- Result := (1 shl lpbi^.biBitCount)
- else
- Result := lpbi^.biClrUsed;
- end;
- (************************************************************************)
- function DIB_WidthBytesN(lpbi: PDIB; n: integer): Longint;
- begin
- Result := WIDTHBYTES(lpbi^.biWidth * Long(n));
- end;
- (************************************************************************)
- function DIB_WidthBytes(lpbi: PDIB): Longint;
- begin
- Result := DIB_WidthBytesN(lpbi, lpbi^.biBitCount);
- end;
- (************************************************************************)
- function DIB_BISize(lpbi: PDIB): integer;
- begin
- Result := lpbi^.biSize + DWORD(DIB_PaletteSize(lpbi));
- end;
- (************************************************************************)
- function DIB_SizeImage(lpbi: PDIB): Longint;
- begin
- if (lpbi^.biSizeImage = 0) then
- Result := DIB_WidthBytes(lpbi) * Long(lpbi^.biHeight)
- else
- Result := lpbi^.biSizeImage;
- end;
- (************************************************************************)
- function DIB_Size(lpbi: PDIB): Longint;
- begin
- Result := lpbi^.biSize + lpbi^.biSizeImage + (lpbi^.biClrUsed * sizeof(TRGBQUAD));
- end;
- (************************************************************************)
- function DIB_PaletteSize(lpbi: PDIB): DWORD;
- begin
- Result := DIB_NumColors(lpbi) * sizeof(TRGBQUAD);
- end;
- (************************************************************************)
- function DIB_FlipY(lpbi: PDIB; y: integer): integer;
- begin
- Result := lpbi^.biHeight-1-y;
- end;
- (************************************************************************)
- function DIB_Colors(lpbi: PDIB): PRGBQUAD;
- begin
- Result := PRGBQUAD(PChar(lpbi) + lpbi^.biSize);
- end;
- (************************************************************************)
- function DIB_Ptr(lpbi: PDIB): Pointer;
- begin
- {$IFDEF WIN32}
- { HACK for NT BI_BITFIELDS DIBs }
- if (lpbi^.biCompression = BI_BITFIELDS) then
- Result := PChar(DIB_Colors(lpbi)) + 3 * sizeof(TRGBQUAD)
- else
- {$ENDIF}
- Result := PChar(DIB_Colors(lpbi)) + lpbi^.biClrUsed * sizeof(TRGBQUAD);
- end;
- (************************************************************************)
- function DIB_XYN(lpbi: PDIB; pb: Pointer; x,y,n: integer): Pointer;
- begin
- Result := pb;
- incHuge(Result,Long(x)*Long(n) div Long(8)+DIB_WidthBytesN(lpbi,n)*Long(y));
- end;
- (************************************************************************)
- function DIB_XY(lpbi: PDIB;x,y: integer): Pointer;
- begin
- Result := DIB_XYN(lpbi,DIB_Ptr(lpbi),x,y,lpbi^.biBitCount);
- end;
- (************************************************************************)
- procedure FixBitmapInfo(lpbi: PDIB);
- begin
- if (lpbi^.biSizeImage = 0) then
- lpbi^.biSizeImage := DIB_SizeImage(lpbi);
- if (lpbi^.biClrUsed = 0) then
- lpbi^.biClrUsed := DIB_NumColors(lpbi);
- if (lpbi^.biCompression = BI_BITFIELDS) and (lpbi^.biClrUsed = 0) then
- lpbi^.biClrUsed := 3;
- end;
- (************************************************************************)
- function DIB_Info(pDIB: PDIB): PBitmapInfo;
- begin
- Result := Pointer(pDIB);
- end;
- (************************************************************************)
- (* Clear the System Palette so that we can ensure an identity palette *)
- (* mapping for fast performance. *)
- (************************************************************************)
- procedure ClearSystemPalette;
- type
- { Logical Palette }
- TLogPal = record
- palVersion: Word;
- palNumEntries: Word;
- palEntry: array[0..256] of TPaletteEntry;
- end;
- var
- i: integer;
- LogPal: TLogPal;
- ScreenPal: HPalette;
- ScreenDC: HDC;
- begin
- with LogPal do
- begin
- palVersion := $300;
- palNumEntries := 256;
- { Reset everything in the system palette to black }
- for i := 0 to 255 do
- begin
- palEntry[i].peRed := 0;
- palEntry[i].peGreen := 0;
- palEntry[i].peBlue := 0;
- palEntry[i].peFlags := PC_NOCOLLAPSE;
- end;
- { Create, select, realize, deselect, and delete the palette }
- ScreenDC := GetDC(0);
- ScreenPal := CreatePalette(PLogPalette(@LogPal)^);
- if (ScreenPal <> 0) then
- begin
- ScreenPal := SelectPalette(ScreenDC,ScreenPal,False);
- RealizePalette(ScreenDC);
- ScreenPal := SelectPalette(ScreenDC,ScreenPal,False);
- DeleteObject(ScreenPal);
- end;
- ReleaseDC(0, ScreenDC);
- end;
- end;
- (************************************************************************)
- function CreateSystemColorPalette: PLogPalette;
- type
- { Logical Palette }
- PLogPal = ^TLogPal;
- TLogPal = record
- palVersion: Word;
- palNumEntries: Word;
- palEntry: array[0..256] of TPaletteEntry;
- end;
- var
- DC: HDC;
- Size: integer;
- pPal: PLogPal;
- begin
- { Get a screen DC to work with }
- DC := GetDC(0);
- try
- { allocate a log pal and fill it with the color table info }
- Size := sizeof(TLogPalette) + 256 * sizeOf(TPaletteEntry);
- pPal := GlobalAllocMem(Size);
- FillChar(pPal^, Size, 0);
- with pPal^ do
- begin
- palVersion := $300; { Windows 3.0 }
- palNumEntries := 256; { table size }
- { Make sure we are on a palettized device }
- if (GetDeviceCaps(DC, RASTERCAPS) and RC_PALETTE <> 0) and
- (GetDeviceCaps(DC, NUMCOLORS) <= 256) then
- begin
- { Get the system colors in the first and last 10 slots }
- GetSystemPaletteEntries(DC, 0, 10, palEntry);
- GetSystemPaletteEntries(DC, 246, 10, palEntry[246]);
- end
- else
- begin
- { set the entrys by hand }
- Longint(palEntry[0]) := RGB($00,$00,$00); { black }
- Longint(palEntry[1]) := RGB($80,$00,$00); { dark red }
- Longint(palEntry[2]) := RGB($00,$80,$00); { dark green }
- Longint(palEntry[3]) := RGB($80,$80,$00); { dark yellow }
- Longint(palEntry[4]) := RGB($00,$00,$80); { dark blue }
- Longint(palEntry[5]) := RGB($80,$00,$80); { dark magneta }
- Longint(palEntry[6]) := RGB($00,$80,$80); { dark cyan }
- Longint(palEntry[7]) := RGB($C0,$C0,$C0); { light gray }
- Longint(palEntry[8]) := RGB($C0,$DC,$C0); { money green }
- Longint(palEntry[9]) := RGB($A6,$CA,$F0); { sky blue }
- Longint(palEntry[246]):= RGB($FF,$FB,$F0); { cream }
- Longint(palEntry[247]):= RGB($A0,$A0,$A4); { medium gray }
- Longint(palEntry[248]):= RGB($80,$80,$80); { dark gray }
- Longint(palEntry[249]):= RGB($FF,$00,$00); { red }
- Longint(palEntry[250]):= RGB($00,$FF,$00); { green }
- Longint(palEntry[251]):= RGB($FF,$FF,$00); { yellow }
- Longint(palEntry[252]):= RGB($00,$00,$FF); { blue }
- Longint(palEntry[253]):= RGB($FF,$00,$FF); { magneta }
- Longint(palEntry[254]):= RGB($00,$FF,$FF); { cyan }
- Longint(palEntry[255]):= RGB($FF,$FF,$FF); { white }
- end;
- end;
- finally
- ReleaseDC(0,DC);
- end;
- Result := PLogPalette(pPal);
- end;
- {$IFNDEF WIN32}
- const
- HFILE_ERROR = -1;
- {$ENDIF}
- (************************************************************************)
- (* Open a DIB file and return a MEMORY DIB, a memory handle containing..*)
- (************************************************************************)
- function DIB_OpenFile(szFile: PChar): PDIB;
- var
- fh: THandle;
- dwLen: DWORD;
- dwBits: DWORD;
- pd: PDIB;
- p: Pointer;
- ofs: TOFSTRUCT;
- h: THandle;
- begin
- Result := nil;
- fh := OpenFile(szFile, ofs, OF_READ);
- if (fh = HFILE_ERROR) then
- begin
- h := FindResource(HInstance, szFile, RT_BITMAP);
- if (h <> 0) then
- begin
- {$IFDEF WIN32}
- { !!! can we call GlobalFree() on this? is it the right format. }
- { !!! can we write to this resource? }
- Result := PDIB(LockResource(LoadResource(HInstance, h)));
- exit;
- {$ELSE}
- fh := AccessResource(HInstance, h);
- {$ENDIF}
- end;
- end;
- if (fh = HFILE_ERROR) then exit;
- pd := DIB_ReadBitmapInfo(fh);
- if (pd = nil) then exit;
- { How much memory do we need to hold the DIB }
- dwBits := pd^.biSizeImage;
- dwLen := pd^.biSize + DIB_PaletteSize(pd) + dwBits;
- { Can we get more memory? }
- p := GlobalReAllocPtr(pd,dwLen,0);
- if (p = nil) then
- begin
- GlobalFreePtr(pd);
- pd := Nil;
- end
- else pd := PDIB(p);
- if (pd <> nil) then
- begin
- { read in the bits }
- _hread(fh, PChar(pd) + pd^.biSize + DIB_PaletteSize(pd), dwBits);
- end;
- _lclose(fh);
- Result := pd;
- end;
- (************************************************************************)
- (* ReadDibBitmapInfo() *)
- (* *)
- (* Will read a file in DIB format and return a global HANDLE to its *)
- (* BITMAPINFO. This function will work with both "old" and "new" *)
- (* bitmap formats, but will always return a "new" BITMAPINFO. *)
- (************************************************************************)
- function DIB_ReadBitmapInfo(fh: THANDLE): PDIB;
- type
- PRGBTRIPLE = ^RGBTRIPLE;
- RGBTRIPLE = array[0..0] of TRGBTRIPLE;
- PRGBQUAD = ^RGBQUAD;
- RGBQUAD = array[0..0] of TRGBQUAD;
- var
- off: DWORD;
- size, i: integer;
- nNumColors: DWORD;
- pRGB: PRGBQUAD;
- RGB: TRGBQUAD;
- bi: TBITMAPINFOHEADER;
- bc: TBITMAPCOREHEADER;
- bf: TBITMAPFILEHEADER;
- pd: PDIB;
- begin
- Result := nil;
- if (fh = HFILE_ERROR) then exit;
- off := _llseek(fh,0,SEEK_CUR);
- if (sizeof(bf) <> _lread(fh,@bf,sizeof(bf))) then exit;
- { do we have a RC HEADER? }
- if (bf.bfType <> BFT_BITMAP) then
- begin
- bf.bfOffBits := 0;
- _llseek(fh,off,SEEK_SET);
- end;
- if (sizeof(bi) <> _lread(fh,@bi,sizeof(bi))) then exit;
- { what type of bitmap info is this? }
- size := bi.biSize;
- if (size = sizeof(TBITMAPCOREHEADER)) then
- begin
- bc := PBITMAPCOREHEADER(@bi)^;
- bi.biSize := sizeof(TBITMAPINFOHEADER);
- bi.biWidth := bc.bcWidth;
- bi.biHeight := bc.bcHeight;
- bi.biPlanes := bc.bcPlanes;
- bi.biBitCount := bc.bcBitCount;
- bi.biCompression := BI_RGB;
- bi.biSizeImage := 0;
- bi.biXPelsPerMeter := 0;
- bi.biYPelsPerMeter := 0;
- bi.biClrUsed := 0;
- bi.biClrImportant := 0;
- _llseek(fh,sizeof(TBITMAPCOREHEADER)-sizeof(TBITMAPINFOHEADER),SEEK_CUR);
- end;
- nNumColors := DIB_NumColors(@bi);
- FixBitmapInfo(@bi);
- pd := GlobalAllocMem(bi.biSize + nNumColors * sizeof(TRGBQUAD));
- if (pd = nil) then exit;
- pd^ := bi;
- pRgb := PRGBQUAD(DIB_Colors(pd));
- if (nNumColors > 0) then
- begin
- if (size = sizeof(TBITMAPCOREHEADER)) then
- begin
- { convert a old color table (3 byte entries) to a new }
- { color table (4 byte entries) }
- _lread(fh,PChar(pRgb),nNumColors * sizeof(TRGBTRIPLE));
- for i := nNumColors-1 downTo 0 do
- begin
- rgb.rgbRed := PRGBTRIPLE(pRgb)^[i].rgbtRed;
- rgb.rgbBlue := PRGBTRIPLE(pRgb)^[i].rgbtBlue;
- rgb.rgbGreen := PRGBTRIPLE(pRgb)^[i].rgbtGreen;
- rgb.rgbReserved := 0;
- pRgb^[i] := rgb;
- end;
- end
- else _lread(fh,PChar(pRgb),nNumColors * sizeof(TRGBQUAD));
- end;
- if (bf.bfOffBits <> 0) then
- _llseek(fh,off + bf.bfOffBits,SEEK_SET);
- Result := pd;
- end;
- (************************************************************************)
- (* DibSetUsage(hdib,hpal,wUsage) *)
- (* *)
- (* Modifies the color table of the passed DIB for use with the wUsage *)
- (* parameter specifed. *)
- (* *)
- (* if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256 *)
- (* if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB *)
- (* values in the passed palette *)
- (************************************************************************)
- function DIB_SetUsage(pbi: PDIB; hPal: HPALETTE; wUsage: UINT): Boolean;
- type
- PRGBQUAD = ^RGBQUAD;
- RGBQUAD = array[0..0] of TRGBQUAD;
- var
- ape: array[0..255] of TPALETTEENTRY;
- pRGB: PRGBQUAD;
- pw: PWord;
- nColors: Longint;
- i: integer;
- begin
- Result := False;
- if (pbi = nil) then exit;
- if (hpal = 0) then
- hpal := GetStockObject(DEFAULT_PALETTE);
- nColors := DIB_NumColors(pbi);
- if (nColors = 3) and (DIB_Compression(pbi) = BI_BITFIELDS) then
- nColors := 0;
- if (nColors > 0) then
- begin
- pRgb := PRGBQUAD(DIB_Colors(pbi));
- case wUsage of
- DIB_PAL_COLORS:
- begin
- { Set the DIB color table to palette indexes }
- pw := Pointer(pRgb);
- for i := 0 to nColors-1 do
- begin
- pw^ := i;
- inc(pw);
- end;
- end;
- else
- begin
- { Set the DIB color table to RGBQUADS }
- { DIB_RGB_COLORS: }
- nColors := min(nColors,256);
- GetPaletteEntries(hpal,0,nColors,ape);
- for i := 0 to nColors-1 do
- begin
- pRgb^[i].rgbRed := ape[i].peRed;
- pRgb^[i].rgbGreen := ape[i].peGreen;
- pRgb^[i].rgbBlue := ape[i].peBlue;
- pRgb^[i].rgbReserved := 0;
- end;
- end;
- end;
- end;
- Result := True;
- end;
- (************************************************************************)
- (* Dib_Create *)
- (* *)
- (* Creates a new packed DIB with the given dimensions and the *)
- (* given number of bits per pixel *)
- (* *)
- (* Orientation: -1 = TOP_DOWN, 1 = BOTTOM_UP *)
- (************************************************************************)
- function DIB_Create(Bits, Orientation, Width, Height: integer; AllocBits: Boolean): PDIB;
- var
- pbi: PDIB;
- i: integer;
- pdw: PLongint;
- dwSizeImage: Longint;
- begin
- Result := nil;
- width := Max(width,1);
- height := Max(height,1);
- if (Bits > 8) and (Bits <> 24) then Bits := 24;
- if AllocBits then
- dwSizeImage := WIDTHBYTES(Longint(Width)*Bits) * Height
- else
- dwSizeImage := 0;
- pbi := GlobalAllocMem(sizeof(TBITMAPINFOHEADER)+dwSizeImage+256*sizeOf(TRGBQuad));
- if (pbi = nil) then exit;
- pbi^.biSize := sizeof(TBITMAPINFOHEADER);
- pbi^.biWidth := Width;
- pbi^.biHeight := Height * Orientation;
- pbi^.biPlanes := 1;
- pbi^.biBitCount := Bits;
- pbi^.biCompression := BI_RGB;
- pbi^.biSizeImage := dwSizeImage;
- pbi^.biXPelsPerMeter := 0;
- pbi^.biYPelsPerMeter := 0;
- pbi^.biClrUsed := 0;
- pbi^.biClrImportant := 0;
- if (bits = 4) then
- pbi^.biClrUsed := 16
- else if (bits = 8) then
- pbi^.biClrUsed := 256;
- pdw := PLongint(PChar(pbi)+pbi^.biSize);
- for i := 0 to (pbi^.biClrUsed div 16)-1 do
- begin
- pdw^ := $00000000; { 0000 black }
- inc(pdw);
- pdw^ := $00800000; { 0001 dark red }
- inc(pdw);
- pdw^ := $00008000; { 0010 dark green }
- inc(pdw);
- pdw^ := $00808000; { 0011 mustard }
- inc(pdw);
- pdw^ := $00000080; { 0100 dark blue }
- inc(pdw);
- pdw^ := $00800080; { 0101 purple }
- inc(pdw);
- pdw^ := $00008080; { 0110 dark turquoise }
- inc(pdw);
- pdw^ := $00C0C0C0; { 1000 gray }
- inc(pdw);
- pdw^ := $00808080; { 0111 dark gray }
- inc(pdw);
- pdw^ := $00FF0000; { 1001 red }
- inc(pdw);
- pdw^ := $0000FF00; { 1010 green }
- inc(pdw);
- pdw^ := $00FFFF00; { 1011 yellow }
- inc(pdw);
- pdw^ := $000000FF; { 1100 blue }
- inc(pdw);
- pdw^ := $00FF00FF; { 1101 pink (magenta) }
- inc(pdw);
- pdw^ := $0000FFFF; { 1110 cyan }
- inc(pdw);
- pdw^ := $00FFFFFF; { 1111 white }
- end;
- Result := pbi;
- end;
- (************************************************************************)
- procedure xlatClut8(pb: PByte; dwSize: DWORD; xlat: PByteArray);
- var
- dw: DWORD;
- begin
- for dw := 0 to dwSize-1 do
- begin
- pb^ := xlat^[pb^];
- incHuge(pb,sizeOf(pB^));
- end;
- end;
- (************************************************************************)
- procedure xlatClut4(pb: PByte; dwSize: DWORD; xlat: PByteArray);
- var
- dw: DWORD;
- begin
- for dw := 0 to dwSize-1 do
- begin
- pb^ := xlat^[pb^ and $0F] or (xlat^[(pb^ shr 4) and $0F] shl 4);
- incHuge(pb,sizeOf(pB^));
- end;
- end;
- (************************************************************************)
- procedure xlatRle8(pb: PByte; dwSize: DWORD; xlat: PByteArray);
- const
- RLE_ESCAPE = 0;
- RLE_EOL = 0;
- RLE_EOF = 1;
- RLE_JMP = 2;
- var
- b,cnt: Byte;
- prle: PByte;
- begin
- prle := pb;
- while True do
- begin
- cnt := prle^;
- incHuge(prle,1);
- b := prle^;
- if (cnt = RLE_ESCAPE) then
- begin
- incHuge(prle,1);
- case b of
- RLE_EOF: exit;
- RLE_EOL: ;
- RLE_JMP: incHuge(prle,2); { skip dX,dY }
- else
- begin
- cnt := b;
- for b := 0 to cnt-1 do
- begin
- prle^ := xlat^[prle^];
- incHuge(prle,1);
- end;
- if (cnt and 1 > 0) then incHuge(prle,1);
- end;
- end;
- end
- else
- begin
- prle^:= xlat^[b];
- incHuge(prle,1);
- end;
- end;
- end;
- (************************************************************************)
- procedure xlatRle4(pb: PByte; dwSize: DWORD; xlat: PByteArray);
- begin
- end;
- (************************************************************************)
- (* DibMapToPalette(pdib, hpal) *)
- (* *)
- (* Map the colors of the DIB, using GetNearestPaletteIndex, to *)
- (* the colors of the given palette. *)
- (************************************************************************)
- procedure DIB_MapToPalette(var pbi: PDIB; hpal: HPALETTE);
- type
- PRGBQUAD = ^RGBQUAD;
- RGBQUAD = array[0..0] of TRGBQUAD;
- var
- pe: TPALETTEENTRY;
- i: integer;
- nDibColors: DWORD;
- nPalColors: DWORD;
- lpBits,p: PByte;
- pRGB: PRGBQUAD;
- xlat: array[0..255] of Byte;
- SizeImage: DWORD;
- begin
- nPalColors := 0;
- if (hpal = 0) or (pbi = nil) then exit;
- pRgb := PRGBQUAD(DIB_Colors(pbi));
- GetObject(hpal,sizeof(Word),@nPalColors);
- nDibColors := DIB_NumColors(pbi);
- SizeImage := pbi^.biSizeImage;
- if (SizeImage = 0) then
- SizeImage := DIB_SizeImage(pbi);
- { build a xlat table. from the current DIB colors to the given }
- { palette. }
- for i := 0 to nDibColors-1 do
- xlat[i] := GetNearestPaletteIndex(hpal,RGB(pRgb^[i].rgbRed,pRgb^[i].rgbGreen,pRgb^[i].rgbBlue));
- lpBits := DIB_Ptr(pbi);
- pbi^.biClrUsed := nPalColors;
- { re-size the DIB }
- if (nPalColors > nDibColors) then
- begin
- GlobalReAllocPtr(pbi, pbi^.biSize + nPalColors*sizeof(TRGBQUAD) + SizeImage, 0);
- p := DIB_Ptr(pbi);
- GlobalMoveMem(lpBits^, p^, SizeImage);
- lpBits := DIB_Ptr(pbi);
- end
- else if (nPalColors < nDibColors) then
- begin
- p := DIB_Ptr(pbi);
- GlobalMoveMem(lpBits^, p^, SizeImage);
- GlobalReAllocPtr(pbi, pbi^.biSize + nPalColors*sizeof(TRGBQUAD) + SizeImage, 0);
- lpBits := DIB_Ptr(pbi);
- end;
- { translate the DIB bits }
- case pbi^.biCompression of
- BI_RLE8: xlatRle8(lpBits, SizeImage, @xlat);
- BI_RLE4: xlatRle4(lpBits, SizeImage, @xlat);
- BI_RGB:
- begin
- if (pbi^.biBitCount = 8) then
- xlatClut8(lpBits, SizeImage, @xlat)
- else
- xlatClut4(lpBits, SizeImage, @xlat);
- end;
- end;
- { Now copy the RGBs in the logical palette to the dib color table }
- for i := 0 to nPalColors-1 do
- begin
- GetPaletteEntries(hpal,i,1,pe);
- pRgb^[i].rgbRed := pe.peRed;
- pRgb^[i].rgbGreen := pe.peGreen;
- pRgb^[i].rgbBlue := pe.peBlue;
- pRgb^[i].rgbReserved := 0;
- end;
- end;
- (************************************************************************)
- function DIB_CreatePalette(pbi: PDIB): HPALETTE;
- var
- R,G,B: Byte;
- DstPal: PLogPalette;
- Colors: integer;
- DC: HDC;
- Focus: HWND;
- SysPalSize: Integer;
- Size: Longint;
- i: Integer;
- begin
- Result := 0;
- Colors := DIB_NumColors(pbi);
- if Colors <> 0 then
- begin
- Size := SizeOf(TLogPalette) + ((Colors - 1) * SizeOf(TPaletteEntry));
- DstPal := GlobalAllocMem(Size);
- try
- with DstPal^ do
- begin
- palNumEntries := Colors;
- palVersion := $300;
- Focus := GetFocus;
- DC := GetDC(Focus);
- try
- SysPalSize := GetDeviceCaps(DC, SIZEPALETTE);
- if (Colors = 16) and (SysPalSize >= 16) then
- begin
- { Ignore the disk image of the palette for 16 color }
- { bitmaps use instead the first 8 and last 8 of the }
- { current system palette }
- GetSystemPaletteEntries(DC, 0, 8, palPalEntry);
- i := 8;
- GetSystemPaletteEntries(DC, SysPalSize - i, i, palPalEntry[i]);
- end
- else
- for i := 0 to Colors-1 do
- with palPalEntry[i] do
- begin
- { Copy the palette for all others (i.e. 256 colors) }
- peRed := PBitmapInfo(pbi)^.bmiColors[i].rgbRed;
- peGreen := PBitmapInfo(pbi)^.bmiColors[i].rgbGreen;
- peBlue := PBitmapInfo(pbi)^.bmiColors[i].rgbBlue;
- peFlags := 0;
- end;
- finally
- ReleaseDC(Focus, DC);
- end;
- end;
- Result := CreatePalette(DstPal^);
- finally
- GlobalFreePtr(DstPal);
- end;
- end
- else if DIB_BitCount(pbi) = 24 then
- begin
- Colors:= 256;
- Size:= SizeOf(TLogPalette) + (Colors-1) * SizeOf(TPaletteEntry);
- DstPal := GlobalAllocMem(Size);
- try
- with DstPal^ do
- begin
- palVersion:= $300;
- palNumEntries:= Colors;
- R:= 0;
- G:= 0;
- B:= 0;
- for i := 0 to Colors-1 do
- with palPalEntry[i] do
- begin
- peRed:= R;
- peGreen:= G;
- peBlue:= B;
- peFlags:= 0;
- Inc(R, 32);
- if (R = 0) then
- begin
- Inc(G, 32);
- if (G = 0) then Inc(B, 64);
- end;
- end;
- end;
- Result:= CreatePalette(DstPal^);
- finally
- GlobalFreePtr(DstPal);
- end;
- end;
- end;
- (************************************************************************)
- procedure DIB_Display(pbi: PDIB; DC: HDC; aRect: TRect);
- var
- OldPal,Pal: HPalette;
- begin
- OldPal := 0;
- Pal := DIB_CreatePalette(pbi);
- if Pal <> 0 then
- begin
- OldPal := SelectPalette(DC, Pal, False);
- RealizePalette(DC);
- end;
- SetStretchBltMode(DC, STRETCH_DELETESCANS);
- StretchDIBits(DC, aRect.Left,aRect.Top,
- aRect.Right-aRect.Left, aRect.Bottom-aRect.Top,
- 0, 0, DIB_WIDTH(pBi), DIB_Height(pBi),
- DIB_PTR(pbi), PBitmapInfo(pbI)^,
- DIB_RGB_COLORS, SRCCOPY);
- if (OldPal <> 0) then
- begin
- SelectPalette(DC, OldPal, False);
- DeleteObject(Pal);
- end;
- end;
- (************************************************************************)
- function DIB_BitmapToDIB(Handle: HBitmap; Palette: HPalette;
- Bits, Orientation: integer): PDIB;
- var
- lpbi: PDIB;
- lpBits: PByte;
- BM: TBitmap;
- OldPal: HPALETTE;
- DC: HDC;
- Focus: HWND;
- begin
- Result := nil;
- GetObject(Handle, sizeOf(TBitmap), @BM);
- lpbi := DIB_Create(Bits, Orientation, BM.bmWidth, BM.bmHeight, True);
- if (lpbi <> nil) then
- with lpbi^ do
- begin
- OldPal := 0;
- Focus := GetFocus;
- DC := GetDC(Focus);
- try
- if Palette <> 0 then
- begin
- OldPal := SelectPalette(DC, Palette, False);
- RealizePalette(DC);
- end;
- lpBits := DIB_PTR(lpbi);
- if GetDIBits(DC, Handle, 0, BM.bmHeight, lpBits, PBitmapInfo(lpbi)^, DIB_RGB_COLORS) = 0 then
- DIB_Free(lpbi)
- else
- Result := lpbi;
- finally
- if (OldPal <> 0) then SelectPalette(DC, OldPal, False);
- ReleaseDC(Focus,DC);
- end;
- end;
- end;
- (************************************************************************)
- procedure DIB_DIBToBitmap(pbi: PDIB; var Bitmap: HBitmap; var Pal: HPalette);
- var
- Focus: HWND;
- DC: HDC;
- OldPal: HPALETTE;
- begin
- OldPal := 0;
- { we use the handle of the window with the focus (which, if this }
- { routine is called from a menu command, will be this window) in }
- { order to guarantee that the realized palette will have first }
- { priority on the system palette }
- Focus := GetFocus;
- DC := GetDC(Focus);
- try
- Pal := DIB_CreatePalette(pbi);
- if Pal <> 0 then
- begin
- OldPal := SelectPalette(DC, Pal, False);
- RealizePalette(DC);
- end;
- Bitmap := CreateDIBitmap(DC, pbi^, CBM_INIT, DIB_PTR(pbi),
- PBitmapInfo(pbi)^, DIB_RGB_COLORS);
- finally
- if (OldPal <> 0) then SelectPalette(DC, OldPal, False);
- ReleaseDC(Focus, DC);
- end;
- end;
- (************************************************************************)
- function LoadPalette(FName: string): PLOGPALETTE;
- Label ERROR_OPEN;
- var
- {$IFDEF WIN32}
- hmio : HMMIO;
- {$ELSE}
- hmio : THMMIO;
- {$ENDIF}
- ckFile : TMMCKINFO;
- ckChunk: TMMCKINFO;
- iSize : integer;
- iColors: integer;
- pData : Pointer;
- pLogPal: PLOGPALETTE;
- aBuf : array[0..MAX_PATH] of Char;
- begin
- Result := nil;
- hmio := 0;
- pData := nil;
- if (FName <> '') then
- begin
- StrPCopy(aBuf,FName);
- hmio := mmioOpen(aBuf, nil, MMIO_READ OR MMIO_ALLOCBUF);
- if (hmio = 0) then
- goto ERROR_OPEN;
- { Check it's a RIFF PAL file }
- ckFile.fccType := $204C4150; {'P','A','L',' '};
- if (mmioDescend(hmio, @ckFile, nil, MMIO_FINDRIFF) <> 0) then
- goto ERROR_OPEN;
- { Find the 'data' chunk }
- ckChunk.ckid := $61746164; {'d','a','t','a'};
- if (mmioDescend(hmio, @ckChunk, @ckFile, MMIO_FINDCHUNK) <> 0) then
- goto ERROR_OPEN;
- { allocate some memory for the data chunk }
- iSize := ckChunk.cksize;
- pData := GlobalAllocMem(iSize);
- if (pdata = nil) then
- goto ERROR_OPEN;
- { read the data chunk }
- if (mmioRead(hmio, pdata, iSize) <> iSize) then
- goto ERROR_OPEN;
- { The data chunk should be a LOGPALETTE structure }
- { which we can create a palette from }
- pLogPal := Pointer(pdata);
- if (pLogPal^.palVersion <> $300) then
- goto ERROR_OPEN;
- { Get the number of entries }
- iColors := pLogPal^.palNumEntries;
- if (iColors <= 0) then
- goto ERROR_OPEN;
- Result := pLogPal;
- end;
- ERROR_OPEN:
- if (hmio <> 0) then
- mmioClose(hmio,0);
- if (Result = nil) and (pData <> nil) then
- GlobalFreePtr(pData);
- end;
- (************************************************************************)
- function SavePalette(FName: string; pLogPal: PLOGPALETTE): Boolean;
- Label ERROR_SAVE;
- var
- {$IFDEF WIN32}
- hmio : HMMIO;
- {$ELSE}
- hmio : THMMIO;
- {$ENDIF}
- ckFile: TMMCKINFO;
- ckData: TMMCKINFO;
- iSize : integer;
- aBuf : array[0..MAX_PATH] of Char;
- begin
- Result := False;
- hmio := 0;
- if pLogPal^.palNumEntries <= 0 then
- goto ERROR_SAVE;
- StrPCopy(aBuf,FName);
- hmio := mmioOpen(aBuf, nil, MMIO_WRITE or MMIO_CREATE or MMIO_ALLOCBUF);
- if (hmio = 0) then
- goto ERROR_SAVE;
- { Create a RIFF chunk for a PAL file }
- ckFile.cksize := 0; { corrected later }
- ckFile.fccType := $204C4150; {'P','A','L',' '};
- if (mmioCreateChunk(hmio, @ckFile, MMIO_CREATERIFF) <> 0) then
- goto ERROR_SAVE;
- iSize := sizeOf(TLogPalette)+sizeOf(TPaletteEntry)*pLogPal^.palNumEntries;
- { create the data chunk }
- ckData.cksize := iSize;
- ckData.ckid := $61746164; {'d','a','t','a'};
- if (mmioCreateChunk(hmio, @ckData, 0) <> 0) then
- goto ERROR_SAVE;
- { write the data chunk }
- if (mmioWrite(hmio, PChar(pLogPal), iSize) <> iSize) then
- goto ERROR_SAVE;
- { Ascend from the data chunk which will correct the length }
- mmioAscend(hmio, @ckData, 0);
- { Ascend from the RIFF/PAL chunk }
- mmioAscend(hmio, @ckFile, 0);
- Result := True;
- ERROR_SAVE:
- if (hmio <> 0) then
- mmioClose(hmio, 0);
- end;
- end.