MMDIB.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:37k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Tel.: +0351-8012255                   =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.html             =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 20.01.1998 - 18:00:00 $                                      =}
  24. {========================================================================}
  25. unit MMDIB;
  26. {$I COMPILER.INC}
  27. interface
  28. uses
  29. {$IFDEF WIN32}
  30.   Windows,
  31. {$ELSE}
  32.   WinProcs,
  33.   WinTypes,
  34. {$ENDIF}
  35.   SysUtils,
  36.   MMSystem,
  37.   MMUtils;
  38. const
  39.      {$IFDEF CBUILDER3} {$EXTERNALSYM BFT_ICON } {$ENDIF}
  40.      BFT_ICON     = $4349; { 'IC' }
  41.      {$IFDEF CBUILDER3} {$EXTERNALSYM BFT_BITMAP } {$ENDIF}
  42.      BFT_BITMAP   = $4d42; { 'BM' }
  43.      {$IFDEF CBUILDER3} {$EXTERNALSYM BFT_CURSOR } {$ENDIF}
  44.      BFT_CURSOR   = $5450; { 'PT' }
  45.      {$IFDEF CBUILDER3} {$EXTERNALSYM BI_BITFIELDS } {$ENDIF}
  46.      BI_BITFIELDS = 3;
  47.      {$IFDEF CBUILDER3} {$EXTERNALSYM HALFTONE } {$ENDIF}
  48.      HALFTONE     = COLORONCOLOR;
  49.      { flags for _lseek }
  50.      {$IFDEF CBUILDER3} {$EXTERNALSYM SEEK_CUR } {$ENDIF}
  51.      SEEK_CUR     = 1;
  52.      {$IFDEF CBUILDER3} {$EXTERNALSYM SEEK_END } {$ENDIF}
  53.      SEEK_END     = 2;
  54.      {$IFDEF CBUILDER3} {$EXTERNALSYM SEEK_SET } {$ENDIF}
  55.      SEEK_SET     = 0;
  56.      { flags for orientation }
  57.      TOPDOWN      = -1;
  58.      BOTTOMUP     =  1;
  59. type
  60.     PRGBQUAD   = ^TRGBQUAD;
  61.     PDIB       = PBitmapInfoHeader;
  62.     HDIB       = THandle;
  63. (************************************************************************)
  64. procedure ClearSystemPalette;
  65. function  CreateSystemColorPalette: PLogPalette;
  66. function  LoadPalette(FName: string): PLOGPALETTE;
  67. function  SavePalette(FName: string; pLogPal: PLOGPALETTE): Boolean;
  68. (************************************************************************)
  69. function  DIB_Create(bits, orientation, width, height: integer; AllocBits: Boolean): PDIB;
  70. function  DIB_ReadBitmapInfo(fh: THandle): PDIB;
  71. function  DIB_OpenFile(szFile: PChar): PDIB;
  72. function  DIB_SetUsage(pbi: PDIB; hPal: HPALETTE; wUsage: UINT): Boolean;
  73. procedure DIB_MapToPalette(var pbi: PDIB; hpal: HPALETTE);
  74. procedure DIB_Display(pbi: PDIB; DC: HDC; aRect: TRect);
  75. function  DIB_BitmapToDIB(Handle: HBitmap; Palette: HPalette;
  76.                           Bits, Orientation: integer): PDIB;
  77. procedure DIB_DIBToBitmap(pbi: PDIB; var Bitmap: HBitmap;
  78.                           var Pal: HPalette);
  79. (************************************************************************)
  80. function  IsWinDIB(pbi: PBITMAPINFOHEADER): Boolean;
  81. function  HandleFrom_DIB(lpbi: PDIB): THandle;
  82. function  DIB_FromHandle(h: THandle): PDIB;
  83. procedure DIB_Free(lpbi: PDIB);
  84. function  DIB_Width(lpbi: PDIB): integer;
  85. function  DIB_Height(lpbi: PDIB): integer;
  86. function  DIB_BitCount(lpbi: PDIB): integer;
  87. function  DIB_Compression(lpbi: PDIB): Longint;
  88. function  DIB_NumColors(lpbi: PDIB): Longint;
  89. function  DIB_WidthBytesN(lpbi: PDIB; n: integer): Longint;
  90. function  DIB_WidthBytes(lpbi: PDIB): Longint;
  91. function  DIB_BISize(lpbi: PDIB): integer;
  92. function  DIB_SizeImage(lpbi: PDIB): Longint;
  93. function  DIB_Size(lpbi: PDIB): Longint;
  94. function  DIB_PaletteSize(lpbi: PDIB): DWORD;
  95. function  DIB_FlipY(lpbi: PDIB; y: integer): integer;
  96. function  DIB_Colors(lpbi: PDIB): PRGBQUAD;
  97. function  DIB_Ptr(lpbi: PDIB): Pointer;
  98. function  DIB_XYN(lpbi: PDIB; pb: Pointer; x,y,n: integer): Pointer;
  99. function  DIB_XY(lpbi: PDIB;x,y: integer): Pointer;
  100. function  DIB_Info(pDIB: PDIB): PBitmapInfo;
  101. implementation
  102. {$IFNDEF WIN32}
  103. function _hread(hFile: THANDLE; lpBuffer: Pointer; lBytes: Longint): Longint;
  104. Far; external 'KERNEL' name '_hread';
  105. {$ENDIF}
  106. (************************************************************************)
  107. function IsWinDIB(pbi: PDIB): Boolean;
  108. begin
  109.    if (pbi^.biSize <> sizeof(TBITMAPINFOHEADER)) then
  110.        Result := False
  111.    else
  112.        Result := True;
  113. end;
  114. (************************************************************************)
  115. function HandleFrom_DIB(lpbi: PDIB): THandle;
  116. begin
  117.    {$IFDEF WIN32}
  118.    Result := GlobalHandle(lpbi);
  119.    {$ELSE}
  120.    Result := GlobalHandle(SELECTOROF(lpbi));
  121.    {$ENDIF}
  122. end;
  123. (************************************************************************)
  124. function DIB_FromHandle(h: THandle): PDIB;
  125. begin
  126.    Result := GlobalLock(h);
  127. end;
  128. (************************************************************************)
  129. procedure DIB_Free(lpbi: PDIB);
  130. begin
  131.    if (lpbi <> nil) then GlobalFreePtr(lpbi);
  132. end;
  133. (************************************************************************)
  134. function WIDTHBYTES(i: Longint): Longint;
  135. begin
  136.    Result := ((i+31) and not 31) div 8;  { DWORD aligned ! }
  137. end;
  138. (************************************************************************)
  139. function DIB_Width(lpbi: PDIB): integer;
  140. begin
  141.    Result := lpbi^.biWidth;
  142. end;
  143. (************************************************************************)
  144. function DIB_Height(lpbi: PDIB): integer;
  145. begin
  146.    Result := lpbi^.biHeight;
  147. end;
  148. (************************************************************************)
  149. function DIB_BitCount(lpbi: PDIB): integer;
  150. begin
  151.     if IsWinDIB(lpbi) then
  152.        Result := lpbi^.biBitCount
  153.     else
  154.        Result := PBitmapCoreHeader(lpbi)^.bcBitCount;
  155. end;
  156. (************************************************************************)
  157. function DIB_Compression(lpbi: PDIB): Longint;
  158. begin
  159.    Result := lpbi^.biCompression;
  160. end;
  161. (************************************************************************)
  162. function DIB_NumColors(lpbi: PDIB): Longint;
  163. begin
  164.    if (lpbi^.biClrUsed = 0) and (lpbi^.biBitCount <= 8) then
  165.       Result := (1 shl lpbi^.biBitCount)
  166.     else
  167.       Result := lpbi^.biClrUsed;
  168. end;
  169. (************************************************************************)
  170. function DIB_WidthBytesN(lpbi: PDIB; n: integer): Longint;
  171. begin
  172.    Result := WIDTHBYTES(lpbi^.biWidth * Long(n));
  173. end;
  174. (************************************************************************)
  175. function DIB_WidthBytes(lpbi: PDIB): Longint;
  176. begin
  177.    Result := DIB_WidthBytesN(lpbi, lpbi^.biBitCount);
  178. end;
  179. (************************************************************************)
  180. function DIB_BISize(lpbi: PDIB): integer;
  181. begin
  182.    Result := lpbi^.biSize + DWORD(DIB_PaletteSize(lpbi));
  183. end;
  184. (************************************************************************)
  185. function DIB_SizeImage(lpbi: PDIB): Longint;
  186. begin
  187.    if (lpbi^.biSizeImage = 0) then
  188.       Result :=  DIB_WidthBytes(lpbi) * Long(lpbi^.biHeight)
  189.    else
  190.       Result := lpbi^.biSizeImage;
  191. end;
  192. (************************************************************************)
  193. function DIB_Size(lpbi: PDIB): Longint;
  194. begin
  195.    Result := lpbi^.biSize + lpbi^.biSizeImage + (lpbi^.biClrUsed * sizeof(TRGBQUAD));
  196. end;
  197. (************************************************************************)
  198. function DIB_PaletteSize(lpbi: PDIB): DWORD;
  199. begin
  200.    Result := DIB_NumColors(lpbi) * sizeof(TRGBQUAD);
  201. end;
  202. (************************************************************************)
  203. function DIB_FlipY(lpbi: PDIB; y: integer): integer;
  204. begin
  205.    Result := lpbi^.biHeight-1-y;
  206. end;
  207. (************************************************************************)
  208. function DIB_Colors(lpbi: PDIB): PRGBQUAD;
  209. begin
  210.    Result := PRGBQUAD(PChar(lpbi) + lpbi^.biSize);
  211. end;
  212. (************************************************************************)
  213. function DIB_Ptr(lpbi: PDIB): Pointer;
  214. begin
  215.    {$IFDEF WIN32}
  216.    { HACK for NT BI_BITFIELDS DIBs }
  217.    if (lpbi^.biCompression = BI_BITFIELDS) then
  218.       Result := PChar(DIB_Colors(lpbi)) + 3 * sizeof(TRGBQUAD)
  219.    else
  220.    {$ENDIF}
  221.      Result := PChar(DIB_Colors(lpbi)) + lpbi^.biClrUsed * sizeof(TRGBQUAD);
  222. end;
  223. (************************************************************************)
  224. function DIB_XYN(lpbi: PDIB; pb: Pointer; x,y,n: integer): Pointer;
  225. begin
  226.    Result := pb;
  227.    incHuge(Result,Long(x)*Long(n) div Long(8)+DIB_WidthBytesN(lpbi,n)*Long(y));
  228. end;
  229. (************************************************************************)
  230. function DIB_XY(lpbi: PDIB;x,y: integer): Pointer;
  231. begin
  232.    Result := DIB_XYN(lpbi,DIB_Ptr(lpbi),x,y,lpbi^.biBitCount);
  233. end;
  234. (************************************************************************)
  235. procedure FixBitmapInfo(lpbi: PDIB);
  236. begin
  237.    if (lpbi^.biSizeImage = 0) then
  238.        lpbi^.biSizeImage := DIB_SizeImage(lpbi);
  239.    if (lpbi^.biClrUsed = 0) then
  240.        lpbi^.biClrUsed := DIB_NumColors(lpbi);
  241.    if (lpbi^.biCompression = BI_BITFIELDS) and (lpbi^.biClrUsed = 0) then
  242.        lpbi^.biClrUsed := 3;
  243. end;
  244. (************************************************************************)
  245. function DIB_Info(pDIB: PDIB): PBitmapInfo;
  246. begin
  247.    Result := Pointer(pDIB);
  248. end;
  249. (************************************************************************)
  250. (*  Clear the System Palette so that we can ensure an identity palette  *)
  251. (*  mapping for fast performance.                                       *)
  252. (************************************************************************)
  253. procedure ClearSystemPalette;
  254. type
  255.    { Logical Palette }
  256.    TLogPal = record
  257.     palVersion: Word;
  258.     palNumEntries: Word;
  259.     palEntry: array[0..256] of TPaletteEntry;
  260.   end;
  261. var
  262.    i: integer;
  263.    LogPal: TLogPal;
  264.    ScreenPal: HPalette;
  265.    ScreenDC: HDC;
  266. begin
  267.    with LogPal do
  268.    begin
  269.       palVersion := $300;
  270.       palNumEntries := 256;
  271.       { Reset everything in the system palette to black }
  272.       for i := 0 to 255 do
  273.       begin
  274.          palEntry[i].peRed := 0;
  275.          palEntry[i].peGreen := 0;
  276.          palEntry[i].peBlue := 0;
  277.          palEntry[i].peFlags := PC_NOCOLLAPSE;
  278.       end;
  279.       { Create, select, realize, deselect, and delete the palette }
  280.       ScreenDC := GetDC(0);
  281.       ScreenPal := CreatePalette(PLogPalette(@LogPal)^);
  282.       if (ScreenPal <> 0) then
  283.       begin
  284.          ScreenPal := SelectPalette(ScreenDC,ScreenPal,False);
  285.          RealizePalette(ScreenDC);
  286.          ScreenPal := SelectPalette(ScreenDC,ScreenPal,False);
  287.          DeleteObject(ScreenPal);
  288.       end;
  289.       ReleaseDC(0, ScreenDC);
  290.    end;
  291. end;
  292. (************************************************************************)
  293. function CreateSystemColorPalette: PLogPalette;
  294. type
  295.    { Logical Palette }
  296.    PLogPal = ^TLogPal;
  297.    TLogPal = record
  298.     palVersion: Word;
  299.     palNumEntries: Word;
  300.     palEntry: array[0..256] of TPaletteEntry;
  301.   end;
  302. var
  303.    DC: HDC;
  304.    Size: integer;
  305.    pPal: PLogPal;
  306. begin
  307.    { Get a screen DC to work with }
  308.    DC := GetDC(0);
  309.    try
  310.       { allocate a log pal and fill it with the color table info }
  311.       Size := sizeof(TLogPalette) + 256 * sizeOf(TPaletteEntry);
  312.       pPal := GlobalAllocMem(Size);
  313.       FillChar(pPal^, Size, 0);
  314.       with pPal^ do
  315.       begin
  316.          palVersion := $300;   { Windows 3.0 }
  317.          palNumEntries := 256; { table size  }
  318.          { Make sure we are on a palettized device }
  319.          if (GetDeviceCaps(DC, RASTERCAPS) and RC_PALETTE <> 0) and
  320.             (GetDeviceCaps(DC, NUMCOLORS) <= 256) then
  321.          begin
  322.             { Get the system colors in the first and last 10 slots }
  323.             GetSystemPaletteEntries(DC, 0, 10, palEntry);
  324.             GetSystemPaletteEntries(DC, 246, 10, palEntry[246]);
  325.          end
  326.          else
  327.          begin
  328.             { set the entrys by hand }
  329.             Longint(palEntry[0])  := RGB($00,$00,$00); { black        }
  330.             Longint(palEntry[1])  := RGB($80,$00,$00); { dark red     }
  331.             Longint(palEntry[2])  := RGB($00,$80,$00); { dark green   }
  332.             Longint(palEntry[3])  := RGB($80,$80,$00); { dark yellow  }
  333.             Longint(palEntry[4])  := RGB($00,$00,$80); { dark blue    }
  334.             Longint(palEntry[5])  := RGB($80,$00,$80); { dark magneta }
  335.             Longint(palEntry[6])  := RGB($00,$80,$80); { dark cyan    }
  336.             Longint(palEntry[7])  := RGB($C0,$C0,$C0); { light gray   }
  337.             Longint(palEntry[8])  := RGB($C0,$DC,$C0); { money green  }
  338.             Longint(palEntry[9])  := RGB($A6,$CA,$F0); { sky blue     }
  339.             Longint(palEntry[246]):= RGB($FF,$FB,$F0); { cream        }
  340.             Longint(palEntry[247]):= RGB($A0,$A0,$A4); { medium gray  }
  341.             Longint(palEntry[248]):= RGB($80,$80,$80); { dark gray    }
  342.             Longint(palEntry[249]):= RGB($FF,$00,$00); { red          }
  343.             Longint(palEntry[250]):= RGB($00,$FF,$00); { green        }
  344.             Longint(palEntry[251]):= RGB($FF,$FF,$00); { yellow       }
  345.             Longint(palEntry[252]):= RGB($00,$00,$FF); { blue         }
  346.             Longint(palEntry[253]):= RGB($FF,$00,$FF); { magneta      }
  347.             Longint(palEntry[254]):= RGB($00,$FF,$FF); { cyan         }
  348.             Longint(palEntry[255]):= RGB($FF,$FF,$FF); { white        }
  349.          end;
  350.       end;
  351.    finally
  352.       ReleaseDC(0,DC);
  353.    end;
  354.    Result := PLogPalette(pPal);
  355. end;
  356. {$IFNDEF WIN32}
  357. const
  358.   HFILE_ERROR = -1;
  359. {$ENDIF}
  360. (************************************************************************)
  361. (* Open a DIB file and return a MEMORY DIB, a memory handle containing..*)
  362. (************************************************************************)
  363. function DIB_OpenFile(szFile: PChar): PDIB;
  364. var
  365.    fh: THandle;
  366.    dwLen: DWORD;
  367.    dwBits: DWORD;
  368.    pd: PDIB;
  369.    p: Pointer;
  370.    ofs: TOFSTRUCT;
  371.    h: THandle;
  372. begin
  373.    Result := nil;
  374.    fh := OpenFile(szFile, ofs, OF_READ);
  375.    if (fh = HFILE_ERROR) then
  376.    begin
  377.       h := FindResource(HInstance, szFile, RT_BITMAP);
  378.       if (h <> 0) then
  379.       begin
  380.          {$IFDEF WIN32}
  381.          { !!! can we call GlobalFree() on this? is it the right format. }
  382.          { !!! can we write to this resource?                            }
  383.          Result := PDIB(LockResource(LoadResource(HInstance, h)));
  384.          exit;
  385.          {$ELSE}
  386.          fh := AccessResource(HInstance, h);
  387.          {$ENDIF}
  388.       end;
  389.    end;
  390.    if (fh = HFILE_ERROR) then exit;
  391.    pd := DIB_ReadBitmapInfo(fh);
  392.    if (pd = nil) then exit;
  393.    { How much memory do we need to hold the DIB }
  394.    dwBits := pd^.biSizeImage;
  395.    dwLen  := pd^.biSize + DIB_PaletteSize(pd) + dwBits;
  396.    { Can we get more memory? }
  397.    p := GlobalReAllocPtr(pd,dwLen,0);
  398.    if (p = nil) then
  399.    begin
  400.       GlobalFreePtr(pd);
  401.       pd := Nil;
  402.    end
  403.    else pd := PDIB(p);
  404.    if (pd <> nil) then
  405.    begin
  406.       { read in the bits }
  407.       _hread(fh, PChar(pd) + pd^.biSize + DIB_PaletteSize(pd), dwBits);
  408.    end;
  409.    _lclose(fh);
  410.    Result := pd;
  411. end;
  412. (************************************************************************)
  413. (*  ReadDibBitmapInfo()                                                 *)
  414. (*                                                                      *)
  415. (*  Will read a file in DIB format and return a global HANDLE to its    *)
  416. (*  BITMAPINFO.  This function will work with both "old" and "new"      *)
  417. (*  bitmap formats, but will always return a "new" BITMAPINFO.          *)
  418. (************************************************************************)
  419. function DIB_ReadBitmapInfo(fh: THANDLE): PDIB;
  420. type
  421.     PRGBTRIPLE = ^RGBTRIPLE;
  422.     RGBTRIPLE  = array[0..0] of TRGBTRIPLE;
  423.     PRGBQUAD = ^RGBQUAD;
  424.     RGBQUAD  = array[0..0] of TRGBQUAD;
  425. var
  426.    off: DWORD;
  427.    size, i: integer;
  428.    nNumColors: DWORD;
  429.    pRGB: PRGBQUAD;
  430.    RGB: TRGBQUAD;
  431.    bi: TBITMAPINFOHEADER;
  432.    bc: TBITMAPCOREHEADER;
  433.    bf: TBITMAPFILEHEADER;
  434.    pd: PDIB;
  435. begin
  436.    Result := nil;
  437.    if (fh = HFILE_ERROR) then exit;
  438.    off := _llseek(fh,0,SEEK_CUR);
  439.    if (sizeof(bf) <> _lread(fh,@bf,sizeof(bf))) then exit;
  440.    { do we have a RC HEADER? }
  441.    if (bf.bfType <> BFT_BITMAP) then
  442.    begin
  443.       bf.bfOffBits := 0;
  444.       _llseek(fh,off,SEEK_SET);
  445.    end;
  446.    if (sizeof(bi) <> _lread(fh,@bi,sizeof(bi))) then exit;
  447.    { what type of bitmap info is this? }
  448.    size := bi.biSize;
  449.    if (size = sizeof(TBITMAPCOREHEADER)) then
  450.    begin
  451.       bc := PBITMAPCOREHEADER(@bi)^;
  452.       bi.biSize          := sizeof(TBITMAPINFOHEADER);
  453.       bi.biWidth         := bc.bcWidth;
  454.       bi.biHeight        := bc.bcHeight;
  455.       bi.biPlanes        := bc.bcPlanes;
  456.       bi.biBitCount      := bc.bcBitCount;
  457.       bi.biCompression   := BI_RGB;
  458.       bi.biSizeImage     := 0;
  459.       bi.biXPelsPerMeter := 0;
  460.       bi.biYPelsPerMeter := 0;
  461.       bi.biClrUsed       := 0;
  462.       bi.biClrImportant  := 0;
  463.       _llseek(fh,sizeof(TBITMAPCOREHEADER)-sizeof(TBITMAPINFOHEADER),SEEK_CUR);
  464.    end;
  465.    nNumColors := DIB_NumColors(@bi);
  466.    FixBitmapInfo(@bi);
  467.    pd := GlobalAllocMem(bi.biSize + nNumColors * sizeof(TRGBQUAD));
  468.    if (pd = nil) then exit;
  469.    pd^ := bi;
  470.    pRgb := PRGBQUAD(DIB_Colors(pd));
  471.    if (nNumColors > 0) then
  472.    begin
  473.       if (size = sizeof(TBITMAPCOREHEADER)) then
  474.       begin
  475.          { convert a old color table (3 byte entries) to a new }
  476.          { color table (4 byte entries)                        }
  477.          _lread(fh,PChar(pRgb),nNumColors * sizeof(TRGBTRIPLE));
  478.          for i := nNumColors-1 downTo 0 do
  479.          begin
  480.             rgb.rgbRed      := PRGBTRIPLE(pRgb)^[i].rgbtRed;
  481.             rgb.rgbBlue     := PRGBTRIPLE(pRgb)^[i].rgbtBlue;
  482.             rgb.rgbGreen    := PRGBTRIPLE(pRgb)^[i].rgbtGreen;
  483.             rgb.rgbReserved := 0;
  484.             pRgb^[i] := rgb;
  485.          end;
  486.       end
  487.       else _lread(fh,PChar(pRgb),nNumColors * sizeof(TRGBQUAD));
  488.    end;
  489.    if (bf.bfOffBits <> 0) then
  490.       _llseek(fh,off + bf.bfOffBits,SEEK_SET);
  491.    Result := pd;
  492. end;
  493. (************************************************************************)
  494. (*  DibSetUsage(hdib,hpal,wUsage)                                       *)
  495. (*                                                                      *)
  496. (*  Modifies the color table of the passed DIB for use with the wUsage  *)
  497. (*  parameter specifed.                                                 *)
  498. (*                                                                      *)
  499. (*  if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256     *)
  500. (*  if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB   *)
  501. (*  values in the passed palette                                        *)
  502. (************************************************************************)
  503. function DIB_SetUsage(pbi: PDIB; hPal: HPALETTE; wUsage: UINT): Boolean;
  504. type
  505.     PRGBQUAD = ^RGBQUAD;
  506.     RGBQUAD  = array[0..0] of TRGBQUAD;
  507. var
  508.    ape: array[0..255] of TPALETTEENTRY;
  509.    pRGB: PRGBQUAD;
  510.    pw: PWord;
  511.    nColors: Longint;
  512.    i: integer;
  513. begin
  514.    Result := False;
  515.    if (pbi = nil) then exit;
  516.    if (hpal = 0) then
  517.        hpal := GetStockObject(DEFAULT_PALETTE);
  518.     nColors := DIB_NumColors(pbi);
  519.     if (nColors = 3) and (DIB_Compression(pbi) = BI_BITFIELDS) then
  520.         nColors := 0;
  521.     if (nColors > 0) then
  522.     begin
  523.        pRgb := PRGBQUAD(DIB_Colors(pbi));
  524.        case wUsage of
  525.           DIB_PAL_COLORS:
  526.           begin
  527.              { Set the DIB color table to palette indexes }
  528.              pw := Pointer(pRgb);
  529.              for i := 0 to nColors-1 do
  530.              begin
  531.                 pw^ := i;
  532.                 inc(pw);
  533.              end;
  534.           end;
  535.           else
  536.           begin
  537.              { Set the DIB color table to RGBQUADS }
  538.              { DIB_RGB_COLORS:                     }
  539.              nColors := min(nColors,256);
  540.              GetPaletteEntries(hpal,0,nColors,ape);
  541.              for i := 0 to nColors-1 do
  542.              begin
  543.                 pRgb^[i].rgbRed      := ape[i].peRed;
  544.                 pRgb^[i].rgbGreen    := ape[i].peGreen;
  545.                 pRgb^[i].rgbBlue     := ape[i].peBlue;
  546.                 pRgb^[i].rgbReserved := 0;
  547.              end;
  548.           end;
  549.        end;
  550.     end;
  551.     Result := True;
  552. end;
  553. (************************************************************************)
  554. (*  Dib_Create                                                          *)
  555. (*                                                                      *)
  556. (*  Creates a new packed DIB with the given dimensions and the          *)
  557. (*  given number of bits per pixel                                      *)
  558. (*                                                                      *)
  559. (*  Orientation: -1 = TOP_DOWN, 1 = BOTTOM_UP                           *)
  560. (************************************************************************)
  561. function DIB_Create(Bits, Orientation, Width, Height: integer; AllocBits: Boolean): PDIB;
  562. var
  563.    pbi: PDIB;
  564.    i: integer;
  565.    pdw: PLongint;
  566.    dwSizeImage: Longint;
  567. begin
  568.    Result := nil;
  569.    width := Max(width,1);
  570.    height := Max(height,1);
  571.    if (Bits > 8) and (Bits <> 24) then Bits := 24;
  572.    if AllocBits then
  573.       dwSizeImage := WIDTHBYTES(Longint(Width)*Bits) * Height
  574.    else
  575.       dwSizeImage := 0;
  576.    pbi := GlobalAllocMem(sizeof(TBITMAPINFOHEADER)+dwSizeImage+256*sizeOf(TRGBQuad));
  577.    if (pbi = nil) then exit;
  578.    pbi^.biSize          := sizeof(TBITMAPINFOHEADER);
  579.    pbi^.biWidth         := Width;
  580.    pbi^.biHeight        := Height * Orientation;
  581.    pbi^.biPlanes        := 1;
  582.    pbi^.biBitCount      := Bits;
  583.    pbi^.biCompression   := BI_RGB;
  584.    pbi^.biSizeImage     := dwSizeImage;
  585.    pbi^.biXPelsPerMeter := 0;
  586.    pbi^.biYPelsPerMeter := 0;
  587.    pbi^.biClrUsed       := 0;
  588.    pbi^.biClrImportant  := 0;
  589.    if (bits = 4) then
  590.        pbi^.biClrUsed := 16
  591.    else if (bits = 8) then
  592.        pbi^.biClrUsed := 256;
  593.    pdw := PLongint(PChar(pbi)+pbi^.biSize);
  594.    for i := 0 to (pbi^.biClrUsed div 16)-1 do
  595.    begin
  596.       pdw^ := $00000000;    { 0000  black          }
  597.       inc(pdw);
  598.       pdw^ := $00800000;    { 0001  dark red       }
  599.       inc(pdw);
  600.       pdw^ := $00008000;    { 0010  dark green     }
  601.       inc(pdw);
  602.       pdw^ := $00808000;    { 0011  mustard        }
  603.       inc(pdw);
  604.       pdw^ := $00000080;    { 0100  dark blue      }
  605.       inc(pdw);
  606.       pdw^ := $00800080;    { 0101  purple         }
  607.       inc(pdw);
  608.       pdw^ := $00008080;    { 0110  dark turquoise }
  609.       inc(pdw);
  610.       pdw^ := $00C0C0C0;    { 1000  gray           }
  611.       inc(pdw);
  612.       pdw^ := $00808080;    { 0111  dark gray      }
  613.       inc(pdw);
  614.       pdw^ := $00FF0000;    { 1001  red            }
  615.       inc(pdw);
  616.       pdw^ := $0000FF00;    { 1010  green          }
  617.       inc(pdw);
  618.       pdw^ := $00FFFF00;    { 1011  yellow         }
  619.       inc(pdw);
  620.       pdw^ := $000000FF;    { 1100  blue           }
  621.       inc(pdw);
  622.       pdw^ := $00FF00FF;    { 1101  pink (magenta) }
  623.       inc(pdw);
  624.       pdw^ := $0000FFFF;    { 1110  cyan           }
  625.       inc(pdw);
  626.       pdw^ := $00FFFFFF;    { 1111  white          }
  627.    end;
  628.    Result := pbi;
  629. end;
  630. (************************************************************************)
  631. procedure xlatClut8(pb: PByte; dwSize: DWORD; xlat: PByteArray);
  632. var
  633.    dw: DWORD;
  634. begin
  635.    for dw := 0 to dwSize-1 do
  636.    begin
  637.       pb^ := xlat^[pb^];
  638.       incHuge(pb,sizeOf(pB^));
  639.    end;
  640. end;
  641. (************************************************************************)
  642. procedure xlatClut4(pb: PByte; dwSize: DWORD; xlat: PByteArray);
  643. var
  644.    dw: DWORD;
  645. begin
  646.    for dw := 0 to dwSize-1 do
  647.    begin
  648.       pb^ := xlat^[pb^ and $0F] or (xlat^[(pb^ shr 4) and $0F] shl 4);
  649.       incHuge(pb,sizeOf(pB^));
  650.    end;
  651. end;
  652. (************************************************************************)
  653. procedure xlatRle8(pb: PByte; dwSize: DWORD; xlat: PByteArray);
  654. const
  655.      RLE_ESCAPE = 0;
  656.      RLE_EOL    = 0;
  657.      RLE_EOF    = 1;
  658.      RLE_JMP    = 2;
  659. var
  660.    b,cnt: Byte;
  661.    prle: PByte;
  662. begin
  663.    prle := pb;
  664.    while True do
  665.    begin
  666.       cnt := prle^;
  667.       incHuge(prle,1);
  668.       b   := prle^;
  669.       if (cnt = RLE_ESCAPE) then
  670.       begin
  671.          incHuge(prle,1);
  672.          case b of
  673.             RLE_EOF: exit;
  674.             RLE_EOL: ;
  675.             RLE_JMP: incHuge(prle,2); { skip dX,dY }
  676.             else
  677.             begin
  678.                cnt := b;
  679.                for b := 0 to cnt-1 do
  680.                begin
  681.                   prle^ := xlat^[prle^];
  682.                   incHuge(prle,1);
  683.                end;
  684.                if (cnt and 1 > 0) then incHuge(prle,1);
  685.             end;
  686.          end;
  687.       end
  688.       else
  689.       begin
  690.          prle^:= xlat^[b];
  691.          incHuge(prle,1);
  692.       end;
  693.    end;
  694. end;
  695. (************************************************************************)
  696. procedure xlatRle4(pb: PByte; dwSize: DWORD; xlat: PByteArray);
  697. begin
  698. end;
  699. (************************************************************************)
  700. (*  DibMapToPalette(pdib, hpal)                                         *)
  701. (*                                                                      *)
  702. (*  Map the colors of the DIB, using GetNearestPaletteIndex, to         *)
  703. (*  the colors of the given palette.                                    *)
  704. (************************************************************************)
  705. procedure DIB_MapToPalette(var pbi: PDIB; hpal: HPALETTE);
  706. type
  707.     PRGBQUAD = ^RGBQUAD;
  708.     RGBQUAD  = array[0..0] of TRGBQUAD;
  709. var
  710.    pe: TPALETTEENTRY;
  711.    i: integer;
  712.    nDibColors: DWORD;
  713.    nPalColors: DWORD;
  714.    lpBits,p: PByte;
  715.    pRGB: PRGBQUAD;
  716.    xlat: array[0..255] of Byte;
  717.    SizeImage: DWORD;
  718. begin
  719.    nPalColors := 0;
  720.    if (hpal = 0) or (pbi = nil) then exit;
  721.    pRgb := PRGBQUAD(DIB_Colors(pbi));
  722.    GetObject(hpal,sizeof(Word),@nPalColors);
  723.    nDibColors := DIB_NumColors(pbi);
  724.    SizeImage := pbi^.biSizeImage;
  725.    if (SizeImage = 0) then
  726.        SizeImage := DIB_SizeImage(pbi);
  727.    { build a xlat table. from the current DIB colors to the given }
  728.    { palette.                                                     }
  729.    for i := 0 to nDibColors-1 do
  730.        xlat[i] := GetNearestPaletteIndex(hpal,RGB(pRgb^[i].rgbRed,pRgb^[i].rgbGreen,pRgb^[i].rgbBlue));
  731.    lpBits := DIB_Ptr(pbi);
  732.    pbi^.biClrUsed := nPalColors;
  733.    { re-size the DIB }
  734.    if (nPalColors > nDibColors) then
  735.    begin
  736.       GlobalReAllocPtr(pbi, pbi^.biSize + nPalColors*sizeof(TRGBQUAD) + SizeImage, 0);
  737.       p := DIB_Ptr(pbi);
  738.       GlobalMoveMem(lpBits^, p^, SizeImage);
  739.       lpBits := DIB_Ptr(pbi);
  740.    end
  741.    else if (nPalColors < nDibColors) then
  742.    begin
  743.       p := DIB_Ptr(pbi);
  744.       GlobalMoveMem(lpBits^, p^, SizeImage);
  745.       GlobalReAllocPtr(pbi, pbi^.biSize + nPalColors*sizeof(TRGBQUAD) + SizeImage, 0);
  746.       lpBits := DIB_Ptr(pbi);
  747.    end;
  748.    { translate the DIB bits }
  749.    case pbi^.biCompression of
  750.        BI_RLE8: xlatRle8(lpBits, SizeImage, @xlat);
  751.        BI_RLE4: xlatRle4(lpBits, SizeImage, @xlat);
  752.        BI_RGB:
  753.        begin
  754.           if (pbi^.biBitCount = 8) then
  755.               xlatClut8(lpBits, SizeImage, @xlat)
  756.           else
  757.               xlatClut4(lpBits, SizeImage, @xlat);
  758.        end;
  759.    end;
  760.    { Now copy the RGBs in the logical palette to the dib color table }
  761.    for i := 0 to nPalColors-1 do
  762.    begin
  763.       GetPaletteEntries(hpal,i,1,pe);
  764.       pRgb^[i].rgbRed      := pe.peRed;
  765.       pRgb^[i].rgbGreen    := pe.peGreen;
  766.       pRgb^[i].rgbBlue     := pe.peBlue;
  767.       pRgb^[i].rgbReserved := 0;
  768.    end;
  769. end;
  770. (************************************************************************)
  771. function DIB_CreatePalette(pbi: PDIB): HPALETTE;
  772. var
  773.   R,G,B: Byte;
  774.   DstPal: PLogPalette;
  775.   Colors: integer;
  776.   DC: HDC;
  777.   Focus: HWND;
  778.   SysPalSize: Integer;
  779.   Size: Longint;
  780.   i: Integer;
  781. begin
  782.    Result := 0;
  783.    Colors := DIB_NumColors(pbi);
  784.    if Colors <> 0 then
  785.    begin
  786.       Size := SizeOf(TLogPalette) + ((Colors - 1) * SizeOf(TPaletteEntry));
  787.       DstPal := GlobalAllocMem(Size);
  788.       try
  789.          with DstPal^ do
  790.          begin
  791.             palNumEntries := Colors;
  792.             palVersion := $300;
  793.             Focus := GetFocus;
  794.             DC := GetDC(Focus);
  795.             try
  796.                SysPalSize := GetDeviceCaps(DC, SIZEPALETTE);
  797.                if (Colors = 16) and (SysPalSize >= 16) then
  798.                begin
  799.                   { Ignore the disk image of the palette for 16 color }
  800.                   { bitmaps use instead the first 8 and last 8 of the }
  801.                   { current system palette                            }
  802.                   GetSystemPaletteEntries(DC, 0, 8, palPalEntry);
  803.                   i := 8;
  804.                   GetSystemPaletteEntries(DC, SysPalSize - i, i, palPalEntry[i]);
  805.                end
  806.                else
  807.                for i := 0 to Colors-1 do
  808.                with palPalEntry[i] do
  809.                begin
  810.                   { Copy the palette for all others (i.e. 256 colors) }
  811.                   peRed := PBitmapInfo(pbi)^.bmiColors[i].rgbRed;
  812.                   peGreen := PBitmapInfo(pbi)^.bmiColors[i].rgbGreen;
  813.                   peBlue := PBitmapInfo(pbi)^.bmiColors[i].rgbBlue;
  814.                   peFlags := 0;
  815.                end;
  816.             finally
  817.                ReleaseDC(Focus, DC);
  818.             end;
  819.          end;
  820.          Result := CreatePalette(DstPal^);
  821.       finally
  822.          GlobalFreePtr(DstPal);
  823.       end;
  824.    end
  825.    else if DIB_BitCount(pbi) = 24 then
  826.    begin
  827.       Colors:= 256;
  828.       Size:= SizeOf(TLogPalette) + (Colors-1) * SizeOf(TPaletteEntry);
  829.       DstPal := GlobalAllocMem(Size);
  830.       try
  831.          with DstPal^ do
  832.          begin
  833.             palVersion:= $300;
  834.             palNumEntries:= Colors;
  835.             R:= 0;
  836.             G:= 0;
  837.             B:= 0;
  838.             for i := 0 to Colors-1 do
  839.             with palPalEntry[i] do
  840.             begin
  841.                peRed:= R;
  842.                peGreen:= G;
  843.                peBlue:= B;
  844.                peFlags:= 0;
  845.                Inc(R, 32);
  846.                if (R = 0) then
  847.                begin
  848.                   Inc(G, 32);
  849.                   if (G = 0) then Inc(B, 64);
  850.                end;
  851.             end;
  852.          end;
  853.          Result:= CreatePalette(DstPal^);
  854.       finally
  855.          GlobalFreePtr(DstPal);
  856.       end;
  857.    end;
  858. end;
  859. (************************************************************************)
  860. procedure DIB_Display(pbi: PDIB; DC: HDC; aRect: TRect);
  861. var
  862.    OldPal,Pal: HPalette;
  863. begin
  864.    OldPal := 0;
  865.    Pal := DIB_CreatePalette(pbi);
  866.    if Pal <> 0 then
  867.    begin
  868.       OldPal := SelectPalette(DC, Pal, False);
  869.       RealizePalette(DC);
  870.    end;
  871.    SetStretchBltMode(DC, STRETCH_DELETESCANS);
  872.    StretchDIBits(DC, aRect.Left,aRect.Top,
  873.                      aRect.Right-aRect.Left, aRect.Bottom-aRect.Top,
  874.                      0, 0, DIB_WIDTH(pBi), DIB_Height(pBi),
  875.                      DIB_PTR(pbi), PBitmapInfo(pbI)^,
  876.                      DIB_RGB_COLORS, SRCCOPY);
  877.    if (OldPal <> 0) then
  878.    begin
  879.       SelectPalette(DC, OldPal, False);
  880.       DeleteObject(Pal);
  881.    end;
  882. end;
  883. (************************************************************************)
  884. function DIB_BitmapToDIB(Handle: HBitmap; Palette: HPalette;
  885.                          Bits, Orientation: integer): PDIB;
  886. var
  887.    lpbi: PDIB;
  888.    lpBits: PByte;
  889.    BM: TBitmap;
  890.    OldPal: HPALETTE;
  891.    DC: HDC;
  892.    Focus: HWND;
  893. begin
  894.    Result := nil;
  895.    GetObject(Handle, sizeOf(TBitmap), @BM);
  896.    lpbi := DIB_Create(Bits, Orientation, BM.bmWidth, BM.bmHeight, True);
  897.    if (lpbi <> nil) then
  898.    with lpbi^ do
  899.    begin
  900.       OldPal := 0;
  901.       Focus := GetFocus;
  902.       DC := GetDC(Focus);
  903.       try
  904.          if Palette <> 0 then
  905.          begin
  906.             OldPal := SelectPalette(DC, Palette, False);
  907.             RealizePalette(DC);
  908.          end;
  909.          lpBits := DIB_PTR(lpbi);
  910.          if GetDIBits(DC, Handle, 0, BM.bmHeight, lpBits, PBitmapInfo(lpbi)^, DIB_RGB_COLORS) = 0 then
  911.             DIB_Free(lpbi)
  912.          else
  913.             Result := lpbi;
  914.       finally
  915.          if (OldPal <> 0) then SelectPalette(DC, OldPal, False);
  916.          ReleaseDC(Focus,DC);
  917.       end;
  918.    end;
  919. end;
  920. (************************************************************************)
  921. procedure DIB_DIBToBitmap(pbi: PDIB; var Bitmap: HBitmap; var Pal: HPalette);
  922. var
  923.   Focus: HWND;
  924.   DC: HDC;
  925.   OldPal: HPALETTE;
  926. begin
  927.    OldPal := 0;
  928.    { we use the handle of the window with the focus (which, if this }
  929.    { routine is called from a menu command, will be this window) in }
  930.    { order to guarantee that the realized palette will have first   }
  931.    { priority on the system palette                                 }
  932.    Focus := GetFocus;
  933.    DC := GetDC(Focus);
  934.    try
  935.       Pal := DIB_CreatePalette(pbi);
  936.       if Pal <> 0 then
  937.       begin
  938.          OldPal := SelectPalette(DC, Pal, False);
  939.          RealizePalette(DC);
  940.       end;
  941.       Bitmap := CreateDIBitmap(DC, pbi^,  CBM_INIT, DIB_PTR(pbi),
  942.                                PBitmapInfo(pbi)^, DIB_RGB_COLORS);
  943.    finally
  944.       if (OldPal <> 0) then SelectPalette(DC, OldPal, False);
  945.       ReleaseDC(Focus, DC);
  946.    end;
  947. end;
  948. (************************************************************************)
  949. function LoadPalette(FName: string): PLOGPALETTE;
  950. Label ERROR_OPEN;
  951. var
  952.    {$IFDEF WIN32}
  953.    hmio   : HMMIO;
  954.    {$ELSE}
  955.    hmio   : THMMIO;
  956.    {$ENDIF}
  957.    ckFile : TMMCKINFO;
  958.    ckChunk: TMMCKINFO;
  959.    iSize  : integer;
  960.    iColors: integer;
  961.    pData  : Pointer;
  962.    pLogPal: PLOGPALETTE;
  963.    aBuf   : array[0..MAX_PATH] of Char;
  964. begin
  965.    Result := nil;
  966.    hmio   := 0;
  967.    pData  := nil;
  968.    if (FName <> '') then
  969.    begin
  970.       StrPCopy(aBuf,FName);
  971.       hmio := mmioOpen(aBuf, nil, MMIO_READ OR MMIO_ALLOCBUF);
  972.       if (hmio = 0) then
  973.           goto ERROR_OPEN;
  974.       { Check it's a RIFF PAL file }
  975.       ckFile.fccType := $204C4150; {'P','A','L',' '};
  976.       if (mmioDescend(hmio, @ckFile, nil, MMIO_FINDRIFF) <> 0) then
  977.           goto ERROR_OPEN;
  978.       { Find the 'data' chunk }
  979.       ckChunk.ckid := $61746164; {'d','a','t','a'};
  980.       if (mmioDescend(hmio, @ckChunk, @ckFile, MMIO_FINDCHUNK) <> 0) then
  981.           goto ERROR_OPEN;
  982.       { allocate some memory for the data chunk }
  983.       iSize := ckChunk.cksize;
  984.       pData := GlobalAllocMem(iSize);
  985.       if (pdata = nil) then
  986.           goto ERROR_OPEN;
  987.       { read the data chunk }
  988.       if (mmioRead(hmio, pdata, iSize) <> iSize) then
  989.           goto ERROR_OPEN;
  990.       { The data chunk should be a LOGPALETTE structure }
  991.       { which we can create a palette from              }
  992.       pLogPal := Pointer(pdata);
  993.       if (pLogPal^.palVersion <> $300) then
  994.           goto ERROR_OPEN;
  995.       { Get the number of entries }
  996.       iColors := pLogPal^.palNumEntries;
  997.       if (iColors <= 0) then
  998.          goto ERROR_OPEN;
  999.       Result := pLogPal;
  1000.    end;
  1001. ERROR_OPEN:
  1002.    if (hmio <> 0) then
  1003.        mmioClose(hmio,0);
  1004.    if (Result = nil) and (pData <> nil) then
  1005.        GlobalFreePtr(pData);
  1006. end;
  1007. (************************************************************************)
  1008. function SavePalette(FName: string; pLogPal: PLOGPALETTE): Boolean;
  1009. Label ERROR_SAVE;
  1010. var
  1011.    {$IFDEF WIN32}
  1012.    hmio  : HMMIO;
  1013.    {$ELSE}
  1014.    hmio  : THMMIO;
  1015.    {$ENDIF}
  1016.    ckFile: TMMCKINFO;
  1017.    ckData: TMMCKINFO;
  1018.    iSize : integer;
  1019.    aBuf  : array[0..MAX_PATH] of Char;
  1020. begin
  1021.    Result := False;
  1022.    hmio   := 0;
  1023.    if pLogPal^.palNumEntries <= 0 then
  1024.       goto ERROR_SAVE;
  1025.    StrPCopy(aBuf,FName);
  1026.    hmio := mmioOpen(aBuf, nil, MMIO_WRITE or MMIO_CREATE or MMIO_ALLOCBUF);
  1027.    if (hmio = 0) then
  1028.        goto ERROR_SAVE;
  1029.    { Create a RIFF chunk for a PAL file }
  1030.    ckFile.cksize := 0; { corrected later }
  1031.    ckFile.fccType := $204C4150; {'P','A','L',' '};
  1032.    if (mmioCreateChunk(hmio, @ckFile, MMIO_CREATERIFF) <> 0) then
  1033.        goto ERROR_SAVE;
  1034.    iSize := sizeOf(TLogPalette)+sizeOf(TPaletteEntry)*pLogPal^.palNumEntries;
  1035.    { create the data chunk }
  1036.    ckData.cksize := iSize;
  1037.    ckData.ckid := $61746164; {'d','a','t','a'};
  1038.    if (mmioCreateChunk(hmio, @ckData, 0) <> 0) then
  1039.       goto ERROR_SAVE;
  1040.    { write the data chunk }
  1041.    if (mmioWrite(hmio, PChar(pLogPal), iSize) <> iSize) then
  1042.       goto ERROR_SAVE;
  1043.    { Ascend from the data chunk which will correct the length }
  1044.    mmioAscend(hmio, @ckData, 0);
  1045.    { Ascend from the RIFF/PAL chunk }
  1046.    mmioAscend(hmio, @ckFile, 0);
  1047.    Result := True;
  1048. ERROR_SAVE:
  1049.    if (hmio <> 0) then
  1050.        mmioClose(hmio, 0);
  1051. end;
  1052. end.